如何用ANTLR4解析XSD正则表达式语法



亲爱的Antlr4社区,

我最近开始使用ANTLR4将正则表达式从XSD/xml转换为cvc4。我使用w3c指定的语法,请参阅http://www.w3.org/TR/xmlschema11-2/#regexs。对于这个问题,我简化了这个语法(通过删除charClass)为:

grammar XSDRegExp;
regExp            :     branch ( '|' branch )* ;
branch            :     piece* ;
piece             :     atom quantifier? ;
quantifier        :     Quantifiers | '{'quantity'}' ;
quantity          :     quantRange | quantMin | QuantExact ;
quantRange        :     QuantExact ',' QuantExact ;
quantMin          :     QuantExact ',' ;
atom              :     NormalChar | '(' regExp ')' ;       // excluded | charClass  ;
QuantExact        :     [0-9]+ ;
NormalChar        :     ~[.\?*+{}()|[]] ;        
Quantifiers       :     [?*+] ;     

解析似乎很正常:

input    a(bd){6,7}c{14,15}

但是,我得到一个错误消息:

input    12{3,4}

错误是:

第1行0不匹配输入'12'期待{,'(','|',NormalChar}

我理解Lexer也可以看到QuantExact作为第一个符号,但由于解析器只查找NormalChar,我没有预料到这个错误。

我尝试了一些更改:

[1]交换QuantExact和NormalChar的定义。但是交换会在第一个输入中引入一个错误:

line 1:6 no viable alternative at input '6'

因为在这种情况下'6'只被视为NormalChar而不是QuantExact。

[2]尝试为QuantExact(数量的花括号)创建一个上下文,这样词法分析器只在这个有限的上下文中提供QuantExact符号。但是我没有找到ANTLR4原语。

所以似乎没有工作,因此我的问题是:我可以用ANTLR4解析这个语法吗?如果有,是怎么做到的?

我理解Lexer也可以看到QuantExact作为第一个符号,但由于解析器只查找NormalChar,我没有预料到这个错误。

词法分析器不"监听"解析器:无论解析器是否试图匹配NormalChar,字符12将始终匹配为QuantExact。词法分析器尝试匹配尽可能多的字符,如果出现平局,它选择先定义的规则。

您可以引入匹配NormalCharQuantExactnormalChar规则,并在atom中使用该规则:

atom              :     normalChar | '(' regExp ')' ;
normalChar        :     NormalChar | QuantExact ;

另一种选择是让词法分析器只创建单个字符令牌,并让解析器将它们粘合在一起(很像PEG)。像这样:

regExp            :     branch ( '|' branch )* ;
branch            :     piece* ;
piece             :     atom quantifier? ;
quantifier        :     Quantifiers | '{'quantity'}' ;
quantity          :     quantRange | quantMin | quantExact ;
quantRange        :     quantExact ',' quantExact ;
quantMin          :     quantExact ',' ;
atom              :     normalChar | '(' regExp ')' ; 
normalChar        :     NormalChar | Digit ;
quantExact        :     Digit+ ;
Digit             :     [0-9] ;
NormalChar        :     ~[.\?*+{}()|[]] ;
Quantifiers       :     [?*+] ;

最新更新