【问题标题】:Extraneous input error when using "lexer rule actions" and "lexer commands"使用“词法分析器规则操作”和“词法分析器命令”时出现无关输入错误
【发布时间】:2019-10-18 14:46:18
【问题描述】:

我看到输入“\aa a”和以下语法的“外部输入”错误:

酷.g4

grammar Cool;
import Lex;

expr
   : STR_CONST # str_const
   ;

Lex.g4

lexer grammar Lex;

@lexer::members {
  public static boolean initial = true;
  public static boolean inString = false;
  public static boolean inStringEscape = false;
}

BEGINSTRING: '"' {initial}? {
  inString = true;
  initial = false;
  System.out.println("Entering string");
} -> more;

INSTRINGSTARTESCAPE: '\\' {inString && !inStringEscape}? {
  inStringEscape = true;
  System.out.println("The next character will be escaped!");
} -> more;

INSTRINGAFTERESCAPE: ~[\n] {inString && inStringEscape}? {
  inStringEscape = false;
  System.out.println("Escaped a character.");
} -> more;

INSTRINGOTHER: (~[\n\\"])+ {inString && !inStringEscape}? {
  System.out.println("Consumed some other characters in the string!");
} -> more;

STR_CONST: '"' {inString && !inStringEscape}? {
  inString = false;
  initial = true;
  System.out.println("Exiting string");
};

WS : [ \t\r\n]+ -> skip ; // skip spaces, tabs, newlines

ID:  [a-z][_A-Za-z0-9]*;

这是输出:

$ grun Cool expr -tree
"\aa a"
Entering string
The next character will be escaped!
Escaped a character.
Consumed some other characters in the string!
Exiting string
line 1:0 extraneous input '"\aa' expecting STR_CONST
(expr "\aa  a")

有趣的是,如果我删除 ID 规则,antlr 会很好地解析输入。这是我删除 ID 规则时的输出:

$ grun Cool expr -tree
"\aa a"
Entering string
The next character will be escaped!
Escaped a character.
Consumed some other characters in the string!
Exiting string
(expr "\aa a")

知道会发生什么吗? ID是Lexer规则之一时,antlr为什么会报错?

【问题讨论】:

    标签: antlr4


    【解决方案1】:

    这是用转义序列解析字符串的一种非常复杂的方法。您是否打印了生成的标记以查看您的词法分析器产生了什么?

    我推荐一种不同(而且更简单)的方法:

    STR_CONST: '"' ('\\"' | .)*? '"';
    

    然后在您的语义阶段,当您对解析树进行后处理时,检查匹配的文本以查找转义序列。当发现无效的转义序列时(在词法分析器中尝试匹配转义序列时无法做到这一点),将它们转换为真实字符并打印一条好的错误消息。

    【讨论】:

    • 嗨,迈克。我通过使用 STR_CONST: '"' ( ESC | .)*? '"'; 解决了这个问题fragment ESC: '\\"' | '\\\\' ; 但是我仍然不明白为什么当 ID 是 Lexer 规则之一时 antlr 会抛出错误。这是 antlr 中的预期行为吗?旁注:你提到了打印生成的令牌。我该怎么做?它与“grun Cool expr -tree”命令不同吗?
    • 想不通为什么 ID 规则会产生如此惊人的效果。这需要详细调试。打印标记:我从来没有使用过grun,所以我不能说它是否允许这样做,但是在代码中,你可以使用生成的词法分析器调用fill() 来解析所有标记,然后遍历它们并打印它们的文本表示.这将向您显示词法分析器找到的类型以及它们是否符合您的预期。
    【解决方案2】:

    复制我在GitHub 上从@sharwell 收到的答案。

    “你的ID 规则是无谓的,所以它匹配\ 之后的aaaaINSTRINGAFTERESCAPE 匹配的a 长,所以它是首选的,即使它在语法的后面)。如果将println 添加到WSID,您将在输出中看到奇怪的行为。"

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-03-04
      • 2013-04-29
      • 1970-01-01
      • 2022-10-13
      • 2017-12-24
      • 1970-01-01
      相关资源
      最近更新 更多