Как разрешить имена переменных и ключевые слова 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 ответа

Решение
  1. Нет, (Register|[IntegerVariableDeclaration]) не может совпадать с пустым. На самом деле [IntegerVariableDeclaration] совпадает с [IntegerVariableDeclaration|ID], это соответствует правилу идентификатора.

  2. Да, я думаю, ты не можешь разделить свои правила.

  3. Я не могу воспроизвести вашу проблему (мне нужна полная грамматика), но, чтобы решить вашу проблему, вы должны взглянуть на эту статью об отладке грамматики xtext:

    • Скомпилируйте грамматику в режиме отладки, добавив следующую строку в ваш workflow.mwe2
      fragment = org.eclipse.xtext.generator.parser.antlr.DebugAntlrGeneratorFragment {}

    • Откройте сгенерированную отладочную грамматику antrl с помощью AntlrWorks и проверьте диаграмму.

В дополнение к ответу Фабьена, я хотел бы добавить, что такое общее правило, как

AnyId:
    name = ID
;

вместо

 (Register|[IntegerVariableDeclaration])

решает проблему. Необходимо динамически проверять, является ли AnyId.name регистром, переменной или чем-то еще, например, константой.

Другие вопросы по тегам