Java历来是一种以不变应万变的语言。在Java 5中,annotation的引入使得Java在某些特殊的应用场合(如企业应用)中能够进行定制。Annotations 可被看作是用Java核心技术来定义的"领域特定语言"(Domain Specific Languages,DSLs)。
Annotation本质上是一种 name-value 形式的绑定,仅限于它们所能表达的意义。它们不能定义新的语法结构,例如为collection增加个"select"。事实上annotations的存在揭示了Java本身需要DSL的兼容,但是却缺乏能够完全实现DSL所必要的丰富性。
在这里我们为使Java能够支持自定义语义给出了一些建议和方案。如果能够进行一些适当的"扩展"(extension),在不与现有的语法冲突的情况下并且保留向后兼容。例如:用一些语法定义类来产生新的语法结构,姑且称之为 "语义类",这样就能够以现有方式在程序中得以实现。我们把这个方案称之:
XJ (eXtensible Java,可扩展Java)。
XJ给Java带来了这个所谓的"语义类"。一个语义类也是一个有通常语法的的Java类,当Java解析器遇到由语义类定义的语法结构,那么就用语义类中定义的语法来处理这些输入信息。如果解析成功,那这些语法可以合成为一个Java抽象语法树(AST:abstract syntax tree )。一个抽象语法树可以有一个标准接口被Java编译器所使用当处理语法的时候。AST的新类型可以通过实现合适的接口来进行创建。
考虑到JAVA中的一个简单语言结构:依据某些条件从一个collection中选一个元素出来。一个使用新结构的例子如下所示:
- import language mylang.Select;
- public Person getChild(Vector people) {
- @Select Person p from people where p.age < 18 {
- return p;
- }
- else { return null; }
- }
import language mylang.Select;
public Person getChild(Vector people) {
@Select Person p from people where p.age < 18 {
return p;
}
else { return null; }
}
这个新的语法接口可以叫做"Select",用"@"符号定义在语法类饮用的的前缀。定义了一个Vector从中选出条件为年纪小于18岁的人群。最后返回满足条件的值,或者返回空值。Select的语法定义如下。
- public Person getChild(Vector people) {
- for(int i = 0; i < people.size(); i ) {
- Person p = people.elementAt(i);
- if(p.age < 18)
- return p;
- }
- return null;
- }
public Person getChild(Vector people) {
for(int i = 0; i < people.size(); i ) {
Person p = people.elementAt(i);
if(p.age < 18)
return p;
}
return null;
}
同理,通过
XJ,一个新的语法接口通过定义语义类来定义。一个语义类包括语法由Java解析器来处理具体的程序语法并且返回一个AST。一旦一个语义类被定义,它就能通过在语义定义符号"@"后定义从而在程序代码中被使用。select的结构定义如下:
- package mylang;
- import language java.syntax.Grammar;
- import java.syntax.AST;
- import java.syntax.Block;
- import java.syntax.Context;
- import java.syntax.Statement;
- import java.syntax.Sugar;
- import java.syntax.Type;
- import java.syntax.Var;
- public class Select extends Sugar {
- private Type type;
- private Var var;
- private AST collection;
- private AST test;
- private Block body;
- private Block otherwise;
- public Select(Type T,String n,AST c,AST t,Block b,Block o){
- type = T;
- var = new Var(n);
- collection = c;
- test = t;
- body = b;
- otherwise = o;
- }
-
- @Grammar extends Statement {
- Select ::=
- T = Type
- n = Name
- 'from' c = Exp
- 'when' t = Exp
- b = Block
- o = ('else' Block | { return new Block(); })
- { return new Select(T,n,c,t,b,o); }. }
-
- public AST desugar(Context context) {
- Class cType = context.getType(collection);
- if(isVector(cType))
- return desugarVector(cType,contect);
- else
- }
-
- public AST desugarVector(Class cType,Context context) {
- Var done = context.newVar();
- Var coll = context.newVar();
- return
- [| boolean = false;
- coll = ;
- for(int i = 0; i < .size(); i ) {
- = .elementAt(i);
- if() {
- = true;
- ;
- }
- }
- if(!)
- ;
- |];
- }
- }
package mylang;
import language java.syntax.Grammar;
import java.syntax.AST;
import java.syntax.Block;
import java.syntax.Context;
import java.syntax.Statement;
import java.syntax.Sugar;
import java.syntax.Type;
import java.syntax.Var;
public class Select extends Sugar {
private Type type;
private Var var;
private AST collection;
private AST test;
private Block body;
private Block otherwise;
public Select(Type T,String n,AST c,AST t,Block b,Block o){
type = T;
var = new Var(n);
collection = c;
test = t;
body = b;
otherwise = o;
}
// Select Grammar definition
@Grammar extends Statement {
Select ::=
T = Type
n = Name
'from' c = Exp
'when' t = Exp
b = Block
o = ('else' Block | { return new Block(); })
{ return new Select(T,n,c,t,b,o); }. }
// Desugar to produce an abstract syntax tree
public AST desugar(Context context) {
Class cType = context.getType(collection);
if(isVector(cType))
return desugarVector(cType,contect);
else // More cases...
}
public AST desugarVector(Class cType,Context context) {
Var done = context.newVar();
Var coll = context.newVar();
return
[| boolean = false;
coll = ;
for(int i = 0; i < .size(); i ) {
= .elementAt(i);
if() {
= true;
;
}
}
if(!)
;
|];
}
}
从Select的语法规则定义可以看到一个良好格式的语句是通过一个名称,关键字"from"及其表达式,关键字"when"及其表达式,以及定义select块的正文。在正文后,还可以定义if-else之类的可选关键字。在select规则中的每个case中,解析元素产生一个可以和名称可选关联的值。例如,和名称为"T"相关联的类型。另外,解析规则也包含返回值的Java语句。这些包含在{and}中,而且可以引用任何在后面定义的名称。由Select rule返回最终结果是Select类的一个实例。
由语法所决定的返回值必须是java.syntax.AST类的一个实例。如果返回值是标准Java AST类的实例,那在语法类中不需要做特殊处理。如果返回值是自定义语法类的实例,那么这个类必须实现AST接口,来由编译器翻译成Java VM识别的代码。更简单易行的办法是用户自定义语义类从java.syntax.Sugar继承,而java.syntax.Sugar通过desugar方法实现了AST接口。desugar方法负责把输入的信息解释为接口中已经定义的AST(抽象语法树),
在这篇短文中我们介绍了Java的扩展(XJ),主要是通过定义新的Java语法来对Java语言本身进行扩展。虽然XJ还没有在Java中实现,但是它是XMF语言的主要特征。XMF语言已经在商业工具(XMF-Mosaic)中被使用并在2008年
开源。关于本文更多的细节和例子可以参照这篇文章:
超越Annotations:可扩展Java语言的计划。
XJ: 一个扩展Java语言的方案XJ: 一个扩展Java语言的方案XJ: 一个扩展Java语言的方案XJ: 一个扩展Java语言的方案XJ: 一个扩展Java语言的方案XJ: 一个扩展Java语言的方案XJ: 一个扩展Java语言的方案XJ: 一个扩展Java语言的方案XJ: 一个扩展Java语言的方案XJ: 一个扩展Java语言的方案XJ: 一个扩展Java语言的方案XJ: 一个扩展Java语言的方案