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)
false
key