(请奠基左边广告支持哈)
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中选一个元素出来。一个使用新结构的例子如下所示:
这个新的语法接口可以叫做"Select",用"@"符号定义在语法类饮用的的前缀。定义了一个Vector从中选出条件为年纪小于18岁的人群。最后返回满足条件的值,或者返回空值。Select的语法定义如下。
同理,通过 XJ,一个新的语法接口通过定义语义类来定义。一个语义类包括语法由Java解析器来处理具体的程序语法并且返回一个AST。一旦一个语义类被定义,它就能通过在语义定义符号"@"后定义从而在程序代码中被使用。select的结构定义如下:
从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语言的计划。
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<Person> people) {
- @Select Person p from people where p.age < 18 {
- return p;
- }
- else { return null; }
- }
import language mylang.Select; public Person getChild(Vector<Person> people) { @Select Person p from people where p.age < 18 { return p; } else { return null; } }
这个新的语法接口可以叫做"Select",用"@"符号定义在语法类饮用的的前缀。定义了一个Vector从中选出条件为年纪小于18岁的人群。最后返回满足条件的值,或者返回空值。Select的语法定义如下。
- public Person getChild(Vector<Person> 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<Person> 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;
- }
- // 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<T> cType = context.getType(collection);
- if(isVector(cType))
- return desugarVector(cType,contect);
- else // More cases...
- }
- public AST desugarVector(Class<T> cType,Context context) {
- Var done = context.newVar();
- Var coll = context.newVar();
- return
- [| boolean <done> = false;
- <cType> coll = <collection>;
- for(int i = 0; i < <coll>.size(); i++) {
- <underlyingType(cType)> <var> = <coll>.elementAt(i);
- if(<test>) {
- <done> = true;
- <body>;
- }
- }
- if(!<done>)
- <otherwise>;
- |];
- }
- }
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<T> cType = context.getType(collection); if(isVector(cType)) return desugarVector(cType,contect); else // More cases... } public AST desugarVector(Class<T> cType,Context context) { Var done = context.newVar(); Var coll = context.newVar(); return [| boolean <done> = false; <cType> coll = <collection>; for(int i = 0; i < <coll>.size(); i++) { <underlyingType(cType)> <var> = <coll>.elementAt(i); if(<test>) { <done> = true; <body>; } } if(!<done>) <otherwise>; |]; } }
从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语言的计划。
介绍一种扩展Java的方法-XJ,允许用户定义新的语法结构,如Select语法接口,用于从集合中选择符合条件的对象。
1103

被折叠的 条评论
为什么被折叠?



