2017-04-14 1 views
0

Kürzlich versuche ich mein Projekt von Antlr3 zu Antlr4 zu verbessern. Aber nach der Änderung in der Grammatikdatei scheint es, dass die zuvor funktionierenden Gleichungen nicht mehr funktionieren. Ich bin neu in Antlr4 und kann nicht verstehen, ob meine Veränderung etwas kaputt gemacht hat oder nicht.Warum Parsen fehlgeschlagen nach dem Upgrade von Antlr 3 auf Antlr 4?

Hier ist meine ursprüngliche Grammatikdatei:

grammar equation; 
options { 
    language=CSharp2; 
    output=AST; 
    ASTLabelType=CommonTree; 
} 

tokens { 
    VARIABLE; 
    CONSTANT; 
    EXPR; 
    PAREXPR; 
    EQUATION; 
    UNARYEXPR; 
    FUNCTION; 
    BINARYOP; 
    LIST; 
} 


equationset: equation* EOF!; 
equation: variable ASSIGN expression -> ^(EQUATION variable expression) 
    ; 

parExpression 
    : LPAREN expression RPAREN -> ^(PAREXPR expression) 
    ; 

expression 
    : conditionalexpression -> ^(EXPR conditionalexpression) 
    ; 

conditionalexpression 
    : orExpression 
    ; 

orExpression 
    : andExpression (OR^ andExpression)* 
    ; 

andExpression 
    : comparisonExpression (AND^ comparisonExpression)*; 


comparisonExpression: 
    additiveExpression ((EQ^ | NE^ | LTE^ | GTE^ | LT^ | GT^) additiveExpression)*; 


additiveExpression 
    : multiplicativeExpression ((PLUS^ | MINUS^) multiplicativeExpression)* 
    ; 

multiplicativeExpression 
    : unaryExpression ((TIMES^ | DIVIDE^) unaryExpression)* 
    ; 

unaryExpression 
    : NOT unaryExpression -> ^(UNARYEXPR NOT unaryExpression) 
    | MINUS unaryExpression -> ^(UNARYEXPR MINUS unaryExpression) 
    | exponentexpression; 

exponentexpression 
    : primary (CARET^ primary)*; 

primary : parExpression | constant | booleantok | variable | function; 

numeric:  INTEGER | REAL; 
constant:  STRING -> ^(CONSTANT STRING) | numeric -> ^(CONSTANT numeric); 
booleantok : BOOLEAN -> ^(BOOLEAN); 
scopedidentifier 
    : (IDENTIFIER DOT)* IDENTIFIER -> IDENTIFIER+; 
function 
    : scopedidentifier LPAREN argumentlist RPAREN -> ^(FUNCTION scopedidentifier argumentlist); 
variable: scopedidentifier -> ^(VARIABLE scopedidentifier); 

argumentlist: (expression) ? (COMMA! expression)*; 

WS : (' '|'\r'|'\n'|'\t')+ {$channel=HIDDEN;}; 

COMMENT : '/*' .* '*/' {$channel=HIDDEN;}; 

LINE_COMMENT : '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}; 

STRING: (('\"') ((~('\"')))* ('\"'))+; 

fragment ALPHA: 'a'..'z'|'_'; 
fragment DIGIT: '0'..'9'; 
fragment ALNUM: ALPHA|DIGIT; 

EQ : '=='; 
ASSIGN : '='; 
NE : '!=' | '<>'; 
OR : 'or' | '||'; 
AND : 'and' | '&&'; 
NOT : '!'|'not'; 
LTE : '<='; 
GTE : '>='; 
LT : '<'; 
GT : '>'; 
TIMES : '*'; 
DIVIDE : '/'; 

BOOLEAN : 'true' | 'false'; 

IDENTIFIER: ALPHA (ALNUM)* | ('[' (~(']'))+ ']') ; 

REAL: DIGIT* DOT DIGIT+ ('e' (PLUS | MINUS)? DIGIT+)?; 
INTEGER: DIGIT+; 


PLUS : '+'; 
MINUS : '-'; 
COMMA : ','; 
RPAREN : ')'; 
LPAREN : '('; 
DOT : '.'; 
CARET : '^'; 

Und hier ist das, was ich nach meiner Änderungen haben:

grammar equation; 
options { 

} 

tokens { 
    VARIABLE; 
    CONSTANT; 
    EXPR; 
    PAREXPR; 
    EQUATION; 
    UNARYEXPR; 
    FUNCTION; 
    BINARYOP; 
    LIST; 
} 


equationset: equation* EOF; 
equation: variable ASSIGN expression 
    ; 

parExpression 
    : LPAREN expression RPAREN 
    ; 

expression 
    : conditionalexpression 
    ; 

conditionalexpression 
    : orExpression 
    ; 

orExpression 
    : andExpression (OR andExpression)* 
    ; 

andExpression 
    : comparisonExpression (AND comparisonExpression)*; 


comparisonExpression: 
    additiveExpression ((EQ | NE | LTE | GTE | LT | GT) additiveExpression)*; 


additiveExpression 
    : multiplicativeExpression ((PLUS | MINUS) multiplicativeExpression)* 
    ; 

multiplicativeExpression 
    : unaryExpression ((TIMES | DIVIDE) unaryExpression)* 
    ; 

unaryExpression 
    : NOT unaryExpression 
    | MINUS unaryExpression 
    | exponentexpression; 

exponentexpression 
    : primary (CARET primary)*; 

primary : parExpression | constant | booleantok | variable | function; 

numeric:  INTEGER | REAL; 
constant:  STRING | numeric; 
booleantok : BOOLEAN; 
scopedidentifier 
    : (IDENTIFIER DOT)* IDENTIFIER; 
function 
    : scopedidentifier LPAREN argumentlist RPAREN; 
variable: scopedidentifier; 

argumentlist: (expression) ? (COMMA expression)*; 

WS : (' '|'\r'|'\n'|'\t')+ ->channel(HIDDEN); 

COMMENT : '/*' .* '*/' ->channel(HIDDEN); 

LINE_COMMENT : '//' ~('\n'|'\r')* '\r'? '\n' ->channel(HIDDEN); 

STRING: (('\"') ((~('\"')))* ('\"'))+; 

fragment ALPHA: 'a'..'z'|'_'; 
fragment DIGIT: '0'..'9'; 
fragment ALNUM: ALPHA|DIGIT; 

EQ : '=='; 
ASSIGN : '='; 
NE : '!=' | '<>'; 
OR : 'or' | '||'; 
AND : 'and' | '&&'; 
NOT : '!'|'not'; 
LTE : '<='; 
GTE : '>='; 
LT : '<'; 
GT : '>'; 
TIMES : '*'; 
DIVIDE : '/'; 

BOOLEAN : 'true' | 'false'; 

IDENTIFIER: ALPHA (ALNUM)* | ('[' (~(']'))+ ']') ; 

REAL: DIGIT* DOT DIGIT+ ('e' (PLUS | MINUS)? DIGIT+)?; 
INTEGER: DIGIT+; 


PLUS : '+'; 
MINUS : '-'; 
COMMA : ','; 
RPAREN : ')'; 
LPAREN : '('; 
DOT : '.'; 
CARET : '^'; 

Eine Probe Gleichung, die ich zu analysieren, ich versuche, (welche OK bevor arbeitete) ist:

[a].[b] = 1.76 * [Product_DC].[PDC_Inbound_Pallets] * if(product_dc.[PDC_DC] =="US84",1,0) 

Vielen Dank im Voraus.

+0

Was ist der Fehler, den Sie bekommen? – Raven

Antwort

0
  • Tokens sollte ; mit Komma , nicht Semikolon aufgeführt werden. Siehe auch Token Section Absatz im offiziellen Dokument.
  • Seit ANTLR 4.7 Backslash ist nicht für das doppelte Anführungszeichen erforderlich. STRING: (('\"') ((~('\"')))* ('\"'))+; sollte in STRING: ('"' ~'"'* '"')+; umgeschrieben werden.
  • Sie haben das Fragezeichen im mehrzeiligen Kommentar-Token für nicht-gieriges Matching verpasst: '/*' .* '*/' ->'/*' .*? '*/'.

So sieht die feste Grammatik wie folgt aus:

grammar equation; 

options { 

} 

tokens { 
    VARIABLE, 
    CONSTANT, 
    EXPR, 
    PAREXPR, 
    EQUATION, 
    UNARYEXPR, 
    FUNCTION, 
    BINARYOP, 
    LIST 
} 


equationset: equation* EOF; 
equation: variable ASSIGN expression 
    ; 

parExpression 
    : LPAREN expression RPAREN 
    ; 

expression 
    : conditionalexpression 
    ; 

conditionalexpression 
    : orExpression 
    ; 

orExpression 
    : andExpression (OR andExpression)* 
    ; 

andExpression 
    : comparisonExpression (AND comparisonExpression)*; 


comparisonExpression: 
    additiveExpression ((EQ | NE | LTE | GTE | LT | GT) additiveExpression)*; 


additiveExpression 
    : multiplicativeExpression ((PLUS | MINUS) multiplicativeExpression)* 
    ; 

multiplicativeExpression 
    : unaryExpression ((TIMES | DIVIDE) unaryExpression)* 
    ; 

unaryExpression 
    : NOT unaryExpression 
    | MINUS unaryExpression 
    | exponentexpression; 

exponentexpression 
    : primary (CARET primary)*; 

primary : parExpression | constant | booleantok | variable | function; 

numeric:  INTEGER | REAL; 
constant:  STRING | numeric; 
booleantok : BOOLEAN; 
scopedidentifier 
    : (IDENTIFIER DOT)* IDENTIFIER; 
function 
    : scopedidentifier LPAREN argumentlist RPAREN; 
variable: scopedidentifier; 

argumentlist: (expression) ? (COMMA expression)*; 

WS : (' '|'\r'|'\n'|'\t')+ ->channel(HIDDEN); 

COMMENT : '/*' .*? '*/' -> channel(HIDDEN); 

LINE_COMMENT : '//' ~('\n'|'\r')* '\r'? '\n' ->channel(HIDDEN); 

STRING: ('"' ~'"'* '"')+; 

fragment ALPHA: 'a'..'z'|'_'; 
fragment DIGIT: '0'..'9'; 
fragment ALNUM: ALPHA|DIGIT; 

EQ : '=='; 
ASSIGN : '='; 
NE : '!=' | '<>'; 
OR : 'or' | '||'; 
AND : 'and' | '&&'; 
NOT : '!'|'not'; 
LTE : '<='; 
GTE : '>='; 
LT : '<'; 
GT : '>'; 
TIMES : '*'; 
DIVIDE : '/'; 

BOOLEAN : 'true' | 'false'; 

IDENTIFIER: ALPHA (ALNUM)* | ('[' (~(']'))+ ']') ; 

REAL: DIGIT* DOT DIGIT+ ('e' (PLUS | MINUS)? DIGIT+)?; 
INTEGER: DIGIT+; 


PLUS : '+'; 
MINUS : '-'; 
COMMA : ','; 
RPAREN : ')'; 
LPAREN : '('; 
DOT : '.'; 
CARET : '^'; 
+0

War es wirklich notwendig, doppelte Anführungszeichen zu vermeiden, wenn sie in einem String-Literal vor 4.7 verwendet wurden? Ich kann mich nicht erinnern, dass ich jemals das gebraucht habe ... –

+0

Es gibt keine solche Notwendigkeit. Aber ANTLR 4.7 warnt nur davor. –