如何使用 ANTLR4 解析速度变量

How to parsing Velocity Variables using ANTLR4

Velocity变量有如下表示法。 (参见 Velocity User Guide):

The shorthand notation of a variable consists of a leading "$" character followed by a VTL Identifier. A VTL Identifier must start with an alphabetic character (a .. z or A .. Z). The rest of the characters are limited to the following types of characters:

  • alphabetic (a .. z, A .. Z)
  • numeric (0 .. 9)
  • underscore ("_")

我想使用词法分析器模式来拆分普通文本和变量,所以我写了这样的东西:

// default mode
DOLLAR : ‘$’ -> pushMode(VARIABLE);
TEXT : ~[$]+? -> skip;

mode VARIABLE:
ID : [a-zA-Z] [a-zA-Z0-9-_]*;
???? : XXX -> popMode;   // how can I pop mode to default?

因为变量的表示法没有明确的结束字符,所以我不知道如何确定它的结束。

也许我听错了?

你会像这样跳出那个范围:

mode VARIABLE;
  ID  : [a-zA-Z] [a-zA-Z0-9-_]* -> popMode;

这是一个快速演示:

lexer grammar VelocityLexer;

DOLLAR : '$' -> more, pushMode(VARIABLE);
TEXT   : ~[$]+ -> skip;

mode VARIABLE;
  // the `-` needs to be escaped!
  ID : [a-zA-Z] [a-zA-Z0-9\-_]* -> popMode;

注意 DOLLAR 中的 more,这将导致 $ 包含在 ID 标记中。如果不这样做,您最终会得到两个标记($foo 输入 $foo

使用以下内容测试语法 Java class:

import org.antlr.v4.runtime.*;

public class Main {

  public static void main(String[] args) {

    VelocityLexer lexer = new VelocityLexer(CharStreams.fromString("<strong>$Mu</strong>$foo..."));
    CommonTokenStream tokenStream = new CommonTokenStream(lexer);
    tokenStream.fill();

    for (Token t : tokenStream.getTokens()) {
      System.out.printf("%-10s '%s'\n", VelocityLexer.VOCABULARY.getSymbolicName(t.getType()), t.getText());
    }
  }
}

这将打印:

ID         '$Mu'
ID         '$foo'
EOF        '<EOF>'

但是,我认为在 ID 的情况下,词法模式不是一个好的选择。为什么不简单地做:

lexer grammar VelocityLexer;

DOLLAR : '$' [a-zA-Z] [a-zA-Z0-9\-_]*;
TEXT   : ~[$]+ -> skip;

?