首页 > 解决方案 > 无法在非组合语法中为字符串文字创建隐式标记:

问题描述

这是我的 XML 解析器语法:

attribute   :   Name '=' STRING ;

和词法分析器:

STRING      :   '"' ~[<"]* '"'
            |   '\'' ~[<']* '\''
            ;

这有效,但是当我在我的 C# 代码中检索 STRING 位时:

context.STRING().ToString();

我得到用引号括起来的文本,例如:“hello”,而不是 hello。所以我尝试将解析器语法更改为:

attribute   :   Name '=' '"' STRING ;

或者

attribute   :   Name '="' STRING ;

我得到错误:“无法在非组合语法中为字符串文字创建隐式标记”

我很困惑为什么解析器语法中允许使用“=”,但不允许使用引号,以及如何更改解析器以检索不带引号的文本。此外,词法分析器似乎已经处理掉引号,所以我不明白为什么我在解析时仍然得到它们。

标签: antlr4

解决方案


如果您有单独的词法分析器和解析器语法,则当且仅当您在词法分析器中使用该字符串文字定义了词法分析器规则时,才允许在解析器中使用字符串文字。否则,词法分析器将永远不会生成与该文字匹配的标记,因为词法分析器不知道哪些字符串文字出现或不出现在解析器中(组合语法不是这种情况,这就是错误消息显示“非-组合语法”)。

所以你可以使用'=',但不是'"'因为你有规则EQUALS: '=';,而是没有规则DQUOTE: '"';。但是在你继续添加这样的规则之前,让我们考虑一下它会做什么以及你是否想要这个(你不想要):

如果您添加了这样的规则(或使用了组合语法,您可以在'"'没有它的情况下使用),该attribute规则现在将匹配一个名称标记,后跟一个=标记,然后是一个"标记,然后是一个字符串标记。由于字符串标记已经在其开头和结尾包含引号,因此看起来像这样:

SomeName   =    "   "hello"
 Name     '='  '"'  STRING

所以这不是你想要的。另外,即使这是您想要的,它甚至都不起作用:上述输入中的第一个引号不会被识别为'"'标记 - 而是" "会被识别为字符串标记,然后hello是 a Name,最后"'"'标记 (因为没有进一步的引用可以使它符合STRING规则。

所以这是错误的方向,你不应该那样做。


如果您想要获取不带引号的字符串内容,则解决方案不是在语法中添加更多引号。您应该只Substring在 C# 代码中使用从字符串中删除第一个和最后一个字符。


推荐阅读