【问题标题】:Grammar to negate two like characters in a lexer rule inside a single quoted string在单引号字符串内的词法分析器规则中否定两个相似字符的语法
【发布时间】:2017-02-22 21:39:08
【问题描述】:

ANLTR 4:

我需要支持带有转义字符的单引号字符串文字以及使用双花括号作为需要额外解析的“转义序列”的能力。所以这两个例子都需要支持。我不太担心第二个例子,因为如果我能让第一个例子工作并且不匹配双花括号字符,这似乎微不足道。

1. 'this is a string literal with an escaped\' character' 2. 'this is a string {{functionName(x)}} literal with double curlies'

StringLiteral 
: '\'' (ESC | AnyExceptDblCurlies)*? '\'' ;

fragment 
ESC : '\\' [btnr\'\\];

fragment 
AnyExceptDblCurlies 
: '{' ~'{' 
| ~'{' .;

我对此进行了大量研究,并了解您不能否定多个字符,甚至在 Bart 在这篇文章中的回答中看到了类似的方法...

Negating inside lexer- and parser rules

但我看到的是,在上面的示例 1 中,转义的单引号未被识别,并且我收到一个解析器错误,它无法匹配“字符”。

如果我将字符串文字标记规则更改为以下内容...

StringLiteral 
: '\'' (ESC | .)*? '\'' ;

任何想法如何更好地处理这种情况?我可以推断出转义字符被 AnyExceptDblCurlies 而不是 ESC 匹配,但我不知道如何解决这个问题。

【问题讨论】:

  • 你真的需要在这个阶段标记字符串文字的内容吗?你不知道你有什么样的语法用例;我正在考虑像 C 或 C# 这样的语言,它们通常将文字解析留给运行时函数、printf、String.Format 等
  • @dlatikay,我需要能够解析文字包含'{{x}}'的情况,所以我不能推迟到运行时。您是否建议在解析器规则级别处理这种情况可能更容易?
  • 我明白了...是的,解析器规则 > 它让我想起了this one

标签: antlr antlr4 parser-generator


【解决方案1】:

从字符串中解析模板定义几乎需要在解析器中进行处理。使用词法分析器模式来区分字符串字符和模板名称。

解析器:

options {
    tokenVocab = TesterLexer ;
}

test : string EOF ;
string   : STRBEG ( SCHAR | template )* STREND ; // allow multiple templates per string
template : TMPLBEG TMPLNAME TMPLEND ;

词法分析器:

STRBEG : Squote -> pushMode(strMode) ;

mode strMode ;
    STRESQ  : Esqote  -> type(SCHAR) ; // predeclare SCHAR in tokens block
    STREND  : Squote  -> popMode ;
    TMPLBEG : DBrOpen -> pushMode(tmplMode) ;
    STRCHAR : .       -> type(SCHAR) ;

mode tmplMode ;
    TMPLEND  : DBrClose  -> popMode ;
    TMPLNAME : ~'}'*  ;

fragment Squote : '\''   ;
fragment Esqote : '\\\'' ;
fragment DBrOpen   : '{{' ;
fragment DBrClose  : '}}' ;

更新以更正 TMPLNAME 规则,添加主规则和选项块。

【讨论】:

  • 这看起来正是我所需要的......我一直在尝试使用语义谓词,但使用模式堆栈似乎是门票!让我试试这个……不敢相信这种情况需要如此高的清晰度。
  • GRosenberg,我什至无法在 ANTLR 中编译您的示例的最简单版本,针对 C#(.NET 4.5.2)...我纠正了您示例中的一些错误,但即使如此我似乎无法匹配一个简单的单引号字符串...我将在主线程的更新中显示我的代码。如果我遗漏了什么,请告诉我。
  • 出现解析器缺少选项块:options { tokenVocab = TesterLexer ; } 这是所有拆分语法的标准要求。
  • 当然,我想先把它纳入我更大的语法中,但你是对的,问题是完全答案。再次感谢!
  • 另一条评论,@GRosenberg,我认为模式名称需要以大写字母开头。
猜你喜欢
  • 2019-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-19
  • 2013-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多