使用“词法分析器规则操作”和“词法分析器命令”时出现无关的输入错误

时间:2019-06-03 03:09:24

标签: antlr4

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

Cool.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会引发错误?

2 个答案:

答案 0 :(得分:0)

这是一种使用转义序列解析字符串的令人惊讶的复杂方法。您是否打印了结果标记以查看您的词法分析器产生了什么?

我建议一种不同的方法(并且更简单):

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

然后在语义阶段中,当您对语法分析树进行后期处理时,检查匹配的文本以查找转义序列。当发现无效的转义序列时(将其与词法分析器中的转义序列进行匹配,您将无法执行这些操作),将它们转换为真正的字符并打印出良好的错误消息。

答案 1 :(得分:0)

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

“您的ID规则是非谓词的,因此它与aa之后的\匹配(aaa匹配的INSTRINGAFTERESCAPE长},因此,即使在语法的后面,它也是首选。如果在printlnWS中添加ID,则会在输出中看到奇怪的行为。”