Antlr4 用于测试隐藏通道标记的ANTR4解析器语法
我想解析cpp预处理指令,同时跳过所有其他cpp语法。特别是,我需要区分类函数宏和类对象宏:Antlr4 用于测试隐藏通道标记的ANTR4解析器语法,antlr4,Antlr4,我想解析cpp预处理指令,同时跳过所有其他cpp语法。特别是,我需要区分类函数宏和类对象宏: # define abc(x,y) x##y //function like macro & token pasting operator # define abc (a,b,c) //object like macro, replace 'abc' by '(a,b,c)' 关键区别在于,类似于函数的宏在标识符abc和它后面的左括号之间没有任何隐藏标记(空格或多行注释) 但问题是,我已
# define abc(x,y) x##y //function like macro & token pasting operator
# define abc (a,b,c) //object like macro, replace 'abc' by '(a,b,c)'
关键区别在于,类似于函数的宏在标识符abc
和它后面的左括号之间没有任何隐藏标记(空格或多行注释)
但问题是,我已经将lexer中的所有多行注释和空格删除到隐藏通道中。那么,如何识别左括号前的空格呢
我试过的lexer语法如下:
CRLF: '\r'? '\n' -> channel(LINEBREAK);
WS: [ \t\f]+ -> channel(WHITESPACE);
ML_COMMENT: '/*' .*? '*/' -> channel(COMMENTS);
SL_COMMENT: '//' ~[\r\n]* -> channel(COMMENTS);
PPHASH: {getCharPositionInLine() == 0}? (ML_COMMENT | [ \t\f])* '#'
; //any line starts with a # as the first char (comments, ws before it skipped)
CHARACTER_LITERAL : 'L'? '\'' (CH_ESC |~['\r\n\\])*? '\'' ; //not exactly 1 char between '' e.g. '0x05'
fragment CH_ESC : '\\' . ;
STRING_LITERAL: 'L'? '"' (STR_ESC | ~["\r\n\\])*? '"' ;
fragment STR_ESC: '\\' . ;
ANY_ID: [_0-9a-zA-Z]+ ;
ALL_SYMBOL:
'~' | '!' | '@' | '#' | '$' | '%' | '^' | '&' | '*' | '=' | '-' | '+' | '\\'| '|' | ':' | ';' | '"' | '\''|
'<' | '>' | '.' | '?' | '/' | ',' | '[' | ']' | '(' | ')' | '{' | '}'
; //basically everything found in a keyboard
该语法错误地将a
#定义abc(a,b,c)
视为类似宏的函数。如何修复语法?解析带有所有提示的预处理器标记(跳过任何禁用的标记、行拼接、宏处理、字符串化、字符化等等)不是一般解析器的任务。您应该实现一个自己的输入流来处理预处理器宏(其中包括一个用于条件的表达式解析器)。然后,该流将评估在读取输入时启用的内容,并跳过它,直到找到#else或#endif#如果/#ifdef是基于行的,因此您可以通过逐行阅读轻松做到这一点
我在几年前就经历了这个过程,并在我的主页上免费提供下载结果:。该项目是针对Windows.rc文件的解析器,但由于其性质,完全实现了.h文件解析器+表达式计算器、宏扩展等
define_line:
PPHASH 'define' (function_like_define | object_like_define)
;
//--- function like define ---
function_like_define:
ANY_ID '(' parameter_seq? ')' fl_replacement_string
;
parameter_seq: ANY_ID ( ',' ANY_ID)* ;
//--- object like define ---
object_like_define:
ANY_ID ol_replacement_string
;
//fl&ol different names, visitor no need to test parent. Separate rule to make it a single node supporting getText()
fl_replacement_string: any_non_crlf_token*;
ol_replacement_string: any_non_crlf_token*;
any_non_crlf_token:ANY_ID | .....;