Antlr 数组帮助

发布于 2024-10-06 05:01:03 字数 78 浏览 1 评论 0 原文

嘿,我开始在 java 中使用 Antlr,我想知道如何将一些值直接存储到二维数组中并返回该数组?我根本找不到任何关于此的教程,感谢所有帮助。

Hey ive started to use Antlr with java and i wanted to know how i can store some values directly into a 2d array and return this array? i cant find any tutorials on this at all, all help is apperciated.

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

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

发布评论

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

评论(2

哆啦不做梦 2024-10-13 05:01:03

假设您想要解析一个包含由空格分隔的数字的平面文本文件。您想将其解析为 int 的二维数组,其中每一行都是数组中的一个“行”。

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

grammar Number;

parse
  :  line* EOF
  ;

line
  :  Number+ (LineBreak | EOF)
  ;

Number
  :  ('0'..'9')+
  ;

Space
  :  (' ' | '\t') {skip();}
  ;

LineBreak
  :  '\r'? '\n'
  |  '\r'
  ;

现在,您希望 parse 规则返回 List< 的 List /代码> 对象。通过添加 returns [List> 来做到这一点number] 在您的 parse 规则之后,可以在 @init{ ... } 块中初始化:

parse returns [List<List<Integer>> numbers]
@init {
  $numbers = new ArrayList<List<Integer>>();
}
  :  line* EOF
  ;

您的 line 规则看起来有点相同,只是它返回一维数字列表:

line returns [List<Integer> row]
@init {
  $row = new ArrayList<Integer>();
}
  :  Number+ (LineBreak | EOF)
  ;

下一步是用正在解析的实际值填充List。这可以通过在 lineNumber+ 循环内嵌入代码 {$row.add(Integer.parseInt($Number.text));} 来完成。 /code> 规则:

line returns [List<Integer> row]
@init {
  $row = new ArrayList<Integer>();
}
  :  (Number {$row.add(Integer.parseInt($Number.text));})+ (LineBreak | EOF)
  ;

最后,您需要添加由 line 规则返回的 List,以实际添加到您的 2D 数字parse 规则中的 code> 列表:

parse returns [List<List<Integer>> numbers]
@init {
  $numbers = new ArrayList<List<Integer>>();
}
  :  (line {$numbers.add($line.row);})* EOF
  ;

下面是最终语法:

grammar Number;

parse returns [List<List<Integer>> numbers]
@init {
  $numbers = new ArrayList<List<Integer>>();
}
  :  (line {$numbers.add($line.row);})* EOF
  ;

line returns [List<Integer> row]
@init {
  $row = new ArrayList<Integer>();
}
  :  (Number {$row.add(Integer.parseInt($Number.text));})+ (LineBreak | EOF)
  ;

Number
  :  ('0'..'9')+
  ;

Space
  :  (' ' | '\t') {skip();}
  ;

LineBreak
  :  '\r'? '\n'
  |  '\r'
  ;

可以使用以下类进行测试:

import org.antlr.runtime.*;
import java.util.List;

public class Main {
    public static void main(String[] args) throws Exception {
        String source = 
                "1 2       \n" +
                "3 4 5 6 7 \n" +
                "      8   \n" +
                "9 10 11     ";
        ANTLRStringStream in = new ANTLRStringStream(source);
        NumberLexer lexer = new NumberLexer(in);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        NumberParser parser = new NumberParser(tokens);
        List<List<Integer>> numbers = parser.parse();
        System.out.println(numbers);
    }
}

现在从语法生成词法分析器和解析器:

java -cp antlr-3.2.jar org.antlr.Tool Number.g

编译所有 .java 源文件:

javac -cp antlr-3.2.jar *.java

并运行主类:

// On *nix
java -cp .:antlr-3.2.jar Main

// or Windows
java -cp .;antlr-3.2.jar Main

产生以下输出:

[[1, 2], [3, 4, 5, 6, 7], [8], [9, 10, 11]]

HTH

Let's say you want to parse a flat text file containing numbers separated by spaces. You'd like to parse this into a 2d array of int's where each line is a "row" in your array.

The ANTLR grammar for such a "language" could look like:

grammar Number;

parse
  :  line* EOF
  ;

line
  :  Number+ (LineBreak | EOF)
  ;

Number
  :  ('0'..'9')+
  ;

Space
  :  (' ' | '\t') {skip();}
  ;

LineBreak
  :  '\r'? '\n'
  |  '\r'
  ;

Now, you'd like to have the parse rule return an List of List<Integer> objects. Do that by adding a returns [List<List<Integer>> numbers] after your parse rule which can be initialized in an @init{ ... } block:

parse returns [List<List<Integer>> numbers]
@init {
  $numbers = new ArrayList<List<Integer>>();
}
  :  line* EOF
  ;

Your line rule looks a bit the same, only it returns a 1 dimensional list of numbers:

line returns [List<Integer> row]
@init {
  $row = new ArrayList<Integer>();
}
  :  Number+ (LineBreak | EOF)
  ;

The next step is to fill the Lists with the actual values that are being parsed. This can be done embedding the code {$row.add(Integer.parseInt($Number.text));} inside the Number+ loop in your line rule:

line returns [List<Integer> row]
@init {
  $row = new ArrayList<Integer>();
}
  :  (Number {$row.add(Integer.parseInt($Number.text));})+ (LineBreak | EOF)
  ;

And lastly, you'll want to add the Lists being returned by your line rule to be actually added to your 2D numbers list from your parse rule:

parse returns [List<List<Integer>> numbers]
@init {
  $numbers = new ArrayList<List<Integer>>();
}
  :  (line {$numbers.add($line.row);})* EOF
  ;

Below is the final grammar:

grammar Number;

parse returns [List<List<Integer>> numbers]
@init {
  $numbers = new ArrayList<List<Integer>>();
}
  :  (line {$numbers.add($line.row);})* EOF
  ;

line returns [List<Integer> row]
@init {
  $row = new ArrayList<Integer>();
}
  :  (Number {$row.add(Integer.parseInt($Number.text));})+ (LineBreak | EOF)
  ;

Number
  :  ('0'..'9')+
  ;

Space
  :  (' ' | '\t') {skip();}
  ;

LineBreak
  :  '\r'? '\n'
  |  '\r'
  ;

which can be tested with the following class:

import org.antlr.runtime.*;
import java.util.List;

public class Main {
    public static void main(String[] args) throws Exception {
        String source = 
                "1 2       \n" +
                "3 4 5 6 7 \n" +
                "      8   \n" +
                "9 10 11     ";
        ANTLRStringStream in = new ANTLRStringStream(source);
        NumberLexer lexer = new NumberLexer(in);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        NumberParser parser = new NumberParser(tokens);
        List<List<Integer>> numbers = parser.parse();
        System.out.println(numbers);
    }
}

Now generate a lexer and parser from the grammar:

java -cp antlr-3.2.jar org.antlr.Tool Number.g

compile all .java source files:

javac -cp antlr-3.2.jar *.java

and run the main class:

// On *nix
java -cp .:antlr-3.2.jar Main

// or Windows
java -cp .;antlr-3.2.jar Main

which produces the following output:

[[1, 2], [3, 4, 5, 6, 7], [8], [9, 10, 11]]

HTH

淡墨 2024-10-13 05:01:03

以下是我编写的语法的一些摘录,该语法解析人名并返回 Name 对象。应该足以向您展示它是如何工作的。其他对象(例如数组)也以同样的方式完成。

在语法中:

grammar PersonNames;

fullname returns [Name name]
@init {
    name = new Name();
}
  : (directory_style[name] | standard[name] | title_without_fname[name] |      family_style[name] | proper_initials[name]) EOF;

standard[Name name]
 : (title[name] ' ')* fname[name] ' ' (mname[name] ' ')* (nickname[name] ' ')? lname[name] (sep honorifics[name])*;

 fname[Name name] : (f=NAME | f=INITIAL)  { name.set(Name.Part.FIRST, toNameCase($f.text)); };

在常规 Java 代码中

public static Name parseName(String str) throws RecognitionException {
    System.err.println("parsing `" + str + "`");
    CharStream stream = new ANTLRStringStream(str);
    PersonNamesLexer lexer = new PersonNamesLexer(stream);
    CommonTokenStream tokens = new CommonTokenStream(lexer);
    PersonNamesParser parser = new PersonNamesParser(tokens);

    return parser.fullname();
}

Here's some excerpts from a grammar I made that parses people's names and returns a Name object. Should be enough to show you how it works. Other objects such as arrays are done the same way.

In the grammar:

grammar PersonNames;

fullname returns [Name name]
@init {
    name = new Name();
}
  : (directory_style[name] | standard[name] | title_without_fname[name] |      family_style[name] | proper_initials[name]) EOF;

standard[Name name]
 : (title[name] ' ')* fname[name] ' ' (mname[name] ' ')* (nickname[name] ' ')? lname[name] (sep honorifics[name])*;

 fname[Name name] : (f=NAME | f=INITIAL)  { name.set(Name.Part.FIRST, toNameCase($f.text)); };

in your regular Java code

public static Name parseName(String str) throws RecognitionException {
    System.err.println("parsing `" + str + "`");
    CharStream stream = new ANTLRStringStream(str);
    PersonNamesLexer lexer = new PersonNamesLexer(stream);
    CommonTokenStream tokens = new CommonTokenStream(lexer);
    PersonNamesParser parser = new PersonNamesParser(tokens);

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