在ANTLR中,如何指定具体的重复次数?

发布于 2024-08-24 23:59:23 字数 142 浏览 5 评论 0原文

我使用 ANTLR 指定包含不能超过 254 个字符的行(不包括行结尾)的文件格式。我如何在语法中对其进行编码,缺少这样做:

line : CHAR? CHAR? CHAR? CHAR? ... (254 times)

I'm using ANTLR to specify a file format that contains lines that cannot exceed 254 characters (excluding line endings). How do I encode this in the grammer, short of doing:

line : CHAR? CHAR? CHAR? CHAR? ... (254 times)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

猫九 2024-08-31 23:59:24

这可以通过使用语义谓词来处理。

首先以这样的方式写你的语法,无论你的行有多长。示例如下:

grammar Test;

parse
  :  line* EOF
  ;

line
  :  Char+ (LineBreak | EOF)
  |  LineBreak // empty line!
  ;

LineBreak : '\r'? '\n' | '\r' ;
Char      : ~('\r' | '\n') ;

然后将“谓词”添加到 line 规则中:

grammar Test;

@parser::members {
    public static void main(String[] args) throws Exception {
        String source = "abcde\nfghij\nklm\nnopqrst";
        ANTLRStringStream in = new ANTLRStringStream(source);
        TestLexer lexer = new TestLexer(in);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        TestParser parser = new TestParser(tokens);
        parser.parse();
    }  
}

parse
  :  line* EOF
  ;

line
  :  (c+=Char)+ {$c.size()<=5}? (LineBreak | EOF)
  |  LineBreak // empty line!
  ;

LineBreak : '\r'? '\n' | '\r' ;
Char      : ~('\r' | '\n') ;

c+=Char 将构造一个包含所有内容的 ArrayList行中的字符。当 ArrayList 的大小超过 5 时,{$c.size()<=5}? 会引发异常。

我还在解析器,这样你就可以自己测试它:

// *nix/MacOSX
java -cp antlr-3.2.jar org.antlr.Tool Test.g
javac -cp antlr-3.2.jar *.java
java -cp .:antlr-3.2.jar TestParser

// Windows
java -cp antlr-3.2.jar org.antlr.Tool Test.g
javac -cp antlr-3.2.jar *.java
java -cp .;antlr-3.2.jar TestParser

它将输出:

line 0:-1 rule line failed predicate: {$c.size()<=5}?

HTH

This can be handled by using a semantic predicate.

First write your grammar in such a way that it does not matter how long your lines are. An example would look like this:

grammar Test;

parse
  :  line* EOF
  ;

line
  :  Char+ (LineBreak | EOF)
  |  LineBreak // empty line!
  ;

LineBreak : '\r'? '\n' | '\r' ;
Char      : ~('\r' | '\n') ;

and then add the "predicate" to the line rule:

grammar Test;

@parser::members {
    public static void main(String[] args) throws Exception {
        String source = "abcde\nfghij\nklm\nnopqrst";
        ANTLRStringStream in = new ANTLRStringStream(source);
        TestLexer lexer = new TestLexer(in);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        TestParser parser = new TestParser(tokens);
        parser.parse();
    }  
}

parse
  :  line* EOF
  ;

line
  :  (c+=Char)+ {$c.size()<=5}? (LineBreak | EOF)
  |  LineBreak // empty line!
  ;

LineBreak : '\r'? '\n' | '\r' ;
Char      : ~('\r' | '\n') ;

The c+=Char will construct an ArrayList containing all characters in the line. The {$c.size()<=5}? causes to throw an exception when the ArrayList's size exceeds 5.

I also added a main method in the parser so you can test it yourself:

// *nix/MacOSX
java -cp antlr-3.2.jar org.antlr.Tool Test.g
javac -cp antlr-3.2.jar *.java
java -cp .:antlr-3.2.jar TestParser

// Windows
java -cp antlr-3.2.jar org.antlr.Tool Test.g
javac -cp antlr-3.2.jar *.java
java -cp .;antlr-3.2.jar TestParser

which will output:

line 0:-1 rule line failed predicate: {$c.size()<=5}?

HTH

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文