ANTLR 4:动态令牌

Edg*_*ina 6 antlr4

鉴于:

grammar Hbs;

var: START_DELIM ID END_DELIM;

START_DELIM: '{{';

END_DELIM: '}}';
Run Code Online (Sandbox Code Playgroud)

我想知道如何改变START_DELIM,并END_DELIM在运行时,例如<%%>.

有没有人知道如何在ANTLR 4中做到这一点?

谢谢.

Bar*_*ers 9

有一种方法,但你需要将你的语法与目标语言联系起来(截至目前,唯一的目标是Java).

这是一个快速演示(我包括一些澄清事情的评论):

grammar T;

@lexer::members {

  // Some default values
  private String start = "<<";
  private String end = ">>";  

  public TLexer(CharStream input, String start, String end) {
    this(input);
    this.start = start;
    this.end = end;
  }

  boolean tryToken(String text) {

    // See if `text` is ahead in the CharStream.
    for(int i = 0; i < text.length(); i++) {

      if(_input.LA(i + 1) != text.charAt(i)) {

        // Nope, we didn't find `text`.
        return false;
      }
    }

    // Since we found the text, increase the CharStream's index.
    _input.seek(_input.index() + text.length() - 1);

    return true;
  }
}

parse
 : START ID END
 ;

START
 : {tryToken(start)}? . 
   // The `.` is needed because a lexer rule must match at least 1 char.
 ;

END
 : {tryToken(end)}? .
 ;

ID
 : [a-zA-Z]+
 ;

SPACE
 : [ \t\r\n] -> skip
 ;
Run Code Online (Sandbox Code Playgroud)

{ ... }?是一个语义谓词.请参阅:https://github.com/antlr/antlr4/blob/master/doc/predicates.md

这是一个小测试类:

import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.*;

public class Main {

  private static void test(TLexer lexer) throws Exception {
    TParser parser = new TParser(new CommonTokenStream(lexer));
    ParseTree tree = parser.parse();
    System.out.println(tree.toStringTree(parser));
  }

  public static void main(String[] args) throws Exception {

    // Test with the default START and END.
    test(new TLexer(new ANTLRInputStream("<< foo >>")));

    // Test with a custom START and END.
    test(new TLexer(new ANTLRInputStream("<? foo ?>"), "<?", "?>"));
  }
}
Run Code Online (Sandbox Code Playgroud)

按如下方式运行演示:

*nix中

java -jar antlr-4.0-complete.jar T.g4
javac -cp .:antlr-4.0-complete.jar *.java
java -cp .:antlr-4.0-complete.jar Main
Run Code Online (Sandbox Code Playgroud)

视窗

java -jar antlr-4.0-complete.jar T.g4
javac -cp .;antlr-4.0-complete.jar *.java
java -cp .;antlr-4.0-complete.jar Main
Run Code Online (Sandbox Code Playgroud)

你会看到以下内容被打印到控制台:

(parse << foo >>)
(parse <? foo ?>)
Run Code Online (Sandbox Code Playgroud)