в небольшом тесте-парсере Я только что написал, я столкнулся с какой-то странной проблемой, которую я не совсем понимаю.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.
Возможно, это будет проблемой?
Странная проблема. Начните с определения всех лексических элементов в качестве правил лексера. Никаких неявных литералов в правилах парсера. Затем пусть ваша буферизованная строка токена предоставит вам все маркеры, которые он находит ('stream.fill()', затем перебирает 'stream.getTokens();' с вызовом token.toString()). Какие же показатели вы видите в этом списке? –
@MikeLischke Спасибо за ваш вклад! Я редактировал вопрос, чтобы включить результаты токена и следующую результирующую проблему. – mtj
Эта ошибка: «строка 1: 6 несогласованный вход» = «Ожидание» = «обычно является признаком наличия нескольких определений« = »(например, литералов, встроенных в правила парсера). Дважды проверьте объявления своих токенов. Все ли токены, на которые распространяются правила lexer, вместо ленивого использования непосредственно в правиле парсера? –