Разбивая лексические элементы на части

Мой файл грамматики test.ebnf похоже,

start = identifier ;

identifier =
  /[a-z]*/ rest;

rest = /[0-9]*/ ;

Когда я запускаю эту грамматику во входных данных "test1234", я хочу, чтобы она выдавала "test1234" как одну лексему, но вместо этого AST выглядит так:

AST:
['test', '1234']

Я пытался бежать с nameguard функция установлена ​​на ложь без удачи. Как я могу получить это поведение без написания правила, как identifier = /[a-z]*[0-9]*/?

1 ответ

Grako всегда будет возвращать список с одним объектом на элемент в правой части правила, кроме случаев, когда есть только один элемент. Даже при именовании элементов несколько совпадений с одним и тем же именем возвращают список. Простое объединение элементов нецелесообразно, поскольку их AST могут быть объектами настолько сложными, насколько этого требует проект.

В вашем случае вы можете использовать семантическое действие, чтобы присоединиться к identifier части:

def identifier(self, ast):
    return ''.join(ast)

Или переопределить identifier Правило иметь один элемент:

identifier
    =
    /[a-z]+[0-9]*|[a-z]*[0-9]+/
    ;

(Обратите внимание на изменения в регулярном выражении, чтобы оно никогда не совпадало с пустой строкой).

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