4

次のテンプレートを解析するための文法が必要だとします。

1. REPORT
2. BEGIN
3.   QUERY
4.   BEGIN
5.     AGGREGATION: day
6.     DIMENSION: department
7.   END
8. END

5 行目と 6 行目はオプションで、2 行の順序は関係ありません。文法ファイルでこれを指定するにはどうすればよいですか? 以下は私の解決策です(行番号12を参照):

1. grammar PRL;
2. report
3.  : REPORT
4.      BEGIN 
5.          query
6.      END
7.  ;
8.
9. query
10.  : QUERY 
11.     BEGIN
12.         (aggregation_decl dimension_decl | dimension_decl aggregation_decl)? 
13.     END
14. ;

動作しますが、見栄えが悪く、パーツが 2 つ以上ある場合、すぐに管理できなくなりますか? 何かアドバイス?

4

2 に答える 2

0

Adam が既に述べたように、これは通常、パーサーがある種の (抽象) 解析ツリーを作成した後に行われます。次のように、すべてのタイプの宣言を収集するだけです。

grammar PRL;

report
 : REPORT BEGIN query END
 ;

query
 : QUERY BEGIN decl* END
 ;

decl
 : NAME ':' NAME
 ;

REPORT : 'REPORT';
BEGIN  : 'BEGIN';
END    : 'END';
QUERY  : 'QUERY';
NAME   : ('a'..'z' | 'A'..'Z')+;

SPACE  : (' ' | '\t' | '\r' | '\n')+ {skip();};

その後、decl*AST に重複があるかどうかを確認します。

しかし、解析中に本当にこれを行いたい場合は、 の左側を取得してdeclこれらを a に追加する必要がありSetます。重複に遭遇した場合は、述語例外をスローします。

grammar PRL;

@parser::header {
  import java.util.Set;
  import java.util.HashSet;
}

report
 : REPORT BEGIN query END
 ;

query
 : QUERY BEGIN unique_decls END
 ;

unique_decls
@init{Set<String> set = new HashSet<String>();}
 : (decl {set.add($decl.key)}?)*
 ;

decl returns[String key]
 : k=NAME ':' NAME {$key = $k.text;}
 ;

REPORT : 'REPORT';
BEGIN  : 'BEGIN';
END    : 'END';
QUERY  : 'QUERY';
NAME   : ('a'..'z' | 'A'..'Z')+;

SPACE  : (' ' | '\t' | '\r' | '\n')+ {skip();};

Validating Semantic Predicates{set.add($decl.key)}?と呼ばれる は、( ) 内のコードが に評価されると例外をスローします。この場合、セットに特定の がすでに含まれている場合は常に false と評価されます。set.add($decl.key)falsekey

于 2012-06-26T07:58:59.820 に答える
0

このようなもの?一般に、後の処理ステップで各アイテムが 1 つだけ存在するように強制します。そうしないと、ご覧のとおり、文法が扱いにくくなります。

grammar PRL;
report
  : REPORT
      BEGIN 
          query
      END
  ;

query
  : QUERY 
     BEGIN
       body_decl* 
     END
 ;

body_decl :
   aggregation_decl dimension_decl
 | dimension_decl aggregation_decl;
于 2012-06-26T03:49:53.820 に答える