Как избежать вложенных объектов с помощью ModelBuilderSemantics в Grako

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

expression::Expression
=
  or_ex:and_expr {'||' or_ex:and_expr}+
| andex:and_expr
;

and_expr::AndExpression
=
  and_ex:sub_expr {'&&' and_ex:sub_expr}+
| subex:sub_expr
;

sub_expr::SubExpression
=
  {'!!'}* '!(' not_ex:expression ')'
| {'!!'}* '(' sub_ex:expression ')'
| compex:comp_expr
;

comp_expr::CompareExpression
=
  comp:identifier operator:('>=' | '<=' | '==' | '!=' | '>' | '<') comp:identifier
;

identifier::str
=
?/[a-zA-Z][A-Za-z0-9_]*/?
;

Синтаксический анализ test_input, приведенный ниже, работает, как и ожидалось, но я бы предпочел пометить элемент and_expr в правиле выражения символом "@" вместо "andex". Я надеялся, что проанализированный вывод приведет только к объекту CompareExpression, который находится внутри элемента not_ex в объекте Expression.

!(a == b)

Кажется, что при использовании метки '@' в элементе and_expr атрибуты не отображаются в объекте Expression! Это ошибка или умышленное? Должен ли я маркировать все элементы именами и не использовать метку '@' при использовании ModelBuilderSemantics?

Еще одна проблема, с которой я столкнулся, заключается в том, что если у более позднего правила, такого как comp_expr, не было ассоциированного имени класса, его элементы появлялись бы в словаре при печати, но средство доступа к точечной нотации не работало бы с AttributeError, то есть "AttributeError: объект 'dict' не имеет атрибута 'comp' ". Есть ли способ использовать средство доступа к точечной нотации, даже если правила не имеют имен классов, связанных с ними?

1 ответ

Некоторые из критериев, которые я использую:

  1. Не каждое правило должно иметь Node учебный класс.
  2. Правила с закрытием {} в качестве основного выражения хороши для возврата списка.
  3. Правила с выбором | в качестве основного выражения лучше всего возвращать то, что возвращает успешный параметр, даже если это часто требует включения этого параметра в собственное правило.
  4. Приоритет важен.
  5. ЭСТ.

Идея состоит в том, что сгенерированная модель разбора должна быть простой в использовании, особенно с ходунками, с минимум if-else или же isinstance(),

Вот как я бы сделал ваш пример:

start
    =
    expression $
    ;


expression
    =
    | or_expre
    | and_expre
    | sub_expre
    ;


or_expre::OrExpression
    =
    operands:'||'.{and_expre}+
    ;


and_expr::AndExpression
    =
    operands:'&&'.{sub_expre}+
    ;


sub_expr
    =
    | not_expr
    | comp_expre
    | atomic
    ;


not_expre::NotExpression
   =
   '!!' ~ sub_expr
   ;


comp_expr::CompareExpression
    =
    lef:atomic operator:('>=' | '<=' | '==' | '!=' | '>' | '<') ~ right:atomic
    ;


atomic
    =
    | group_expre
    | identifier
    ;


group_expr::GroupExpression
    =
    '(' ~ expre:expression ')'
    ;


identifier::str
    =
    /[a-zA-Z][A-Za-z0-9_]*/
    ;
Другие вопросы по тегам