Как разрешить имена переменных и ключевые слова Xtext статически?
У меня есть грамматика, описывающая ассемблерный диалект. В разделе кода программист может ссылаться на регистры из определенного списка и на определенные переменные. Также у меня есть правило, соответствующее [reg0++413] и [myVariable++413]:
BinaryBiasInsideFetchOperation:
'['
v = (Register|[IntegerVariableDeclaration]) ( gbo = GetBiasOperation val = (Register|IntValue|HexValue) )?
']'
;
Но когда я пытаюсь скомпилировать его, Xtext выдает предупреждение:
Decision can match input such as "'[' '++' 'reg0' ']'" using multiple alternatives: 2, 3. As a result, alternative(s) 3 were disabled for that input
Разделив правила, я заметил, что
BinaryBiasInsideFetchOperation:
'['
v = Register ( gbo = GetBiasOperation val = (Register|IntValue|HexValue) )?
']'
;
BinaryBiasInsideFetchOperation:
'['
v = [IntegerVariableDeclaration] ( gbo = GetBiasOperation val = (Register|IntValue|HexValue) )?
']'
;
хорошо работать отдельно, но не одновременно. Когда я пытаюсь скомпилировать их оба, XText пишет несколько ошибок, говорящих о том, что регистры из списка могут быть обработаны неоднозначно. Так:
1) Прав ли я, что часть правила v = (Register|[IntegerVariableDeclaration]) соответствует любому имени IntegerVariable, включая пустое, но правило v = [IntegerVariableDeclaration] соответствует только непустым именам?
2) Правильно ли то, что когда я пытаюсь скомпилировать отдельные правила вместе, Xtext считает, что [IntegerVariableDeclaration] может совпадать с Register?
3) Как решить эту двусмысленность?
редактировать: определители
Register:
areg = ('reg0' | 'reg1' | 'reg2' | 'reg3' | 'reg4' | 'reg5' | 'reg6' | 'reg7' )
;
IntegerVariableDeclaration:
section = SectionServiceWord? name=ID ':' type = IntegerType ('[' size = IntValue ']')? ( value = IntegerVariableDefinition )? ';'
;
ID - это стандартный терминал, который анализирует одно слово, или идентификатор
2 ответа
Нет, (Register|[IntegerVariableDeclaration]) не может совпадать с пустым. На самом деле [IntegerVariableDeclaration] совпадает с [IntegerVariableDeclaration|ID], это соответствует правилу идентификатора.
Да, я думаю, ты не можешь разделить свои правила.
Я не могу воспроизвести вашу проблему (мне нужна полная грамматика), но, чтобы решить вашу проблему, вы должны взглянуть на эту статью об отладке грамматики xtext:
Скомпилируйте грамматику в режиме отладки, добавив следующую строку в ваш workflow.mwe2
fragment = org.eclipse.xtext.generator.parser.antlr.DebugAntlrGeneratorFragment {}
Откройте сгенерированную отладочную грамматику antrl с помощью AntlrWorks и проверьте диаграмму.
В дополнение к ответу Фабьена, я хотел бы добавить, что такое общее правило, как
AnyId:
name = ID
;
вместо
(Register|[IntegerVariableDeclaration])
решает проблему. Необходимо динамически проверять, является ли AnyId.name регистром, переменной или чем-то еще, например, константой.