我为一种语言编写了一个语法,现在我想处理一些语法糖结构,因为我正在考虑编写一个模板翻译器。
问题是我希望我的模板语法只翻译语言的一些结构,并保留原样。
例如:
我将此作为输入:
class Main {
int a[10];
}
我希望将其翻译成:
class Main {
Array a = new Array(10);
}
理想情况下,我想在ANTLR
中做一些这样的思考grammer Translator
options { output=template;}
decl
: TYPE ID '[' INT ']' -> template(name = {$ID.text}, size ={$INT.text})
"Array <name> = new Array(<size>);
我希望将剩下的输入与规则decl不匹配。
如果没有为该语言编写完整的语法,我怎样才能在ANTLR中实现这一目标?
答案 0 :(得分:1)
我只是在解析器语法中处理这些事情。
假设您在解析器语法中构建了一个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:
与为输入Array a = new Array(10);
创建的AST完全相同。
这是一个小型的工作演示:
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);
}
}