【问题标题】:Avoiding nested objects using ModelBuilderSemantics in Grako在 Grako 中使用 ModelBuilderSemantics 避免嵌套对象
【发布时间】:2016-10-10 22:15:33
【问题描述】:

如果你看一下下面的语法,你会看到一个主要的规则,表达式,它被解析成更具体的表达式类型。

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 的解析按预期工作,但我更愿意用“@”而不是“andex”来标记表达式规则中的 and_expr 元素。我希望解析后的输出只会产生一个 CompareExpression 对象,该对象位于 Expression 对象的 not_ex 元素内。

!(a == b)

似乎在 and_expr 元素上使用“@”标签时,Expression 对象中没有显示任何属性!这是一个错误还是故意的?在使用 ModelBuilderSemantics 时,我必须用名称标记所有元素并且不使用“@”标签吗?

我一直面临的另一个问题是,如果后面的规则(例如 comp_expr)没有关联的类名,则其元素在打印时会出现在字典中,但点符号访问器会失败并出现 AttributeError,即“AttributeError:'dict'对象没有属性'comp'”。即使规则没有与之关联的类名,是否有任何方法可以使用点符号访问器?

【问题讨论】:

    标签: grako


    【解决方案1】:

    我使用的一些标准:

    1. 并非每个规则都必须具有关联的 Node 类。
    2. {} 闭包作为主要表达式的规则非常适合返回列表。
    3. 选择| 作为主表达式的规则最好返回成功选项返回的任何内容,即使这通常需要将选项考虑到它自己的规则中。
    4. 优先级很重要。

    这个想法是生成的解析模型应该易于使用,特别是 walkers,至少有 if-elseisinstance()

    这就是我将如何做你的例子:

    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_]*/
        ;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-30
      • 1970-01-01
      • 2014-12-02
      • 1970-01-01
      • 1970-01-01
      • 2018-07-15
      • 1970-01-01
      • 2019-03-24
      相关资源
      最近更新 更多