我看到输入“ \ 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会引发错误?
答案 0 :(得分:0)
这是一种使用转义序列解析字符串的令人惊讶的复杂方法。您是否打印了结果标记以查看您的词法分析器产生了什么?
我建议一种不同的方法(并且更简单):
STR_CONST: '"' ('\\"' | .)*? '"';
然后在语义阶段中,当您对语法分析树进行后期处理时,检查匹配的文本以查找转义序列。当发现无效的转义序列时(将其与词法分析器中的转义序列进行匹配,您将无法执行这些操作),将它们转换为真正的字符并打印出良好的错误消息。
答案 1 :(得分:0)
复制我在GitHub上从@sharwell收到的答案。
“您的ID
规则是非谓词的,因此它与aa
之后的\
匹配(aa
比a
匹配的INSTRINGAFTERESCAPE
长},因此,即使在语法的后面,它也是首选。如果在println
和WS
中添加ID
,则会在输出中看到奇怪的行为。”