2014-04-20 2 views
1

J'ai écrit un lexeur et un analyseur pour analyser des instructions d'algèbre linéaire. Chaque instruction consiste en une ou plusieurs expressions suivies d'une ou de plusieurs déclarations. J'utilise menhir et OCaml pour écrire le lexer et l'analyseur. Par exemple: Ax = b, où A est inversible.Multiplication de surcharge en utilisant menhir et OCaml

Cela devrait être lu comme A * x = b, (A, inversible)

Dans une expression tous doivent être soit ids un symbole en majuscules ou en minuscules. Je voudrais surcharger l'opérateur de multiplication afin que l'utilisateur n'ait pas à taper le symbole '*'.

Cependant, comme le lexeur doit également être capable de lire des chaînes (comme "inversible" dans ce cas), la partie "Axe" de l'expression est envoyée à l'analyseur sous la forme d'une chaîne. Cela provoque une erreur de l'analyseur, car aucune chaîne ne doit être rencontrée dans la partie expression de l'instruction.

Voici l'idée de base de la grammaire

stmt := 
    | expr "." 
    | decl "." 
    | expr "," decl "." 

expr := 
    | term 
    | unop expr 
    | expr binop expr 

term := 
    | <int> num 
    | <char> id 
    | "(" expr ")" 

decl := 
    | id "is" kinds 

kinds := 
    | <string> kind 
    | kind "and" kinds 

Est-il possible de séparer les caractères individuels et indiquer à l'analyseur qu'ils doivent être traités comme la multiplication? Existe-t-il un moyen de modifier le lexeur pour qu'il soit suffisamment intelligent pour savoir que tous les groupes de caractères avant une virgule sont des identifiants et que tous les groupes après doivent être traités comme des chaînes?

Répondre

3

Il me semble que vous avez deux problèmes:

  1. Vous voulez que votre lexer pour traiter des séquences de caractères différemment dans différents endroits.

  2. Vous souhaitez que la multiplication soit indiquée par des expressions adjacentes (aucun opérateur entre les deux).

Le premier problème que je voudrais aborder dans le lexer.

Une question est pourquoi vous dites que vous devez utiliser des chaînes. Cela implique qu'il y a un ensemble de choses complètement ouvertes que vous pouvez dire. C'est peut-être vrai, mais si vous pouvez vous limiter à un petit nombre, vous pouvez utiliser des mots-clés plutôt que des chaînes. Par exemple, invertible serait un mot-clé. Si vous voulez vraiment autoriser n'importe quelle chaîne dans de tels endroits, il est toujours possible de pirater un lexer pour qu'il conserve un état décrivant ce qu'il a vu, et regarde vers l'avenir pour voir ce qui va arriver. Si vous n'êtes pas obligé d'adhérer à une grammaire prédéfinie, vous pouvez ajuster votre grammaire pour vous faciliter la tâche. (Par exemple, vous pouvez utiliser des virgules pour un seul but.)

Pour le deuxième problème, je dirais que vous devez ajouter la contiguïté à votre grammaire. C'est-à-dire, votre grammaire a besoin d'une règle qui dit quelque chose comme term := term term. Je suppose qu'il est difficile de faire fonctionner correctement ceci, mais cela fonctionne dans OCaml (où les expressions adjacentes représentent l'application de la fonction) et dans awk (où les expressions adjacentes représentent la concaténation de chaîne).

+0

La solution que mon partenaire et moi avons trouvée consistait à définir des mots-clés dans le lexeur de telle sorte qu'ils ne puissent pas faire partie d'un mot plus grand. Donc le "in" dans "invertible" ne serait pas enregistré comme un mot-clé (puisqu'il a un caractère qui le suit). Existe-t-il un moyen standard de le faire? –