Я бы просто обработал такие вещи в грамматике синтаксического анализатора.
Предполагая, что вы строите AST в своей грамматике синтаксического анализатора, я думаю, у вас будет правило для разбора ввода, например Array a = new Array(10);
, подобное:
decl
: TYPE ID '=' expr ';' -> ^(DECL TYPE ID expr)
;
, где expr
в конце концовсоответствует term
следующим образом:
term
: NUMBER
| 'new' ID '(' (expr (',' expr)*)? ')' -> ^('new' ID expr*)
| ...
;
Чтобы учесть короткую комбинацию int a[10];
, все, что вам нужно сделать, это развернуть decl
следующим образом:
decl
: TYPE ID '=' expr ';' -> ^(DECL TYPE ID expr)
| TYPE ID '[' expr ']' ';' -> ^(DECL 'Array' ID ^(NEW ARRAY expr))
;
который перезапишет вход int a[10];
в следующий AST:
![enter image description here](https://i.stack.imgur.com/q8MqC.png)
, который в точности совпадает с AST, созданным для ввода Array a = new Array(10);
.
РЕДАКТИРОВАТЬ
Вот небольшая рабочая демонстрация:
grammar T;
options {
output=AST;
}
tokens {
ROOT;
DECL;
NEW='new';
INT='int';
ARRAY='Array';
}
parse
: decl+ EOF -> ^(ROOT decl+)
;
decl
: type ID '=' expr ';' -> ^(DECL type ID expr)
| type ID '[' expr ']' ';' -> ^(DECL ARRAY ID ^(NEW ARRAY expr))
;
expr
: Number
| NEW type '(' (expr (',' expr)*)? ')' -> ^(NEW ID expr*)
;
type
: INT
| ARRAY
| ID
;
ID : ('a'..'z' | 'A'..'Z')+;
Number : '0'..'9'+;
Space : (' ' | '\t' | '\r' | '\n') {skip();};
, которая может быть протестирована с классом:
import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;
import org.antlr.stringtemplate.*;
public class Main {
public static void main(String[] args) throws Exception {
String src = "Array a = new Array(10); int a[10];";
TLexer lexer = new TLexer(new ANTLRStringStream(src));
TParser parser = new TParser(new CommonTokenStream(lexer));
CommonTree tree = (CommonTree)parser.parse().getTree();
DOTTreeGenerator gen = new DOTTreeGenerator();
StringTemplate st = gen.toDOT(tree);
System.out.println(st);
}
}