ANTLR4 Lexer匹配行终点行

时间:2013-05-05 08:03:46

标签: regex antlr4

如何在ANLTR4词法分析器中实现Perl正则表达式^和$?即。匹配行的开头和行的结尾而不消耗任何字符。

我正在尝试使用ANTLR4词法分析器来匹配行开头的#字符,但不能在行的中间匹配例如,要隔离并抛弃所有C ++预处理器指令,而不管它是哪个指令而忽略了#在字符串文字内。 (通常我们可以对C ++字符串文字进行标记,以消除出现在行中间的#,但假设我们没有这样做)。这意味着我只想指定#。*?没有打扰#if #ifndef #pragma等。

此外,C ++标准允许在#例之前和之后的空白和多行注释。

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

被认为是出现在单行上的有效预处理程序指令。 (ML评论中的CRLF被抛出)

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

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

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

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

如果Perl样式的regex ^ $语法可用,我可以匹配SOL / EOL,而不是显式匹配和使用CRLF。

2 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:1)

您可以尝试使用带门控语义(Different lexer rules in different state)或模式(pushMode - > http://www.antlr.org/wiki/display/ANTLR4/Lexer+Rules)的多个规则,为文件的开头添加备用规则,然后切换到核心指令结束时的规则,但这可能是一项漫长的工作。

首先,或许,我会尝试在解决#pragma / preprocessor指令时确实存在问题而不改变任何东西,因为例如,如果找到#的问题是它可能存在于字符串和注释中,那么只需通过排序您应该能够将规则指向正确的规则(但对于可以在注释中添加指令的语言,这可能是一个问题)。