如何使用ANTLR4解析速度变量

时间:2018-04-23 13:34:11

标签: parsing antlr4 velocity

Velocity的变量有以下符号。 (见Velocity User Guide):

  

变量的简写符号由一个前导" $"字符后跟VTL标识符。 VTL标识符必须以字母字符(a .. z或A .. Z)开头。其余字符仅限于以下类型的字符:

     
      
  • 字母(a .. z,A .. Z)
  •   
  • 数字(0 .. 9)
  •   
  • 下划线(" _")
  •   

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

// 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?

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

也许我弄错了?

1 个答案:

答案 0 :(得分:0)

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

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;

请注意more中的DOLLAR$会导致ID令牌中包含$。如果您没有,则最终会输入两个令牌(foo$foo作为输入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()); } } }

使用以下Java类测试语法:

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

将打印:

ID

但是,我觉得如果lexer grammar VelocityLexer; DOLLAR : '$' [a-zA-Z] [a-zA-Z0-9\-_]*; TEXT : ~[$]+ -> skip; ,词汇模式不是一个好的选择。为什么不简单地做:

{{1}}