ANTLR grammatica per le espressioni
-
12-09-2019 - |
Domanda
Sto cercando di implementare una gestione espressione di grammatica (che si occupa di parentesi nidificate e roba del genere). Ho il seguente fino ad ora, ma non posso affrontare alcuni casi (casi di successo / insuccesso compaiono dopo il seguente blocco di codice). Qualcuno sa cosa sta succedendo?
Nota: Il varname + = e varname = solo roba alcune cose aiutante sono ulteriore generazione AST in xtext. Non preoccuparti di loro per ora.
...
NilExpression returns Expression:
'nil';
FalseExpression returns Expression:
'false';
TrueExpression returns Expression:
'true';
NumberExpression returns Expression:
value=Number;
StringExpression returns Expression:
value=STRING; //EllipsesExpression: '...';
//FunctionExpression: function=function; //don't allow random functions
UnaryExpression:
op=unop ('(' expr=Expression ')')|expr=Expression;
BinaryExpression:
'or'? AndOp; //or op
AndOp:
'and'? ComparisonOp;
ComparisonOp:
('>'|'<'|'>='|'<='|'=='|'~=')? ConcatOp;
ConcatOp:
'..'? AddSubOp;
AddSubOp:
('+' '-')? MultDivOp;
MultDivOp:
('*' '/')? ExpOp;
ExpOp:
'^'? (('(' expr=Expression ')')|expr=Expression);
ExprSideOne : Variable|NilExpression|FalseExpression|TrueExpression|
NumberExpression|StringExpression|UnaryExpression;
Expression:
(
'('
expression1=ExprSideOne expression2+=BinaryExpression*
')'
)
|
( expression1=ExprSideOne expression2+=BinaryExpression* )
;
...
Ed ecco l'elenco dei analizza / fallisce:
c = ((b)); //fails
c = ((a not b)); //fails
c = b; //parses
d = (b); //parses
Soluzione
Cosa sta succedendo è che la vostra espressione / Espressioni supportano parentesi singoli ma non multipli parentesi (come avete concluso). Non ho ANTLR specifica esperienza, ma ho lavorato con JavaCC che condivide molti concetti simili (ho scritto una grammatica per Prolog ... non chiedere).
Per gestire parentesi nidificate, è in genere necessario qualcosa di simile a:
ParenthesisExpression: '(' (ParenthesisExpression | Expression) ')';
Ciò significa che l'espressione o è avvolto in parentesi o è solo un'espressione grezzo. Per quanto riguarda come le offerte AST con questo, un ParenthesisExpression 'è un' espressione, in modo che possa essere rappresentato come una sottoclasse o di un'implementazione di (se espressione è un'interfaccia / classe astratta di sorta).
Altri suggerimenti
Sfruttate l'^
posto dopo il token / nome della regola è molto utile per la definizione delle espressioni.
expression : e1 (OR^ e1)* ;
e1 : e2 (AND^ e2)*;
e2 : e3 (PIPE^ e3)*;
e3 : e4 (ANDSYMB^ e4)*;
e4 : e5 ((EQUAL^|NOTEQUAL^) e5)*;
e5 : e6 ((LESS^|GREATER^) e6)*;
e6 : e7 ((PLUS^|MINUS^) e7)* ;
e7 : e8 ((STAR^|SLASH^) e8)* ;
e8 : e9 (NEW^ ID LPAREN RPAREN)*;
e9 : (NOT^)? e10;
e10 : e11 | call_def;
e11 : constant
| '(' expression ')' -> expression;
Ho usato questo grammatica per semplici espressioni: http: //fisheye2.atlassian .com / browse / ~ grezzo, r = 5175 / antlr-examples / C / polydiff / Poly.g
Ho anche usato la grammatica contiene in questo progetto per le espressioni più complesse: http://www.codeproject.com/KB/recipes/sota_expression_evaluator.aspx