ANTLR - 可以在语法中处理具有变量,指定长度的令牌吗?

时间:2011-09-19 17:37:18

标签: antlr grammar

示例字符串

023abc7defghij

标题

字符0,1 =以下块的大小

结块

第一个字符=以下字符串String的长度

以下字符=具有指定长度的字符串

示例结果

所以在上面的例子中,这意味着:

02 - >以下2个块

3 - > 3个字符串将跟随

abc - >三个字符串

7 - >将跟随7个字符串

defghij - >七个字符串

问题

我可以写一个语法,描述这种形式的字符串吗? 我需要解释'length'信息,然后用指定的长度构建标记,用长度信息和字符串填充我的对象。

我希望我可以形容这种可理解性。我无法找到信息,描述或解决我的问题。

1 个答案:

答案 0 :(得分:2)

我假设您的实际问题有点复杂,因为如果"023abc7defghij"是您的实际输入,我不会使用像ANTLR这样的解析器生成器,而只是坚持一些简单的字符串操作。 / p>

那就是说,这是一个可能的解决方案:

由于预先不知道chunks,因此您无法创建除单个DigitOther令牌之外的任何令牌,这些令牌可以是除数字之外的任何字符。请注意,您并不真正需要header信息:您只需解析"3"然后获取接下来的3个字符,然后解析"7"并获得接下来的7个字符,...一直到文件的末尾。

这种语言的语法可能如下所示:

grammar T;

parse
  :  file EOF
  ;

file
  :  header chunk*
  ;

header
  :  Digit Digit
  ;

chunk
  :  Digit any*
  ;

any
  :  Digit
  |  Other
  ;

Digit
  :  '0'..'9'
  ;

Other
  :  .
  ;

但是现在chunk规则含糊不清:它现在不会停止消费字符。这可以使用gated semantic predicate来完成,这会导致* any*在满足特定条件时停止消费(当计数器int n倒计时时,在这种情况下)。

上面的语法包括这个谓词和一些println - 语句看起来像这样:

grammar T;

parse
  :  file EOF
  ;

file
  :  header {System.out.println("header=" + $header.text);}
     (chunk {System.out.println("chunk=" + $chunk.text);})*
  ;

header
  :  Digit Digit
  ;

chunk
  :  Digit {int n = Integer.valueOf($Digit.text);} ({n > 0}?=> any {n--;})*
  ;

any
  :  Digit
  |  Other
  ;

Digit
  :  '0'..'9'
  ;

Other
  :  .
  ;

可以在课堂上进行测试:

import org.antlr.runtime.*;

public class Main {
  public static void main(String[] args) throws Exception {
    String source = "023abc7defghij";
    TLexer lexer = new TLexer(new ANTLRStringStream(source));
    TParser parser = new TParser(new CommonTokenStream(lexer));
    parser.parse();
  }
}

如果您现在生成词法分析器和解析器,请编译所有.java文件并运行Main类:

java -cp antlr-3.3.jar org.antlr.Tool T.g
javac -cp antlr-3.3.jar *.java
java -cp .:antlr-3.3.jar Main

您会看到以下内容正在打印到您的控制台:

header=02
chunk=3abc
chunk=7defghij