2016-12-23 4 views
0

в небольшом тесте-парсере Я только что написал, я столкнулся с какой-то странной проблемой, которую я не совсем понимаю.Antsr4 разбор непоследовательности

Зачистка его вплоть до мельчайших примера, показывающего проблемы, давайте начнем со следующей грамматикой:

Testing.g4:

grammar Testing; 

cscript       // This is the construct I shortened 
    : (statement_list)* ; 

statement_list 
    : statement ';' statement_list? 
    | block 
    ; 

statement 
    : assignment_statement 
    ; 

block : '{' statement_list? '}' ; 

expression 
    : left=expression op=('*'|'/') right=expression    # arithmeticExpression 
    | left=expression op=('+'|'-') right=expression    # arithmeticExpression 
    | left=expression op=Comparison_operator right=expression # comparisonExpression 
    | ID               # variableValueExpression 
    | constant             # ignore // will be executed with the rule name 
    ; 

assignment_statement 
    : ID op=Assignment_operator expression 
    ; 

constant 
    : INT 
    | REAL; 

Assignment_operator : ('=' | '+=' | '-=') ; 

Comparison_operator : ('<' | '>' | '==' | '!=') ; 

Comment : '//' .*? '\n' -> skip; 

fragment NUM : [0-9]; 

INT : NUM+; 
REAL 
    : NUM* '.' NUM+ 
    | '.' NUM+ 
    | INT 
    ; 

ID : [a-zA-Z_] [a-zA-Z_0-9]*; 

WS : [ \t\r\n]+ -> skip; 

Используя вход

z = x + y; 

все нормально , мы получаем дерево разбора, которое идет от cscript к statement_list, statement, assign_statement, id и expression. Большой!

Теперь, если добавить возможность объявлять переменные, все идет насмарку:

Это изменение грамматики:

cscript 
    : (statement_list | variable_declaration ';')* ; 

variable_declaration 
    : type ID ('=' expression)? 
    ; 

type 
    : 'int' 
    | 'real' 
    ; 

statement_list 
    : statement ';' statement_list? 
    | block 
    ; 

statement 
    : assignment_statement 
    ; 

// (continue as before) 

Внезапно, тот же тест-вход ошибочно расчленяется на два оператора, каждый из которых продолжит утверждение с предупреждением «missing»; «», первое из которых переходит к неполному присваиванию_размера «z =», а второе - к неполному присваиванию_имя «x +».

Моя попытка показать дерево разбора в текстовом виде:

cscript 
    statement_list 
     statement 
      assignment_statement 
       'z' 
       '=' [marked as error] 
     [warning: missing ';'] 
    statement_list 
     statement 
      assignment_statement 
       'x' 
       '+' [marked as error] 
     'y' [marked as error] 
     ';' 

Может кто-нибудь сказать мне, в чем проблема? (И как это исправить ;-)?)


Редактировать на 2016-12-26, после комментария Майка:

После замены всех неявных правил LeXeR с явными декларациями, внезапно , работал «z = x + y». (пальцы)

Следующая вещь, которую я восстанавливал больше первоначального примера я имел в виду, и добавление новой строки ввода

int x = 22; 

на вход (который работал ранее, но сделал не делайте это в минимальном примере). Теперь , что линия не работает. Это -token выход испытательной установки:

[@0,0:2='int',<4>,1:0] 
[@1,4:4='x',<22>,1:4] 
[@2,6:6='=',<1>,1:6] 
[@3,8:9='22',<20>,1:8] 
[@4,10:10=';',<12>,1:10] 
[@5,13:13='z',<22>,2:0] 
[@6,15:15='=',<1>,2:2] 
[@7,17:17='x',<22>,2:4] 
[@8,19:19='+',<18>,2:6] 
[@9,21:21='y',<22>,2:8] 
[@10,22:22=';',<12>,2:9] 
[@11,25:24='<EOF>',<-1>,3:0] 
line 1:6 mismatched input '=' expecting '=' 

Поскольку проблема, казалось, в variable_declaration части, я даже пытался разделить это на два правила синтаксического анализа, как это:

cscript 
    : (statement_list | variable_declaration_and_assignment SEMICOLON | variable_declaration SEMICOLON)* ; 

variable_declaration_and_assignment 
    : type ID EQUAL expression 
    ; 

variable_declaration 
    : type ID 
    ; 

С результат:

line 1:6 no viable alternative at input 'intx=' 

Тем не менее застрял :-( КСТАТИ: Нарезка "ИНТ х = 22;" в "междунар х", и "х = 22;" работ.Вздох


правка 2016-12-26, после следующего комментария Майка:

Дважды проверил, и все правила лексера. Тем не менее, несоответствие между '=' и '=' (которое я, к сожалению, не могу восстановить больше) дало мне идею проверить типы токенов. Текущее состояние:

(укороченный грамматика)

cscript 
    : (statement_list | variable_declaration)* ; 

... 

variable_declaration 
    : type ID (EQUAL expression)? SEMICOLON 
    ; 

... 

Assignment_operator : (EQUAL | PLUS_EQ | MINUS_EQ) ; 

// among others 
PLUS_EQ : '+='; 
MINUS_EQ : '-='; 
EQUAL: '='; 

... 

укороченный выход:

[@0,0:2='int',<4>,1:0] 
[@1,4:4='x',<22>,1:4] 
[@2,6:6='=',<1>,1:6] 
... 
line 1:6 mismatched input '=' expecting ';' 

Вот, если я понимаю, это правильно, '=' разобран лексем типа 1, который - в соответствии с выходом lexer.tokens - Assignment_Operator, тогда как ожидаемый EQUAL будет 13.

Возможно, это будет проблемой?

+0

Странная проблема. Начните с определения всех лексических элементов в качестве правил лексера. Никаких неявных литералов в правилах парсера. Затем пусть ваша буферизованная строка токена предоставит вам все маркеры, которые он находит ('stream.fill()', затем перебирает 'stream.getTokens();' с вызовом token.toString()). Какие же показатели вы видите в этом списке? –

+0

@MikeLischke Спасибо за ваш вклад! Я редактировал вопрос, чтобы включить результаты токена и следующую результирующую проблему. – mtj

+0

Эта ошибка: «строка 1: 6 несогласованный вход» = «Ожидание» = «обычно является признаком наличия нескольких определений« = »(например, литералов, встроенных в правила парсера). Дважды проверьте объявления своих токенов. Все ли токены, на которые распространяются правила lexer, вместо ленивого использования непосредственно в правиле парсера? –

ответ

1

Хорошо, кажется, главный отрыв: подумайте о своих определениях и о том, как вы их определяете. Создайте четкие правила лексики для ваших литералов, а не определяйте их неявно в правилах парсера. Проверьте значения маркера, которые вы получаете из лексера, если синтаксический анализатор дает вам странные ошибки, потому что они должны быть правильными в первую очередь или ваш синтаксический анализ не имеет возможности выполнить свою работу.

+0

Спасибо большое! :) – mtj

+0

Btw, вы еще не назначили награду ;-) –

+0

Извините, первый таймер. Должно быть сделано сейчас. – mtj

Смежные вопросы