6

如何在 ANLTR4 词法分析器中实现 Perl 正则表达式 ^ 和 $?IE。在不消耗任何字符的情况下匹配行首和行尾。

我正在尝试使用 ANTLR4 词法分析器来匹配行首的 # 字符,但不在行的中间例如,隔离并丢弃所有 C++ 预处理器指令,无论它是哪个指令,同时忽略 a 中的 #字符串字面量。(通常我们可以标记 C++ 字符串文字以消除出现在行中间的 # 但假设我们没有这样做)。这意味着我只想指定 # .*? 无需打扰#if #ifndef #pragma 等。

此外,C++ 标准允许在 # 之前和之后使用空格和多行注释,例如

   /* helo
world*/  #  /* hel
l
o
*/  /*world */ifdef .....

被认为是出现在单行上的有效预处理器指令。(ML COMMENT 中的 CRLF 被扔掉了)

这就是我目前正在做的事情:

PPLINE: '\r'? '\n' (ML_COMMENT | '\t' | '\f' |' ')* '#' (ML_COMMENT | ~[\r\n])+ -> channel(PPDIR); 

但问题是我必须依赖 # 之前存在 CRLF 并将该 CRLF 与指令一起丢弃。我需要替换由该指令行的 CRLF 抛出的 CRLF,因此我必须确保该指令由 CRLF 终止。

但是,这意味着我的语法无法处理出现在文件开头的指令(即没有前面的 CRLF)或前面有 EOF 而不终止 CRLF。

如果 Perl 风格的正则表达式 ^ $ 语法可用,我可以匹配 SOL/EOL 而不是显式匹配和使用 CRLF。

4

2 回答 2

5

您可以对条件使用语义谓词。

PPLINE
    :   {getCharPositionInLine() == 0}?
        (ML_COMMENT | '\t' | '\f' |' ')* '#' (ML_COMMENT | ~[\r\n])+
        {_input.LA(1) == '\r' || _input.LA(1) == '\n'}?
        -> channel(PPDIR)
    ;
于 2013-05-05T17:37:35.430 回答
1

您可以尝试使用门控语义(不同状态下的不同词法分析器规则)或模式(pushMode -> http://www.antlr.org/wiki/display/ANTLR4/Lexer+Rules)的多个规则,有一个替代规则文件的开头,然后在指令结束时切换到核心规则,但这可能是一项漫长的工作。

首先,也许,如果在不更改任何内容的情况下解析#pragma/preprocessor 指令时确实存在问题,我会尝试,因为例如,如果查找# 的问题可能出现在字符串和注释中,那么只需对规则进行排序即可应该能够将它指向正确的情况(但这对于可以在注释中放置指令的语言来说可能是一个问题)。

于 2013-05-05T10:47:05.477 回答