【发布时间】:2016-12-20 00:54:45
【问题描述】:
我正在使用 ANTLR4 为一些 JavaScript 预处理器生成 Lexer(基本上它标记一个 javascript 文件并提取每个字符串文字)。
我使用了最初为 Antlr3 制作的语法,并为 v4 导入了相关部分(仅词法分析器规则)。
我只剩下一个问题:我不知道如何处理 RegEx 文字的极端情况,如下所示:
log(Math.round(v * 100) / 100 + ' msec/sample');
/ 100 + ' msec/ 被解释为 RegEx 文字,因为词法分析器规则始终处于活动状态。
我想要合并这个逻辑(C# 代码。我需要 JavaScript,但我不知道如何适应它):
/// <summary>
/// Indicates whether regular expression (yields true) or division expression recognition (false) in the lexer is enabled.
/// These are mutual exclusive and the decision which is active in the lexer is based on the previous on channel token.
/// When the previous token can be identified as a possible left operand for a division this results in false, otherwise true.
/// </summary>
private bool AreRegularExpressionsEnabled
{
get
{
if (Last == null)
{
return true;
}
switch (Last.Type)
{
// identifier
case Identifier:
// literals
case NULL:
case TRUE:
case FALSE:
case THIS:
case OctalIntegerLiteral:
case DecimalLiteral:
case HexIntegerLiteral:
case StringLiteral:
// member access ending
case RBRACK:
// function call or nested expression ending
case RPAREN:
return false;
// otherwise OK
default:
return true;
}
}
}
这条规则作为内联谓词出现在旧语法中,如下所示:
RegularExpressionLiteral
: { AreRegularExpressionsEnabled }?=> DIV RegularExpressionFirstChar RegularExpressionChar* DIV IdentifierPart*
;
但我不知道如何在 ANTLR4 中使用这种技术。
在 ANTLR4 书中,有一些关于在解析器级别解决此类问题的建议(第 12.2 章 - 上下文敏感词法问题),但我不想使用解析器。我只想提取所有标记,除了字符串文字之外的所有内容都保持不变,并且不影响解析。
非常感谢任何建议,谢谢!
【问题讨论】:
-
这显然是一个你无法通过词法单独解决的问题。 Lexing 只为您提供特定输入的标记值。它没有任何信息如何处理该 RE 输入。如果特定输入序列的含义根据某些上下文发生变化,那么您可以仅在解析器端或通过在词法分析后添加语义阶段来手动处理。
-
虽然您的评论是正确的,但当提到词法分析的抽象任务时,在 Antlr3 中,您可以将少量逻辑附加到词法分析器语法中,就像解决我的问题所需要的那样。我在 v3 中不需要解析器。我现在在 v4 中需要它吗?
-
您仍然可以在 ANTLR4 中使用谓词,但 syntax is different。此外,出于性能原因,将谓词放在规则的末尾(或者更好的是,就在第一个
/分隔符字符之后)。