我想在C源文件中额外处理所有预处理语句,并忽略所有其他语句。我尝试在词法分析器中添加最后一个规则,例如Unknown : . -> skip ; // or -> channel(HIDDEN) ;
,或者在解析器中添加最后一个规则,例如:ignored : . ;
,但它不起作用。
这是我的语法:
grammar PreProcessStatement;
pre_if_statement
: pre_if pre_elif* pre_else? pre_endif
;
pre_if : PreProcessBegin 'if' statement;
pre_endif : PreProcessBegin 'endif' ;
pre_else : PreProcessBegin 'else' ;
pre_elif : PreProcessBegin 'elif'statement ;
pre_define : PreProcessBegin 'define' statement;
pre_undef : PreProcessBegin 'undef'statement ;
pre_pragma : PreProcessBegin 'pragma'statement;
statement
: IDENTIFIER
| statement Condition statement
| '(' statement (Condition | Logic_or | Logic_and) statement ')'
| statement (Logic_or | Logic_and) statement
;
Logic_or
: '||'
;
Logic_and
: '&&'
;
PreProcessBegin : '#' ;
Condition : '==' | '>' | '>='| '<' | '<=' ;
NUM : INT | HEX ;
STRID : '"'ID'"' ;
IDENTIFIER : [a-zA-Z_0-9]+ ;
ID : [a-zA-Z_]+ ;
INT : [0-9]+ ;
HEX : '0x'INT;
WS : [ tnr]+ -> skip ;
NewLine : ('n' | 'r' | 'nr');
MulLine : '\' NewLine -> skip ;
Unknown : .*? -> skip ; // or -> channel(HIDDEN) ;
输入:
#if (test == ttt)
#elif rrrr
#else
aaa
#endif
错误:
line 4:0 extraneous input 'aaa' expecting '#'
我阅读了下面的链接,不起作用。跳过 Antlr 中不匹配的输入
我的语法有什么问题?
解释
aaa
输入与令牌不匹配Unknown
。它将与Unknown
词法之前定义的IDENTIFIER : [a-zA-Z_0-9]+
令牌匹配。
解决 方案
修改令牌
将Unknown
词法定义放在其他标记之前。在此词法中添加一个语义谓词,该谓词将检查行中的第一个字符是否不是#
字符。如果为 true,则跳过整行,直到NewLine
令牌。
Unknown : {getCharPositionInLine() == 0 && _input.LA(1) != '#'}? .*? NewLine -> skip;
使用词法分析器模式
当您发现#
字符时,进入新的词法分析器模式PREPROCESSOR
。这允许我们从现在开始仅使用在PREPROCESSOR
模式下定义的令牌。出现新行时退出此模式。因此,当我们退出模式时,我们正在寻找两个标记:PreProcessBegin
(以#
字符开头的行)和Unknown
(不带#
的行)。否则PREPROCESSOR
模式下,我们将像任何其他常规语言一样匹配语句。
词法分析器示例:
PreProcessBegin : '#' -> pushMode(PREPROCESSOR); // enter mode
Unknown : .*? NewLine -> skip; // or skip the line
mode PREPROCESSOR; // when in PREPROCESSOR mode use defined below tokens
(...)
Condition : '==' | '>' | '>='| '<' | '<=';
IDENTIFIER : [a-zA-Z_0-9]+ ;
ID : [a-zA-Z_]+ ;
INT : [0-9]+ ;
(...)
NewLine : ('n' | 'r' | 'nr') -> popMode; // exit mode