首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >树重写语法中的ANTLR3语义谓词

树重写语法中的ANTLR3语义谓词
EN

Stack Overflow用户
提问于 2013-08-21 15:36:17
回答 1查看 226关注 0票数 0

我正在创建一个解析器,它创建一个AST,然后重写它以解决所有的歧义,然后遍历它并计算结果。

重写的一部分是将像^(QUERY ID)这样的节点转换为^(DECIMALQUERY ID)^(DATEQUERY ID),这取决于ID所代表的变量的类型。

代码语言:javascript
复制
query
    :   ^(QUERY ID)
    { 
        var type = GetQueryType($ID.text); 
    }
    -> { type == QueryType.Decimal }?   ^(DECIMALQUERY ID)
    -> { type == QueryType.Date }?      ^(DATEQUERY ID)
    -> { type == QueryType.String }?    ^(STRINGQUERY ID)
;

也就是说,基于type值,QUERY令牌被转换为DECIMALQUERYDATEQUERYSTRINGQUERY

问题是ANTLR拒绝为该语法生成代码。该命令是:

代码语言:javascript
复制
java -jar ..\..\binaries\antlr-3.4-complete.jar -message-format vs2005 .\TreeTransform.g

而错误是:

代码语言:javascript
复制
.\TreeTransform.g(54,2) : error 100 : syntax error: antlr: MismatchedTokenException(52!=84)
.\TreeTransform.g(53,52) : error 100 : syntax error: assign.types: NoViableAltException(0@[])
org\antlr\grammar\v3\DefineGrammarItemsWalker.g: node from line 53:51 no viable alternative at input ')'
.\TreeTransform.g(53,52) : error 100 : syntax error: buildnfa: NoViableAltException(0@[])
.\TreeTransform.g(53,52) : error 100 : syntax error: codegen: NoViableAltException(0@[])
.\TreeTransform.g(53,52) : error 100 : syntax error: antlr.print: NoViableAltException(0@[])
.\TreeTransform.g(53,52) : error 100 : syntax error: antlr.print: NoViableAltException(0@[])

但是,当我移除最后一个语义谓词时,一切都正常:

代码语言:javascript
复制
query
    :   ^(QUERY ID)
    { 
        var type = GetQueryType($ID.text); 
    }
    -> { type == QueryType.Decimal }?   ^(DECIMALQUERY ID)
    -> { type == QueryType.Date }?      ^(DATEQUERY ID)
    ->                                  ^(STRINGQUERY ID)
;

但我不喜欢string类型是“默认”分支的想法。如果这三个谓词中没有一个得到真,我宁愿有一个异常(即在枚举中添加了一个新类型,但没有添加到语法中;如果删除最后一个谓词,它将返回到字符串中)。

所以,我的问题是:

如何明确指定这种基于类型的交换的所有情况?如果这三种选择都没有得到满足,是否有办法强制例外?

完整的解析器和树转换语法如下:

https://bitbucket.org/ik/public/src/8f91e683e79a084138d6b55beabf8d5e18d965d4/AntlrSemanticPredicatesProblem?at=default

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-08-23 17:03:36

为了最大限度地支持正常的错误消息,您应该使用以下方法:

代码语言:javascript
复制
-> { type == QueryType.Decimal }?   ^(DECIMALQUERY[$QUERY] ID)
-> { type == QueryType.Date }?      ^(DATEQUERY[$QUERY] ID)
-> { type == QueryType.String }?    ^(STRINGQUERY[$QUERY] ID)
->                                  ^(INVALIDQUERY[$QUERY] ID)

然后,您可以报告INVALIDQUERY出现在树中的情况,而不会导致解析器失败。

PS:我添加的[$QUERY]参数确保在重写的树中保留令牌行/列信息。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18361768

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档