ANTLR AST Grammar Tree + Lists

I read a lot while trying to find a way to cleanly use lists in the ANTLR tree grammar. Here is what I tried and their results (I really hope that I am missing something trivial) ...

Usage + = Syntax

program returns [someInterface result] : m+=method* EOF {result = new SomeClass(m);}; method returns [SomeMethod result] : <definition here> 

This is not with ...

'+ =' rule list labels are not allowed without output option

If I set the output to "AST" or "template" (the only options), then the method signatures of the generated class are changed. That is, m will not consist of a list of SomeMethod (s), but rather a list of nodes or templates, respectively. I am open to suggestions if there is a way to make this method work.

Using rule areas

 program returns [CompilesToJavaByteCode result] scope { List<SomeMethod> methods; } @init { $program::methods = new ArrayList<SomeMethod>(); } : (m=method {$program::methods.add(m);})* EOF {result = new SomeClass($program::methods);}; 

This seems to work, although I admit that I have not tested it with nested / recursive cases yet.

Final goal

I want to create a set of classes that represent my language (class, method, variable, Statement, ect) so that I can do some static analysis and optimization before generating the compiled code. For this, I need to be able to use lists. I was expecting the + = syntax to "just work", but I might be missing out on something. The second method works, but it looks too verbose and inelegant.

Question

What is the correct use of lists in the grammar of the ANTLR tree to navigate to my specific classes?

+4
source share
1 answer

You can cut out a region from your example and do it all with local variables.

 program returns [CompilesToJavaByteCode result] @init { List<SomeMethod> methods = new ArrayList<SomeMethod>(); } : (m=method { methods.add($m.result); })* EOF { $result = new SomeClass(methods); }; 

This is what we do for this case at work. Another option is for your method rule to handle it:

 program returns [CompilesToJavaByteCode result] @init { List<SomeMethod> methods = new ArrayList<SomeMethod>(); } : method[methods]* EOF { $result = new SomeClass(methods); }; method [List<SomeMethod> methods] : ... { methods.add(new SomeMethod(...); }; 

I do not like the second option, since the rule of the method probably should not worry about what is being done with its results. But you can imagine a structure in which the top rule creates a ClassBeingCompiled , and the rest of the code gradually fills it with .addMethod() .

+6
source

Source: https://habr.com/ru/post/1346403/


All Articles