2017-10-06 6 views
2

Je inopinément je développe une calculatrice simple avec la grammaire de formule:Antlr4 arrête l'analyse syntaxique expression

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 ; 

entrée "column a"*"column b" me donne l'arbre suivant comme prévu: enter image description here

Mais l'entrée "column a" * "column b" arrête de façon inattendue l'analyse syntaxique: enter image description here

Qu'est-ce qui me manque?

Répondre

3

La règle WS est rompue par la règle COLUMN, qui a une valeur supérieure à precedence. Plus précisément, le problème est que ~[\r\n"] correspond également aux caractères d'espace.

"column a"*"column b" Lexes comme suit: '"'COLUMN'"'MULTIPLICATION'"'COLUMN'"'

"column a" * "column b" Lexes comme suit: '"'COLUMN'"'COLUMN'"'COLUMN'"'

Oui, "space space star" se sont lexed comme COLUMN jeton parce que c'est ainsi que fonctionnent les règles ANTLR lexer: les correspondances plus longues sont prioritaires.

Comme vous pouvez le voir, ce flux jeton ne pas match de la règle expr dans son ensemble, donc expr matchs autant qu'il pouvait, ce qui est '"'COLUMN'"'.

Déclarer une règle lexer avec seulement une règle négative comme vous l'avez fait est toujours une mauvaise idée. Et avoir des jetons séparés ne me convient pas non plus.

Qu'est-ce que vous auriez dû faire est d'inclure les citations dans la règle COLUMN car ils sont logiquement partie du jeton:

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

Ensuite, retirer les citations autonomes de votre règle de l'analyseur. Vous pouvez soit débloquer le texte plus tard lorsque vous allez traiter l'arbre d'analyse, soit changer la logique d'émission de jeton dans le lexeur pour changer la valeur sous-jacente du jeton.

Et pour pas ignorer l'entrée arrière, ajouter une autre règle qui fera en sorte que vous avez consommé toute entrée:

formula: expr EOF; 

Ensuite, utilisez cette règle comme règle d'entrée au lieu de expr lorsque vous appelez votre analyseur .

+0

Merci beaucoup pour les explications détaillées! – tiktak

3

Mais "colonne un" * "colonne b" entrée arrête de façon inattendue l'analyse syntaxique

Si je cours avec votre grammaire ANTLR 4.6, il ne s'arrête pas l'analyse syntaxique, il analyse le fichier entier et affiche en rose ce que l'analyseur ne peut pas correspondre:

Les points représentent des espaces.

Et il y a un important message d'erreur:

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

Comme je l'explique here dès que vous avez une erreur "ne correspondent pas", ajouter -tokens à Grun.

Avec "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] 

Avec "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>, '*', '/', '+', '-', '%', '^'} 

vous voyez immédiatement que " * " est interprété comme COLUMN.

De nombreuses questions sur l'entrée correspondant à des règles ont été posées analyseurs lexicaux ces derniers jours:

extraneous input

ordering

greedy

ambiguity

expression

Tant de fois que Lucas a posté une fausse question juste pour faire une réponse qui résume tout ce problème: disambiguate.