原文刊登于:
http://www.bitwisemag.com/2/DLR-Build-Your-Own-Language,由Ray Linn翻译,如需转载,请站内告知。
-------------------------------------------------------------------
你曾经为学习一门计算机语言而苦恼么?那好,为啥不丢掉那些C++手册,动手按自己的想法去写一门称心的语言呢?这听起来无比困难,可能只有计算机科学的专家们才能完成,直到最近,两门新的技术让你我一样的普通人编写一门称心的语言成为了可能。首先是ANTLR3,这是广泛应用的ANTLR2解析系统的全新版本(http://www.antlr.org/)。另外一项技术则是微软的新革新“动态语言运行时”-DLR (http://www.codeplex.com/IronPython).
DLR是什么?
了解DLR是什么不是件很容易的事情。关于DLR并没有太多信息,至多只有些片段。开始我以为微软为现有的CLR添加了些新的指令来为动态语言提供帮助,但后来我发现这是错的,DLR压根儿没触及CLR的修改,实际上DLR只是个基于CLR的能运行你的动态语言的程序,这有点像解释器,但它要比通常的解释器聪明得多,也要快得多。事实上,它介于解释器和编译器之间,并带有一些很纯粹的特性来支持动态语言。
顺便说一下,CLR还是JVM谁比较适合支持动态语言是有些争论的。Sun有个实验性的项目叫"Da Vinci Machine“,它试图为JVM提供新指令以支持动态语言。但是,这条路走下坡了,应该在经过很长很长的研究和测试之后才能为JVM或CLR添加指令,因为,虚拟机必须完美瑕疵的工作。所以个人觉得,在新的动态语言指令出现在JVM或CLR之前,我们得等上一段时间了。微软将DLR层叠于CLR之上而不是内嵌于CLR看起来是个更好更实际的方法。
DLR区别于解释器或编译器的地方在于它如何处理动态语言中的“动态”。本质上,动态语言是指在运行时一个对象的类型可以被改变。下面的代码在Java或C#(至少是4.0之前)里都是错误的。
i = 1;
i = "hello";
当然,动态语言的特性远不只这么点:[url="http://en.wikipedia.org/wiki/Dynamic_programming_language"
]这篇文章[/url]很好的介绍了动态语言,不过这两行代码也总结了动态语言是怎么回事儿。上面代码中的"i"的类型从表示一个整数变成了表示一个字符串。这不是啥新东西,微软大肆将VB修改成VB.Net之前有‘variants’ 可变类型,而它的爷爷辈,Lisp语言,也足有50多年的历史了。随着时间的推移,可变类型现在被认为是个“好东西”。
如下所示,DLR保留了关于如何处理加法的规则,并更具类型选择了正确的规则。这些规则就是CLR里的“委托”--本质上就是方法指针-- DRL会在必要使调用。因此,如果变量的类型改变了,新的规则就被调用,如下所示
i = 1;
j = 2;
k = i + j; // integer addition rule invoked
i = "hello";
j = "world";
k = i + j; // string addition rule invoked?
现在问题是,你如何把这些规则告诉DLR?
ANTLR Detour
为了使用DLR,你必须创建抽象语法树AST,AST是程序的符号表达。有两种方法来产生AST,困难的方法或者使用ANTLR。困难的方法是使用传统的yacc/flex解析器和词法分析器。yacc是个LALR(自底向上)解析器能产生状态表然后建立语法树,我个人的感受是,浪费数年光阴在yacc状态表除错上,不如换点有趣的活法。
反之,ANTLR是一种‘递归下降’解析器, 术语叫LL(K). 事实上, ANTLR产生可读性很高的代码,意味着你可以理解和调试。这儿我谈的是ANTLR3。ANTLR3是自由使用的,由Java语言编写,但能够产生诸如java,C#,C++等等目标代码。现在的发布版是3.0.1,但我们真正需要的是下一个发布3.1(还在beta阶段),它能正确链接到DLR.
使用ANTLR来为DLR生成语法树包括三个步骤:
第一、词法分析。语汇分析器定义了语言的符号,例如C#的词法分析器会辨别关键字
“void“和整数"123"。第二、解析。解析器接受词法分析器的成组符号,并创建表达式(用某种语言如英文写就的句子)。解析器会分别正确与错误的表达式。比方说,解析器会接受诸如void abs(){}的表达式,但不会接受void(){}的表达式,即使词法分析器产生的符号是正确的。第三是树语法生成器. ANTLR解析器生成AST,而树语法(tree grammar)告诉ANTLR如何遍历AST并生成DLR代码。
这听起来好像很复杂,实际不然。 ANTLR3句法相当直白,并带丰富的例子,很容易上手。
链接到DLR
一旦你创建了ANTLR的词法分析器、解析器和生成器,接下来你需要创建DLR要使用的对象。DLR在两遍式操作中使用这些对象。首先,当DLR遍历ANTLR生成的AST时对象被创建,这是个标准的OO create操作,例如我们的示例语言的二进制操作符的构造函数:
public MyLBinary(SourceSpan span, int op, MyLExpression left, MyLExpression right)
: base(span) {
_op = op;
_left = left;
_right = right;
}
接下来是当遇到某个语言结构时所调用的“规则”:
protected internal override Expression Generate() {
Expression left = _left.Generate();
Expression right = _right.Generate();
Operators op;
switch (_op) {
case TestLexerLexer.PLUS:
op = Operators.Add;
break;
case TestLexerLexer.MINUS:
op = Operators.Subtract;
break;
case TestLexerLexer.MULTIPLY:
op = Operators.Multiply;
break;
case TestLexerLexer.DIVIDE:
op = Operators.Divide;
break;
default:
throw new System.InvalidOperationException();
}
return Ast.Action.Operator(op, typeof(object), left, right);
}
这儿,‘Generate’方法定义了DLR该为二进制操作做些什么。现在的DLR不需要每次都调用Generate方法,实际上,它通过你定义的规则产生了CLR代码并缓存在DLR规则缓存中。因此,通常,你的规则只被调用了一次,被DLR编译成字节码并被运行。这与普通的解析器每次都遇到二进制操作就再次调用上面的规则是完全不同的。
小结
在这篇文章里,我们了解:
. 用ANTLR3编写分析器-解析器-生成器定义了DLR所要遍历的AST结构。
. DLR遍历该结构偶并随之创建某语言对应操作的对象。
. 当语言被执行时,DLR调用这些对象以获取规则 - 当遇到某种指定的语言结构时,这些代码就被执行。这些规则只会被调用一次,并被编译。
分享到:
相关推荐
而DLR则是建立在CLR之上,为动态语言和C#中的动态类型特性提供支持。 C#中的`dynamic`关键字是DLR的核心,它使得变量的类型在运行时而不是编译时确定。当我们声明一个`dynamic`类型的变量时,编译器不会尝试进行...
LINQ的核心之一是Expression Tree(表达式树),它将代码表达式转化为可遍历的数据结构。这篇博客文章“LINQ与DLR的Expression tree(4):创建静态类型的LINQ表达式树节点”深入探讨了如何构建这种数据结构,特别是...
Boo支持元编程、反射、动态类型检查等高级功能,这使得它成为构建DSLs的理想选择之一。 ### 3. 驱动DSLs发展的因素 随着软件工程复杂度的增加,开发者们开始寻求更高效、更直观的方式来表达业务逻辑,这推动了DSLs...
除了`System.Reflection.Emit`,C# 4.0引入了动态语言运行时(DLR),它提供了一个更高级别的抽象来处理动态操作。DLR支持C#中的`dynamic`关键字,使得编译器在遇到`dynamic`类型时会跳过静态类型检查,在运行时通过...
C# 4.0的主要特点之一是引入了动态类型和动态语言运行时(DLR)。动态类型允许在运行时解析对象类型,这对于在不同语言间的互操作性,以及与动态语言的交互非常有用。书中详细讨论了动态类型和动态语言运行时的使用...
DLR是.NET Framework的一个扩展,它为动态类型语言提供了基础设施,包括操作符重载、元数据访问和动态方法调用。这使得IronPython能够在运行时动态解析和执行代码,极大地提升了灵活性和开发效率。 使用IronPython...
C#作为.NET Framework的主要编程语言之一,充分利用了这个框架提供的强大功能。 ### C# 4.0新特性 C# 4.0引入了一系列新特性,包括动态类型(dynamic type)、并行编程(Parallel Extensions)、动态语言运行时(DLR)...
动态类型(Dynamic Typing)是C# 4.0中的核心特性之一。在C# 3.0及以前的版本中,如果需要调用未知类型的对象的方法,通常需要借助反射等技术。而`dynamic`关键字的出现极大地简化了这一过程。当一个变量声明为`...
- **内容概览:** GHC是最流行的Haskell编译器之一。本章全面介绍了GHC的设计理念、实现细节和性能优化策略。对于学习函数式编程语言Haskell的开发者来说,这是一篇必读的文章。 **6. Git** - **作者:** Susan ...
1. **IronRuby**:IronRuby是Microsoft对Ruby解释器的实现,它利用了.NET平台的动态语言运行时(DLR)。IronRuby让开发者可以利用Ruby的简洁性和灵活性,同时享受到.NET框架提供的跨平台支持、高性能以及丰富的类库...
在.NET Framework 4.0中,最重要的改进之一是引入了CLR(Common Language Runtime)的更新版本,即CLR 4.0。这个版本的运行时引擎对垃圾回收、类型检查和多线程管理进行了优化,提高了应用程序的性能和稳定性。同时...
综上所述,《Satellite Orbits: Models, Methods, and Applications》是一本全面而深入地探讨卫星轨道动力学领域的专著,不仅适合从事航天工程的专业人士参考学习,也是相关专业学生的重要教材之一。
《Professional IronPython》是一本全面而深入地介绍IronPython编程语言的著作,无论是初学者还是有一定经验的开发者,都能从中获得宝贵的指导和启示。通过本书的学习,读者可以系统地掌握IronPython的各项技能,并...
3. **动态语言运行时**:.NET Framework 4.0支持DLR(Dynamic Language Runtime),这使得在.NET平台上更容易地编写和执行动态语言代码。 4. **WCF和WF改进**:Windows Communication Foundation (WCF) 和 Windows ...
《Apress.Pro.CSharp.2010.and.the.dotNET.4.Platform.5th.Edition.May.2010》这本书是C#编程领域的经典之作,它详细讲解了C# 2010语言以及.NET Framework 4平台的相关知识。这本书的第五版发布于2010年5月,旨在...