Как избежать вложенных объектов с помощью 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 ответ
Некоторые из критериев, которые я использую:
- Не каждое правило должно иметь
Node
учебный класс. - Правила с закрытием
{}
в качестве основного выражения хороши для возврата списка. - Правила с выбором
|
в качестве основного выражения лучше всего возвращать то, что возвращает успешный параметр, даже если это часто требует включения этого параметра в собственное правило. - Приоритет важен.
- ЭСТ.
Идея состоит в том, что сгенерированная модель разбора должна быть простой в использовании, особенно с ходунками, с минимум 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_]*/
;