Анализатор Antlr4 неправильно анализирует оператор переназначения - PullRequest
0 голосов
/ 25 марта 2019

Я создавал синтаксический анализатор грамматики с помощью Antlr4 и хотел добавить переназначение переменной (без необходимости объявления новой переменной)

Я пытался изменить выражение переназначения на выражение, но это ничего не изменило

Вот сокращенная версия моей грамматики:

grammar MyLanguage;

program: statement* EOF;

statement
    : expression EOC
    | variable EOC 
    | IDENTIFIER ASSIGNMENT expression EOC
    ;

variable: type IDENTIFIER (ASSIGNMENT expression)?;

expression
    : STRING
    | INTEGER
    | IDENTIFIER
    | expression MATH expression
    | ('+' | '-') expression
    ;

MATH:       '+' | '-' | '*' | '/' | '%' | '//' | '**';
ASSIGNMENT: MATH? '=';
EOC:        ';';
WHITESPACE: [ \t\r\n]+ -> skip;

STRING:     '"' (~[\u0000-\u0008\u0010-\u001F"] | [\t])* '"' | '\'' (~[\u0000-\u0008\u0010-\u001F'] | [\t])* '\'';
INTEGER:    '0' | ('+' | '-')? [1-9][0-9]*;
IDENTIFIER: [a-zA-Z_][a-zA-Z0-9_]*;

type:      'str';

если что-то еще может иметь отношение, пожалуйста, спросите

поэтому я попытался разобрать

str test = "empty";
test = "not empty";

, который работал, но когда я пытался (часть функции fibbionaci)

temp = n1;
n1 = n1 + n2;
n2 = temp;

он получил ошибку и проанализировал ее как

temp = n1; //statement
n1 = n1 //statement - <missing ';'>
+n2; //statement
n2 = temp; //statement

1 Ответ

1 голос
/ 25 марта 2019

Ваша проблема не имеет ничего общего с операторами присваивания.Дополнения просто не работают вообще - являются ли они частью задания или нет.Таким образом, самый простой ввод для получения ошибки будет x+y;.Если вы распечатаете поток токенов для этого ввода (например, используя grun с опцией -tokens), вы получите следующий вывод:

[@0,0:0='x',<IDENTIFIER>,1:0]
[@1,1:1='+',<'+'>,1:1]
[@2,2:2='y',<IDENTIFIER>,1:2]
[@3,3:3=';',<';'>,1:3]
[@4,4:3='<EOF>',<EOF>,1:4]
line 1:1 no viable alternative at input 'x+'

Теперь сравните это с x*y;, чтоотлично работает:

[@0,0:0='x',<IDENTIFIER>,1:0]
[@1,1:1='*',<MATH>,1:1]
[@2,2:2='y',<IDENTIFIER>,1:2]
[@3,3:3=';',<';'>,1:3]
[@4,4:3='<EOF>',<EOF>,1:4]

Важным отличием здесь является то, что * распознается как токен MATH, а + - нет.Вместо этого он распознается как токен '+'.

Это происходит потому, что в альтернативном | ('+' | '-') expression вы ввели отдельный тип токена '+''-').Поэтому, когда лексер видит +, он генерирует токен '+', а не MATH, потому что строковые литералы в правилах синтаксического анализатора имеют приоритет над именованными правилами лексера.

Если вы включите MATH ввместо правила синтаксического анализатора math (или, возможно, mathOperator) все операторы будут литералами, и проблема исчезнет.Тем не менее, вам, вероятно, не нужно одно правило для всех математических операторов, потому что это не дает вам желаемого приоритета, но это другая проблема.

PS: что-то вроде x+1 все еще выиграно 'не работает, потому что он будет видеть +1 как один INTEGER токен.Это можно исправить, удалив ведущие + и - из правила INTEGER (таким образом x = -2 будет проанализирован как унарный минус, примененный к целому числу 2 вместо целого числа -2,но это не проблема).

...