基本上,我正在尝试编写包含proprocessor指令的语言。我把问题缩小到一个非常简单的例子。在我的示例语言中,以下内容应该是有效的语法:
@@some preprocessor text
PRINT some regular text
在解析代码时,我希望能够识别令牌" 一些预处理器文本"," PRINT &# 34;和" 一些常规文本"。
这是解析器语法:
parser grammar myp;
root: (preprocessor | command)*;
preprocessor: PREPROC PREPROCLINE;
command: PRINT STRINGLINE;
这是词法分析器语法:
lexer grammar myl;
PREPROC: '@@' -> pushMode(PREPROC_MODE);
PRINT: 'PRINT' -> pushMode(STRING_MODE);
WS: [ \t\r\n] -> skip;
mode PREPROC_MODE;
PREPROCLINE: (~[\r\n])*[\r\n]+ -> popMode;
mode STRING_MODE;
STRINGLINE: (~[\r\n])*[\r\n]+ -> popMode;
当我解析上面的示例代码时,我收到以下错误:
第1行:2个无关输入'一些预处理文本\ r \ n&n;期待 PREPROCLINE第2行:5令牌识别错误:'一些常规文本'
无论行是否为" WS:[\ t \ r \ n] - >,都会发生此错误。跳过; "是否包含在词法分析器语法中。我想如果我引用标记PREPROCLINE和STRINGLINE而不是行结尾,它会起作用(至少我在其他语言中实现了常规字符串)。但是在这种特殊的语言中,我真的想要没有引号的字符串。
非常感谢有关此错误发生原因或如何使用不带引号的字符串实现预处理器语言的任何帮助。
谢谢
答案 0 :(得分:1)
更新:首先,识别错误是因为您的解析器需要引用词法分析器标记。将选项块添加到解析器:
options {
tokenVocab=MyLexer;
}
其次,当您生成词法分析器/解析器时,请注意在继续之前通常需要考虑并纠正警告。
最后,一旦添加了选项块,这些都是可行的替代方案。
XXXX: (~[\r\n])*[\r\n]+ -> popMode;
有点清洁:
XXXX: .*? '\r'? '\n' -> popMode;
要不包括行结尾,请尝试
XXXX: .*? ~[\r\n] -> popMode;