Bonjour,
Je suis en train d'essayer de parser du code source Caml à l'aide de Boost::Spirit. (L'objectif étant à terme de convertir le code Caml en métaprog C++ à l'aide de boost::mpl)
J'ai eu l'occasion de voir cette idée que très récemment, donc je ne suis que sur le début...
Pour le moment, je commence par la phase où il y a pas trop besoin de réfléchir: parser le Caml...
Globalement, le parsage avec boost:spirit marche pas trop mal. J'ai juste 3 sourcis:
(Le code source est dispo là: http://www.mediafire.com/?gdcyuwwx1mm )
* Le premier est le suivant: je comprend pas bien pourquoi, mais j'ai des erreurs bizare sous gcc 4.4.1-1 sous Arch Linux alors que sous Win / VS 9.0 SP 1 pas de souci
Citation :
....
Parser.hpp:379:79: attention : caractère(s) nul(s) ignoré(s)
Parser.hpp:380:1: attention : caractère(s) nul(s) ignoré(s)
Parser.hpp:381:1: attention : caractère(s) nul(s) ignoré(s)
Parser.hpp:382:1: attention : caractère(s) nul(s) ignoré(s)
Parser.hpp:383:1: attention : caractère(s) nul(s) ignoré(s)
Parser.hpp:383:3: attention : caractère(s) nul(s) ignoré(s)
Parser.hpp:384:1: attention : caractère(s) nul(s) ignoré(s)
Parser.hpp:385:1: attention : caractère(s) nul(s) ignoré(s)
Parser.hpp:386:1: attention : caractère(s) nul(s) ignoré(s)
Parser.hpp:387:1: attention : caractère(s) nul(s) ignoré(s)
In file included from main.cpp:2:
Parser.hpp:15: erreur: ‘v’ does not name a type
Parser.hpp:29: erreur: expected unqualified-id before ‘/’ token
In file included from main.cpp:2:
Parser.hpp:37: erreur: ‘t’ does not name a type
|
Et les lignes désignées par le compilateur me semblent vraiment sans aucun problèmes... (par ex: la 15 c'est juste un commentaire )
* mon deuxième souci est sur le parsage des chaines de caractères pour les noms de fonctions et variable...
Basiquement l'expression régulière est
Code :
- ([a...z] | '_' )([a...z] | '_' | [0-9] | ''' )*
|
soit dans boost::spirit
Code :
- +( letter | ch_p('_') ) >> *(letter | digit_p | ch_p('_') | ch_p('\''))
- letter = letterUpCase | letterLowCase;
- letterUpCase = range<>('A','Z');
- letterLowCase = range<>('a','z');
|
Mais ce que je comprend pas c'est qu'il a l'air de me prendre aussi les espaces... du coup, si je rentre un truc du genre:
il me parse toute la chaine "test as test2" comme le nom d'une variable
Dans la doc de Spirit, il y a des info pour ne pas tenir compte des espaces dans des cas particulier (comme pour gérer les nombres du type "12 000" ) Mais j'ai rien trouvé pour résoudre mon problème... Si vous avez une idée...
* Le troisième souci que j'ai est au niveau de certaines expressions du type:
Code :
- expr -> constante
- | variable
- | "(" expr " )"
- | "begin" expr "end"
- | "if" expr "then" expr ["else" expr]
- ...
- | expr operateur expr
- | expr (expr)+
- | expr ; expr
- | expr "::" expr
|
Le souci étant sur la deuxième partie: avec Spirit, ce type de cas conduit sur de la récursion infinie. Il est nécessaire d'avoir autre chose que l'expression en première partie. Du coup, je me dit qu'il fraudait faire quelque chose du genre:
Code :
- expr -> constante
- | variable
- | "(" expr " )"
- | "begin" expr "end"
- | "if" expr "then" expr ["else" expr]
- ...
- | variable operateur expr
- | "(" expr " )" operateur expr
- | "begin" expr "end" operateur expr
- | "if" expr "then" expr ["else" expr] operateur expr
- ...
|
Mais comme j'ai pas envie de me taper les !4 * n expressions... j'avais pensé à ça: (en Spirit)
Code :
- startExpr = longest_d[
- constant
- | value_name
- | "(" >> expr >> " )"
- | "begin" >> expr >> "end"
- | "[" >> expr >> *( ";" >> expr) >> "]"
- | "if" >> expr >> "then" >> expr >> !("else" >> expr)
- | "match" >> expr >> "with" >> pattern_matching
- | "let" >> !(str_p("rec" )) >> let_binding >> "in" >> expr
- | "function" >> pattern_matching
- | "fun" >> multiple_matching
- ];
- startExpr2 = longest_d[
- startExpr
- | startExpr >> "::" >> expr
- | startExpr >> +(expr)
- | startExpr >> ";" >> expr
- | startExpr >> infix_op >> expr
- ];
- expr = longest_d[
- startExpr2
- | startExpr2 >> "::" >> expr
- | startExpr2 >> +(expr)
- | startExpr2 >> ";" >> expr
- | startExpr2 >> infix_op >> expr
- ];
|
Mais cela n'a pas l'air de bien marcher: quand j'associe une règle a exécuter lors de la reconnaissance des constantes pour vérifier une expression du type "3 + 4 ;;" J'ai l'impression de voir toutes les tentative d'association qu'il a fait. Du coup, il m'appelle plein de fois la règle associé à la reconnaissance du 3 et 4... (un exemple de ce pb est directement visible dans le code source complet posté ci dessus)
(la solution où je tapais tout avait l'air de marcher... mais bon, c'est pas vraiment une solution... Je ferai comment le jours où j'aurai 7 règles récursive comme ceci..)
Bon globalement à part la question des noms de variables je suis capable de vérifier si ce qui est tapé vérifie la grammaire de Caml. Mais je me demandais si vous auriez une idée pour résoudre mes derniers problèmes...
Merci!
Message édité par Amonchakai le 09-09-2009 à 14:10:34