如果您查看下面的语法,您可以看到一个主要规则,表达式,它被解析为更具体的表达式类型。
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元素&#39; @&#39;而不是&#39; andex&#39;。我希望解析的输出只会导致一个CompareExpression对象,它位于Expression对象的not_ex元素中。
!(a == b)
似乎在使用&#39; @&#39;在and_expr元素上的标签,Expression对象中没有显示任何属性!这是一个错误还是故意的?我必须用名称标记所有元素,而不是使用&#39; @&#39;使用ModelBuilderSemantics时标签?
我面临的另一个问题是,如果后来的规则(例如comp_expr)没有关联的类名,则其元素在打印时会出现在字典中,但点符号访问器将失败并且AttributeError,即&#34;属性错误:&#39; dict&#39;对象没有属性&#39; comp&#39;&#34;。有没有办法使用点符号访问器,即使规则没有与它们相关联的类名?
答案 0 :(得分:0)
我使用的一些标准:
Node
类。{}
为主表达式的规则适用于返回列表。|
作为主表达式的规则最好返回成功选项返回的内容,即使这通常需要将选项分解为自己的规则。 我们的想法是生成的解析模型应该易于使用,特别是 walkers ,最少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_]*/
;