如何在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。
答案 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指令时确实存在问题而不改变任何东西,因为例如,如果找到#的问题是它可能存在于字符串和注释中,那么只需通过排序您应该能够将规则指向正确的规则(但对于可以在注释中添加指令的语言,这可能是一个问题)。