正如亚当已经提到的:这通常是在解析器创建某种(抽象)解析树之后完成的。您只需收集所有类型的声明,如下所示:
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();};
{set.add($decl.key)}?
称为Validating Semantic Predicates将在其中的代码 ( set.add($decl.key)
) 计算为时引发异常false
。在这种情况下,只要集合已经包含某个 ,它就会评估为 false key
。