2016-10-10 18 views
0

以下の文法を見てみると、より具体的な式タイプに解析される主要なルールexpressionが見えます。GrakoのModelBuilderSemanticsを使用したネストされたオブジェクトの回避

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要素にラベルを付けることを好むだろう。私の希望は、解析された出力は、Expressionオブジェクトのnot_ex要素の内部にあるCompareExpressionオブジェクトのみになるということでした。

!(a == b) 

and_expr要素に '@'ラベルを使用すると、Expressionオブジェクトに属性が表示されないようです。これはバグか故意ですか? ModelBuilderSemanticsを使用する場合は、すべての要素に名前を付ける必要がありますが、 '@'ラベルは使用しないでください。

私が直面してきたもう一つの問題は、comp_exprのような後の規則に関連するクラス名がないと、その要素が印刷時に辞書に表示されますが、ドット表記アクセサーがAttributeErrorつまり、 "AttributeError: 'dict'オブジェクトには属性 'comp'がありません。ルールにクラス名が関連付けられていない場合でも、ドット表記アクセッサを使用する方法はありますか?私が使用基準の

答えて

0

一部:

  1. 必ずしもすべてのルールが関連付けられているNodeクラスを持っている必要があります。
  2. 閉鎖を持つルールは、メインの式として{}がリストを返すのに適しています。
  3. 選択肢のある規則|は、成功したオプションが返すすべてのものを返すのが最も適しています。
  4. 優先順位が重要です。
  5. Ect。

アイデアは、生成された解析モデルは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_]*/ 
    ;