2017-10-06 3 views
2

ich einen einfachen Rechner mit der Formel Grammatik entwickeln:Antlr4 unerwartet beendet Ausdrucksanalyse

grammar Formula ; 
expr : <assoc=right> expr POW expr    # pow 
    | MINUS expr        # unaryMinus 
    | PLUS expr        # unaryPlus 
    | expr PERCENT       # percent 
    | expr op=(MULTIPLICATION|DIVISION) expr # multiplyDivide 
    | expr op=(PLUS|MINUS) expr    # addSubtract 
    | ABS '(' expr ')'      # abs 
    | '|' expr '|'       # absParenthesis 
    | MAX '(' expr (',' expr)* ')'   # max 
    | MIN '(' expr (',' expr)* ')'   # min 
    | '(' expr ')'       # parenthesis 
    | NUMBER         # number 
    | '"' COLUMN '"'       # column 
    ; 

MULTIPLICATION: '*' ; 
DIVISION: '/' ; 
PLUS: '+' ; 
MINUS: '-' ; 
PERCENT: '%' ; 
POW: '^' ; 
ABS: [aA][bB][sS] ; 
MAX: [mM][aA][xX] ; 
MIN: [mM][iI][nN] ; 
NUMBER: [0-9]+('.'[0-9]+)? ; 
COLUMN: (~[\r\n"])+ ; 
WS : [ \t\r\n]+ -> skip ; 

"column a"*"column b" Eingang gibt mir folgenden Baum wie erwartet: enter image description here

Aber "column a" * "column b" Eingang unerwartet beendet Parsen: enter image description here

Was fehlt mir?

Antwort

3

Ihre WS Regel ist durch die COLUMN Regel gebrochen, die eine höhere precedence hat. Genauer gesagt, das Problem ist, dass ~[\r\n"] auch Leerzeichen entspricht.

"column a"*"column b" Lexes wie folgt: '"'COLUMN'"'MULTIPLICATION'"'COLUMN'"'

"column a" * "column b" Lexes wie folgt: '"'COLUMN'"'COLUMN'"'COLUMN'"'

Ja "space star Raum" wurde alsgelextToken, denn so funktionieren ANTLR-Lexer-Regeln: längere Token-Übereinstimmungen erhalten Priorität.

Wie Sie sehen können, dieses Token Strom tut nicht Spiel der expr Regel als Ganzes, so expr Matches so viel, wie es könnte, die '"'COLUMN'"' ist.

Eine Lexer-Regel mit nur einer negativen Regel zu deklarieren, wie Sie es getan haben, ist immer eine schlechte Idee. Und getrennte Tokens für '"' fühlen sich auch nicht richtig für mich.

Was Sie getan haben sollten, ist die Zitate in der COLUMN Regel enthalten sein, da sie logisch als Teil des Tokens sind:

COLUMN: '"' (~["\r\n])* '"'; 

dann die Standalone-Zitate aus Ihrer Parser-Regel entfernen. Sie können den Text später entweder aufheben, wenn Sie den Syntaxbaum verarbeiten, oder die Token-Emissionslogik im Lexer ändern, um den zugrunde liegenden Wert des Tokens zu ändern.

Und um zu ignorieren nicht eingegeben Hinter, eine weitere Regel hinzufügen, die Sie sicher, dass die gesamte Eingabe verbraucht haben machen:

formula: expr EOF; 

Dann diese Regel als Entry-Regel verwenden, anstatt expr wenn Ihr Parser aufrufen .

+0

Vielen Dank für die ausführliche Erklärung! – tiktak

3

Aber "Spalte ein" * "Spalte b" -Eingang unerwartet beendet

Parsen Wenn ich Ihre Grammatik mit ANTLR 4 laufen.6, es stoppt nicht das Parsen, es analysiert die gesamte Datei und zeigt in rosa, was der Parser nicht mithalten können:

Die Punkte stehen für Räume.

Und es ist eine wichtige Fehlermeldung:

line 1:10 mismatched input ' * ' expecting {<EOF>, '*', '/', '+', '-', '%', '^'} 

Wie ich here erklären, sobald Sie eine „nicht übereinstimmen“ Fehler haben, fügen -tokens zu grun.

Mit "column a"*"column b":

$ grun Formula expr -tokens -diagnostics t1.text 
[@0,0:0='"',<'"'>,1:0] 
[@1,1:8='column a',<COLUMN>,1:1] 
[@2,9:9='"',<'"'>,1:9] 
[@3,10:10='*',<'*'>,1:10] 
[@4,11:11='"',<'"'>,1:11] 
[@5,12:19='column b',<COLUMN>,1:12] 
[@6,20:20='"',<'"'>,1:20] 
[@7,22:21='<EOF>',<EOF>,2:0] 

Mit "column a" * "column b":

$ grun Formula expr -tokens -diagnostics t2.text 
[@0,0:0='"',<'"'>,1:0] 
[@1,1:8='column a',<COLUMN>,1:1] 
[@2,9:9='"',<'"'>,1:9] 
[@3,10:12=' * ',<COLUMN>,1:10] 
[@4,13:13='"',<'"'>,1:13] 
[@5,14:21='column b',<COLUMN>,1:14] 
[@6,22:22='"',<'"'>,1:22] 
[@7,24:23='<EOF>',<EOF>,2:0] 
line 1:10 mismatched input ' * ' expecting {<EOF>, '*', '/', '+', '-', '%', '^'} 

Sie sofort sehen, dass " * " als COLUMN interpretiert wird.

extraneous input

ordering

greedy

ambiguity

expression

:

Viele Fragen über die Eingabe mit Lexer Regeln passend haben in den letzten Tagen gefragt worden,

So oft hat Lucas eine falsche Frage gestellt, nur um eine Antwort zu geben, die all das problematische zusammenfasst: disambiguate.

Verwandte Themen