




已阅读5页,还剩62页未读, 继续免费阅读
(计算机软件与理论专业论文)支持静态元编程的可扩展式开放编译器的研究与实现.pdf.pdf 免费下载
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
支持静态元编程的可扩展式开放编译器的研究与实现 摘要 摘要 在很多情况下,由于受表达机制( 语法构造,控制结构,组合手段等) 的限制,我们无 法用通用编程语言来构建一个清晰、自然和高效的解决方案。而这时针对特定问题的领域特 定语言则是一个很好的选择。因此,如果开发人员能够方便地创造适合他们自己需求的领域 特定语言将是极有意义的。 本文以动态语言l u a 为例,设计并实现了一个支持静态元编程的可扩展式开放l u a 编 译器o p e n l u a ,它能够支持程序员在无需改动编译器的情况下扩展语言的语法设施, 从而快速地构造出领域特定语言。 文章首先介绍了静态元编程和开放式编译器的基本概念,也简要介绍了标准l u a 语言, 同时还对o p e n l u a 做了一个概览。 接着详细描述了o p e n l u a 在语言层面对标准l u a 所做的扩展,包括o p e n l u a 为了支 持静态元编程和自定义语法而为标准l u a 语言引入的3 个新的语法设施用户自定义语 法,源代码转换子,编译期模块导入。跟着介绍了o p e n l u a 编译器为静态元程序提供的可 编程接口和运行环境。 然后详细描述了o p e n l u a 编译器的实现包括作为o p e n l u a 开放式架构基础的开放 式词法分析算法、开放式s l r 解析算法以及用户自定义语法的确定性递归下降解析算法等。 接着解释了编译器如何处理与静态元编程相关的3 个新的语法设施和转换子调用,即它们 的语义。然后还深入探讨了编译器提供的可编程接口和元程序运行环境的实现。 随后作者通过给出o p e n l u a 的若干有趣应用来展示开放式架构可以如何支持语言的扩 展。也介绍了该领域的相关研究工作,并将o p e n l u a 与它 f 】傲了比较,最后分析总结了 o p e n l u a 的不足,并提出了相应的改进计划。 关键词元编程:开放式编译器i 可扩展式语言;l u a 1 x 支持静态元编程的可扩展式开放编译器的研究与实瑰a b s t r a c t g e n e r a lp u r p o s ep r o g r a m m i n gl a n g u a g es o m e t i m e sc a nn o tb eu s e dt o 8 0 l v es o m e p r o b l e m sn a t u r a l l y a n d e f f e c t i v e l y , b e c a u s eo ft h e l i m i t a t i o n so ft h el a n g u a g e se x p r e s s i v ep o w e r s y n t a xc o n s t r u c t s , c o n t r o l s t r u c t u r e s , c o m b i n a t i o nm e a n se t c ) a tt h a t 七i m e , a d o m a i n s p e c i f i cl a n g u a g ew i l lb eaq o o dc h o i c e s oi t ss i g n i f i c a n t t h a tp r o g r a r n m e r sc a nc r e a t ead s lc o n v e n i e n 七l yf o rt h e i ro w n p u r p o s e s id e s i g na n di m p l e m e n ta ne x t e n s i b l eo p e nc o m p i l e rs u p p o r t i n g s t a t i cm e t a p r o g r a 舢i n gn a m e d o p e n l u a i nt h i s p a p e r i t a 1 1 0 w s p r o g r a r n m e rt oc r e a t ead s lr a p i d l y b yi n 七o d u c i n gn e ws y n t a xc o n s t r u c 七s a t f i r s t , t h e r ei sai n t r o d u c t i o nt 0 m e t a p r o g r a m m i n g ,o p e n c o m p i l e r , a n dl u a1 a n g u a g e a no v e r v i e wo f ( ) p e n l u a f o l l o w s t h e nid e s c r i b et h el a n g u a g ee x t e n s i o n sm a d et ol u ab y0 p e n l u a , w h i c h i n c l u d et h r e en e wc o n s 七r u c t s : u s e r d e i n e ds y n t a x ,s o u r c e t r a n s f o r m e r , a n dm o d u l ei m p o r t a t i o n , a n dh o wc o m p i l e rd e a l sw i 七h t h e m,n a m e l y七h e i rs e m a n t i c s t h e nt h ec o n c r e t e a l g o r i t h m sa r e i l l u s t r a t e d ,w h i c hi n c l u d e so p e nl e x c i a la n a l y 3 i s ,o p e ns l rp a r s i n g , a n dp r e d i c t i v er e c u r s i v e d e 8 c e n tp a r s i n g ,e t c a n da l s oy o uc a ns e e t h ed e t a i l so ft h ee x p o s e dp r o g r a r n m a b l ei n t e r f a c e so fo p e n l u aa n dt h e e x e c u t i o ne n v i r o n m e n to fm e t a p r o g r a m 。a f t e r 七h a t ,i tw i l lb ee x p l a i n e d t h a th o wt op e r f o r ma8 0 u r c et r a n 8 f o r m a t i o n iu s es o m ei n t e r e s t i n ge x a m p l e st od e m o n s t r a t eh o wo p e n l u ac a nb e u s e dt oe x t e n dt h ep r o g r a l 鼬i n gl a n g u a g e a n dt h e nr e a d e r sc a ns e es o m e r e l a t e dw o r ki nt h i sa r e a a tl a s t , is u 舳a r i z es o m es h o r c o m m i n g so f o p e n l u aa n dg i v eap l a n0 fi m p r o v e m e n t 8i nt h ef u t u r e 甙j 曩y 材o r 由 m e t a p r o g r a 衄i n g ;o p e nc o 如p i l e r ;e x t e n s i b l el a n g u a g e ,l u a 支持静态元蝙程的可扩展式开放编译器的研究与实现 目录 4 3 2 循环编译, 4 4 面向方面的骗程与静态代码织入 4 5 为l u a 引入契约式开发机制 4 5 1 契约式开发简介 4 5 2 支持契约机制的运行时标准l u a 扩展库 q 5 3 利用o p e n l u a 改善后的契约机制的实现 第5 章相关研究工作, 5 1 l i s p 的可编程宏系统 5 2 基于抽象语法树数据类型和语法模板置换的宏系统 5 3c h 模板元编程技术, 5 4 利用自省机制及元对象协议的开放系统 5 5 意图编程 s 6 其它工作 5 7 小结 第6 章总结与改进计划 6 1 编译终止问题,。 6 2 编译时间 6 3 用户自定义语法的描述 6 具体语法树的操作, 6 5 静态元程序的调试 6 6 编译器的开放程度 附录ao p e n l u a 语法( b n f 格式) ,。 附录bo p e n l u a 操作符优先级定义表, 参考文献, 攻读硬士学位期间发表的学术论文 图目录 圈l 一1 利用元表构建的单继承对象模型 图2 1o p e n l u a 的编译过程 v i 3 8 3 9 d 1 4 1 2 4 2 6 4 6 日7 4 7 4 8 8 5 0 5 0 5 1 。5 1 5 1 5 1 。5 2 5 2 5 2 ,5 4 5 7 5 8 6 l 5 b 支持静态元编程的可扩展式开放编译器的研究与实现 目录 图3 1 词法分析器与输入流示意图 图3 2 开放式词法分析器p e e k 动作流程图 图3 3 开放式s l r 解析算法流程图 图3 4 用户自定义语法解析算法流程图 图3 5p a r s e 接口闭包的内存布局 图3 6 转换子调用动作流程图 示例代码目录 程序l l 用表来实现对象3 程序1 2 实例化( i n s t a n t i a t i o n l 与派生( d e r i v a t i o n )5 程序3 一l 一个用户自定义语法的例子1 0 程序3 2m e t a 转换子的定义1 3 程序3 3 几种具有歧义的语句2 0 程序3 4 创建闭包的示例2 9 程序4 1 简单条件编译结构。3 7 程序4 2 多分支条件编译结构3 8 程序4 3 循环编译结构示例3 8 程序4 4l o g 转换子使用示例4 0 程序4 5l o g 修饰的函数被编译后生成的标准l u a 代码4 1 程序4 6 书写不变式、前置断言和后置断言的新语法4 3 程序4 7 改进后的契约机制的使用4 4 v 1 1 “ ” 拍 孙 孔 ” 学位论文独创性声明 本人所呈交的学位论文是我在导师的指导下进行的研究工作及 取得的研究成果据我所知,除文中已经注明引用的内容外,本论文 不包含其他个人已经发表或撰写过的研究成果对本文的研究做出重 要贡献的个人和集体,均巳在文中作了明确说明并表示谢意 作者签名:翟叠五整 作者签名:趱必彳至 学位论文授权使用声明 本人完全了解华东师范大学有关保留、使用学位论文的规定,学 校有权保留学位论文并向国家主管部门或其指定机构送交论文的电 子版和纸质版有权将学位论文用于非赢利目的的少量复制并允许论 文进入学校图书馆被查阅有权将学位论文的内容编入有关数据库进 行检索有权将学位论文的标题和摘要汇编出版保密的学位论文在 解密后适用本规定。 学位论文作者签名:砷际锑导师签名:狄娩戈 日期型至至! 支持静态元编程的可扩展式开放编译器的研究与实现致谢 致谢 首先,感谢我的导师张桂戌老师在学术研究上,张老师充分尊重我的意愿,让我根据 兴趣自主发展,而他则在旁边适时引导。这种开放、民主的学术作风使我真正享受到了学习 和研究的快乐。在毕业论文的撰写过程中,张老师又仔细地审阅,并耐心地提出建议和意见 这大大提高了本文的质量但是毫无疑问剩下的所有错误仍应由我个人负责。生活上张老 师也一直对我关心照顾,给予了许多无私的帮助。在我攻读硕士学位即将结束之际,特向张 老师表示衷心的感谢! 再次,我要感谢l u a 语言的发明人。感谢你们刨造了这么一门简洁、高效、有趣的编 程语言,从而使我的研究工作变得饶有趣味。 非常感谢殷群老师和李旭辉老师,由于你们的细心和耐心,读研期间的许多繁琐问题都 一一解决了。接着我想感谢所有我听过你们讲课或讲座的老师,我的学识的增长正是来自于 你们的教导。 同时我还要感谢同普路公寓9 号1 0 2 的所有室友以及理科大楼a 4 3 2 实验室的所有 师弟师妹们,与你们在一起的日子是愉快和值得回忆的。 接着我要对家人说声谢谢,是你们的默默奉献才使得我顺利地完成了学业。 最后,衷心祝愿我的亲人、师长、同学和朋友们一切如意! 邓际锋 2 0 0 5 年3 月 支持静态元编程的可扩展式开放编译器的研究与实现第l 章b l 言 1 1 基本概念介绍 1 1 1 静态元编程 第1 章引言 元( m e t a ) 这个词是从希腊词汇中借来的,惫为“a f t e r ”或者“b e f o r e ”,用于表示 级别的改变。丽在计算机科学中,它主要表示“b e i n ga b o u t ” 关于) 的意思 c e 2 0 0 4 】。 因此元程序( m e t a p r o 拿r a m ) 是关于程序本身的程序,正如元数学( m e t a m a t h e m a t i c s 是关于数学本身的数学一样。 元程序实际上可以在不同的语境( c o n t e x t 】和不同的时间段运行,但如果元程序是在 它们操纵的代码被载入( 1 0 a d e d ) 之前运行的话,那么就称其为静态元程序( s t a t i c m e t a p r o g r a m ) ,相应的设计活动称为静态元编程( s t a t i cm e t a p r o g r a r m i n g ) 。包 含静态元程序的系统最常见的例子就是编译器和预处理器。这些系统操纵表示输入的内部数 据结构( 比如抽象语法树) ,并把它们转换为使用其它语言( 例如汇编) 或者同样语言但结构 被修改了的程序【c e 2 0 0 4 。 在编译期运行的元程序只是静态元程序的一种,不过却是非常常见的一种。如果没有特 别说明,本文剩下部分提到的元程序或静态元程序均特指编译期运行的静态元程序。如果要 让元程序在编译期运行,那么编译器就有义务为它们提供一个完整的执行环境( e x e c u t i o n e n v i r o n m e n 七) 。 1 1 2 开放式编译器 开放式编译器( o p e nc o m p i l e r ) 的思路是向静态元程序提供某些定义良好的高层接 口,使其能够改变默认的编译动作比如按照新的语法来解析源代码) ,获取若操纵编译过 程中源代码的内部表示( 比如语法解析树:s y n t a xp a r s et r e e ) 。事实上每一个编译器 或多或少都能称得上是开放式的,因为编译器后端( 代码生成器) 必然要调用前端提供的接 口以取得代码的中间表示( 通常是抽象语法树或3 元组,恕元程序提供接口只不过是朝开 放的道路上更前进了一步而已。 1 支持静态元编程的可扩展式开放编译嚣的研究与实现 第l 章引言 1 2 研究意义 从理论上来说,任何一种图灵完备f t u r i n g c o m p l e te ) 语言的计算能力都是等价的 但实际上却没有种语言 即使它号称通用语言) 对解决所有问题都是适合的。因为语言内 建的表达机制f 语法设施、数据类型,控制结构,组合手段) 逶常是固定的,而适合描述某 类问题的语言,对其它类型问题可能就力不从心了。领域专用语言( d s l ,d o m a i ns p e c i f i c l a n g u a g e ) 通过提供合适的机制可以优雅而高效地解决特定领域的问题,因此d s l 越来越 受到开发者的重视。然而从头构建一门新的针对特定领域的语言对许多开发者来说是一项非 常困难的工作,因此程序员迫切需要一种允许使用者在基本框架的基础上不断发展出新机制 的语言,即可扩展式编程语言( e x t e n s i b l ep r o g r a m m i n gl a n g u a g e ) 。开放式架构 的编译器提供了这种可能:朋户可以在原始语言的基础上定义新的语法格式,可以把用新语 法格式书写的源代码转换成语义相等的原始语言代码( 这不是必需的,事实上你可以对它们 做任何事) 。这样程序员便可以在无需重写或扩展编译器的前提下,为一门语言引入适合描 述他们所面对问题的新的语法设施、新的控制结构,新的关键宇等等。这可不就是创造了一 门d s l ? l 。3 动态语言l u a 1 3 1 简介 l u a ( i f c 2 0 0 3 】,【i e r 2 0 0 4 】) 是由巴西里约熟内卢天主教大学( p o n t i f i c a l c a t h o l i cu n i v e r s i t yo fr i od ej a n e i r o ) 研究人员创造的一门语法类p a s c a l 而 语义类s c h e m e 【a s s 2 0 0 4 】的过程型动态语言,最初主要用来扩展c 程序,所以整个系统c 包 括解释器、编泽器、虚拟机) 全部采用a n s ic 实现并以c 程序库的方式提供同时语言本 身定义了完善的与c 语言交互的接口。l u a 的主要特点有:变量( v a r i a b l e l 没有类型, 只有值( v a l u e ) 才有类型,运行期可以赋给变量任何类型的值:函数是一阶值 ( f i r s t c l a s sv a l u e ) ,井支持c l o s u r e 概念:采用词法定界( 1 e x i c a ls c o p i n g ) 提供了协程( c 。r o u t i n e ) 机制;系统自带内存回收 g a r b a g ec o u e c t i o n ) 功能:表 ( t a b l e ) 是唯一的数据结构,相当于关联数组 a s s o c i a t i v ea r r a y ) ,任何类型的值都 可以作为表的键来检索( i n d e x ) 数据;提供了较丰富的反射( r e f l e c t i o n ) 功能 可以为 2 支持静态元编程的可扩展式开放编译器的研究与实现 第1 章引言 每一个表设定元表( m e t a t a b le ) 和元方法( m e t a m e t h o d ) 从而改变表操作的原始语义, 此即所谓的动态元机制( d y n a m i cm e t a m e c h a n i s m ) 。 选择l u a 作为研究对象主要是因为它在许多领域尤其是电脑游戏开发中得到了越来越 广泛的应用,是一门非常有活力的成长型语言,为它实现的开放式编译器将确实有可能帮助 工业界的程序员提高开发效率。 1 3 2 基于原型的面向对象模型 由于l u a 提供的独特的面向对象编程模型在本文的研究与实现中占有重要的位置,所 以本节将对其做一个介绍。 l u a 的数据类型里并没有类( c l a s s 与对象的概念,但实际上却可以很容易用表来表 示对象,程序1 1 是一个简单示例。在本文的余下部分,表和对象这两个词将不加区分地 混合使用。 程序1 1 用表来实现对象 与c + + 、j a v a 这些基于类的面向对象语言不同,l u a 无法通过类的概念来描述继承关 系,但通过语言的动态元机制则可以构建出一种基于原型p r o t o t y p e - b a s e d ) 的继承模 型。采用这种模型的典型语言有j a v a s c r i p t 、s e l f f u s l 9 8 7 】。原型实际上就是普通对 象任何对象都可以成为其它对象 包括原型) 的原型。如果一个对象以另一个对象为原型, 3 支持静态元编程的可扩展式开放编译嚣的研究与实现第l 章引言 那么在它内部就会保存一个指向原型的引用( r e f r e n c e ) ,当该对象碰到它不能理解的消息 时便到原型中去寻找相应的处理方法,如果愿型中没找到就再到原型的原型中找直至找到 或者不再有原型。由此可见,对象与原型之间是一种委托( d e l e g a t e ) 与被委托的关系,它 们之间的区别完全是由所担当角色的不同而产生的。通过指向同一个原型。许多对象可以共 享该原型的行为与属性【l i e l 9 8 6 】,因此它们也就具有了某些共同性质,从而成为同一类 对象实例化某类对象很简单,仅仅是根据该类对象的原型克隆( c l o n e ) 出一个新对象, 并为新对象设置一个指向原型的引用。而为了方便我们称该原型为对象的直接原型 ( d i r e c tp r o t 。t y p e ) 。假设根据原型b 实例化出对象a ,然后再为a 添加新的或者重定 义c o v e r r i d e ) b 原有的属性与方法,这样便可以利用a 为原型实例化出与b 相似但又有自 己特色的对象。此时我们称原型b 派生 d e r i v e ) 了原型a 而a 继承( i n h e r i t ) 了b ,b 是a 的父原型( p a r e n tp r o t o t y pe ) ,a 是b 的子原型( c h i l dp r o 七o t y p e ) 。假如b 叉继承了c c 又继承了d ,那么它们便构成了一条继承链i n h e r i t a n c ec h a i n ) , 并且b 、c 、d 位于a 的上方,而所有在继承链中位于a 上方的原型被统称为a 的祖先 原型( a n c e s t o rp r o 七o t y p e ,包括父原型) 。 l u a 允许一个对象用另一个普通的表作为自己的元表( m e t a t a b l e ) ,元表中有若干特 殊宇段代表着元方法( 1 n e t a m e t h o d ) ,i n d e x 就是其中之一。一个元袁的i n d e x 字 段的值应该要么是一个表,要么是个型构f s i g n a t u r e ) 为f u n c t i o n t a b l e ,k e y ) 的 函数。如果| 三l 不存在的键检索某个对象时,l u a 或者会把在元表的i n d e x 中检索到的值 返回或者会以对象和键作为参数执行i n d e x 代表的函数,并把函数返回值作为检索值 返回。假如元表自身还有元表,并且也有相应的i n d e x 元方法那么将重复上述过程。 程序l 一2 演示了如何利用元表与元方法来构建基于原型的单继承对象模型。代码执行完后 对象的布局如图l 一1 所示。n e w 是p o i n t 2 d 的成员函数,它返回的对象都以p o i n t 2 d 为元袁。p o i n t 3 d 正是由p o i n t 2 d :n e w 实例化的对象,由布局图可以看到p o i n t 3 d 本 身并不真正包含x 和n e w 字段,但是当我们试图在p o i n t 3 d 中检索它们的值时,l u a 便 会自动到元表的i n d e x ( 也即p o i n t 2 d ) 中去找,这就使得p o i n t 2 d 成为了p o i n t 3 d 的原型。p o i n t 3 d y 是重定义的属性,p o i n t 3 d z 是新添加的属性。因为都位于p o i n t 3 d 中,所以检索它们无需到原型中寻找。同样地p o i n t 3 d 调用继承来的n e w 函数实例化的 对象v 以p o i n t 3 d 为原型,它的y 、z 属性在p o i n t 3 d 中检索到x 属性舞8 最终在p o i n t 2 d 中找到。 4 支持静态元编程的可扩展式开放编译器的研究与实现第l 章引言 程序1 2 实例化( i n s t a n t i a 七i 。n ) 与派生( d e r i v a t i o n p 0 1 n 七2 dp o i n 七3 d 1 3 3 标准l u a 图1 1 利用元表构建的单继承对象模型 在本文中,作者将l u a 5 o 参考手册【i f c 2 0 0 3 】定义的语言称为标准l u a ,雨由l u a 官方网站塾! 监! 堕型竺:! i :! ! g 发行的完全遵循了 i f c 2 0 0 3 】定义的l u a 实现称为标 准l u a 实现或标准l u a 系统。 1 4 本文的主要贡献 本文在可扩展式编程语言、开放式开发系统、元编程技术的研究上主要做出了以下几方 面的贡献: 5 支持静态元编程的可扩展式开放编译器的研究与实现第l 章引言 对标准h u a 编程语言进行了扩展,引入了新的支持静态元编程的语法设施,为l u a 同 时作为运行期和编译期两个层次的编程语言奠定了基础; 将自定义语法的概念引入了l u a 语言,并且设计了自定义语法的解析接口、语法树的 操作及转换接口以及转换后生成的程序文本如何与原有的代码集成的机制从而为用户自行 扩展l u a 构建了一个良好的框架: 针对扩展后的l u a 语言开发了一个开放式编译器帕p e n l u a ,该编译器除了为静态 元程序提供一个完善的运行环境外,还实现了自定义语法解析接口、语法树操作及转换接口, 它的完成为l u a 语言使用者学习及实践可扩展式编程语言提供了一个良好的平台; 利用编译器的开放式能力为l u a 语言实现了若干有趣的扩展,从而在实际应用中检验 了此类开放式系统的有效性及易用性。 1 5 本文的组织结构 本文的具体组织结构安排如下: 夺 第2 章概括地介绍了o p e n l u a 编译系统及其使用格式,并且描述了从用户角度看到的 编译过程。 第3 章详细地介绍了o p e n l u a 的设计与实现,包括o p e n l u a 为标准l u a 语言引入的 新的语法设施的格式及语义、o p e n l u a 提供的元编程环境及开放的编程接口的定义及 实现,还包括为开放式架构定制的特别的词法分析器的实现和o p e n l u a 内建语法及用 户自定义语法的解析算法。 夺在第4 章中,作者通过若干具体的应用实例展示了o p e n l u a 的扩展能力,并检验了该 系统的有效性与易用性。 夺 第5 章分析了在可扩展编程语肓、开放式开发系统、元编程技术以及相关的领域内国 际国内其他研究人员所做的主要工作、贡献,并与本文的工作进行了比较。 第6 章对本文研究工作进行总结,着重分析了o p e n l u a 系统在使用及实现上的缺陷 并提出了相应的改进计划。 6 支持静态元编程的可扩展式开放编译嚣的研究与实现第2 章o p e n l u a 概述 第2 章o p 鲫l u a 概述 o p e n l u a 这个名字代表两个意思:一是指为支持静态元编程而对标准l u a 进行扩展得 到的语言;二是指一款针对上述语言的,并且开放了若干内部可编程接口的编译器。读者一 般根据上下文就能判断当前o p e n l u a 这个词确指哪个概念,只有在可能引起混淆的情况下 作者才会做额外说明。 o p e n l u a 提供给用户的静态元编程语言就是标准l u a 本身,因此程序员无需学习另外 一门语言即可轻松地利用开放式编译器的扩展能力。而有的系统提供的静态元编程语言与普 通源代码使用的语言间的编程模型相差太大,最突出的例子便是c + + 的t e m p l a t e 。作为 元编程语言的t e m p l a t e 本质上提供的是一种函数式编程范式( f u n c t i o n a l p r o g r a m m i n gp a r a d i g m ) :没有变量、不允许赋值( 也就没有s i d e e f f e c t s ) 、用递 归来实现各种控制结构,这对许多c + + 程序员来说都是非常陌生的。 该系统主要用标准l u a 语言并辅以少量的c 来实现,所有功能( 包括词法分析语法分 析) 均为从头独立构建,并未采用任何外部辅助工具( 比如y a c c 等) 。做出这样的设计决定 有这么几个原因:1 、l u a 官方网站b l b ;竖里:l ! ! q 强已经为我们提供了一个商效率 的标准实现,这使得用l u a 来编写l u a 语言编译器( 一个有趣的元环:m e t a c i r c l e ) 成 为可能;2 、标准l u a 本身非常简洁、易于使用并且功能足够强大,尤其是提供了比较完善 的文本处理函数,这一切都有助于开发效率的提高;3 、l u a 是作为一门嵌入式语言 ( e m b e d e dl a n g u a g e ) 来设计的,并且以c 程序库的形式提供完整系统,这使得我们很容 易将标准l u a 语言的解释器集成到o p e n l u a 编译器中,从而为静态元程序提供一个完善的 运行时环境;4 、o p e n l u a 是一个开放式架构的编译器,它的很多编译行为 包括词法分析、 语法分析) 与非开放式系统有很大不同,而w 虻c 等自动生成工具只能生成普通的封闭式系 统,因此类似工具并不适合在本项目中使用。 因为l u a 虚拟机及其指令集并非语言定义的一部分,它们有可能在未通知语言使用者 的情况下变更而且底层的虚拟机平台与o p e n l u a 提供的静态元编程能力、开放式架构并 无关联所以o p e n l u a 编译器没有傲生成字节码b y t e c 。d e ) 的工作。 具体一点来说。o p e n l u a 的编译过程就是:首先解析源文件中的o p e n o u a 源代码, 并同时执行相应的静态元程序( 如果有的话) 以对源代码进行各种转换与处理如果不出错 意味着语法正确、静态元程序运行无误) 那么解析完毕后即生成一颗标准l u a 语言的语法 7 支持静态元编程的可扩展式开放编译器的研究与实现 第2 章o p e n l u a 概述 解析树( s y n t a xp a r s et r e e ) ,最后如果需要( 见下文关于o p e n l u a 使用格式的介绍) 便将这颗语法解析树反解析 u n 阳r s e ) 回标准l u a 程序文本。图2 1 形象地刻画了整个 过程。反解析得到的标准l u a 程序代码一定是能被标准l u a 编译器编译通过的语法正确的 代码因为语法树的生成过程口口保证了这二点。 l w 代码语法树 图2 1o p e n l u a 的编译过程 o p e n l u a 的项目主页是! ! ! ! ! ! 塑:! ! i ! b i ! i :! ! g 驻! ! i 皇! ! ! 巳! 旦! ! i 2 0 0 5 年1 2 月2 8 日o 0 1 版发布,读者可访闯以上地址下载软件包。 o p e n l u a 的使用格式是; o p e n l u as o u r c e f i l e【o u t p u t f i l e l s o u r c e f i l e 是待编译的o p e n l u a 源文件名,o u t p u t f i l e 是可选的输出文件名。上述 命令会首先编译s o u r c e f i l e ,如果出错便打印错误信息并退出;如果成功且指定了 o u t p u t f i l e 参数,。p e n l u a 就会把编译s 。u r c e f i l e 得来的语法树反解析回标准l u a 程序并输出到o u t p u t f i l e 中。最后显示编译成功消息并退出。 8 支持静态元编程的可扩展式开放犏译器的研究与实现第3 章o p e n l u a 的设计与实现 第3 章0 p e n l u a 的设计与实现 3 1o p e n l u a 对标准l u a 语言的扩展 3 1 1 语法的形式化定义及其书写规则 标准l u a 语言语法的形式化定义采用的是e b n f 格式,大概有7 0 个左右的产生式 i f c 2 0 0 3 。基于实现上的考量,作者将它们改写成了标准8 n f 形式。 个产生式形如: f l e l d : e x p 。;e x p 冒号左边是非终结符( n 。n t e r m i n a l ) 也即产生式左部( 1 e f ts i d e ,而冒号右边则是 产生式右部( r l g h ts i de 】。产生式中出现的所有语法符号有两种书写形式:( 1 没有被单 引号 l 用的字符串,代表该语法符号的名字它必须以下划线( 一 或字母开头,其后紧随。 或多个字母、数字或下划线,这与标准l u a 甲对变量名的词法规定是一致的,非终结符和 关键宇( k e y w o r d ) 一定要写成这种形式。( 2 ) 用单引号引用住的字符串,这种形式用于表 示标点( p u n c t u a t i 。n 、操作符 。p e r a t 。r ) 等语法符号,注意单引号本身不是符号的一 部分。 具有相同左部的产生式可以把左部合井在一起右部之间用l 号分隅。不同的右部可以 写在一行内,也可分几行写,但是同一个右部只能写在同一行内。冒号或者i 号必须与它们 引导的右吉口在同一行,并且右部不允许为空。比如 f i e l d s e p : ,i; 或者 f i e l d 8 e p :。, i j 。 都是正确的格式,但是 f l e l d s e p : 。,i ; 却是错误的格式。因为 号引导的右部t ;t 与它不在同一行内。 如果左部是新的非终结符- 那么产生式一定要另启新的一行写。e m p t y 和e o f 是两个 特殊的终结符,代表空符号和输入结尾符,用户不应该用它们做任何非终缩符的名字。 特殊的终结符,代表空符号和输入结尾符,用户不应该用它们做任何非终结符的名字。 9 支持静态元编程的可扩展式开放编译器的研究与实现第3 章o p e n l u a 阿设计与实现 o p e n l u a 在标准l u a 的基础上引入了3 个新的语法成分:用户自定义语法 ( u s e r d e f i n e ds y n t a x ) 、源代码转换子f s o u r c ec o d et r a n s f o r m e r ) 以及编译期 模块导入( i m p 。r tm o d u l e ) 语句。附录a 是o p e n l u a 语法完整的形式化定义。 3 1 2 用户自定义语法 引入用户自定义语法的产生式如下: s y n t a x d e f : s y n t a xn a m e : l i t e r a l s y n t a x 关键字后是自定义语法的名字,然后一个冒号,悬后是包含了完整描述自定义语法 产生式的字符串。程序3 1 是个例子: 程序3 1 一个用户自定义语法的例子 在o p e n l u a ( 咀及标准l u a ) 中,被【c 和1 1 包住的字符串是r a w l i t e r a l ,即意 味着它不会因换行而中止,也不解释任何转义字符,这使得书写包含程序文本之类内容的字 符串非常方便。自定义语法的产生式书写规则与上一小节介绍的完全一致,用户可| ;工在自定 义语法中引入新的关键字( 如本例中的r e q u i r e 和e n s u r e ) ,也可以引入新的长度为1 的 标点或操作符( 本例并无体现) 。很多时候定义语法成分是一件很繁琐的事情。如果每次都 要求用户从头开始可想而知他们会多么沮丧。因此系统允许自定义语法引用o p e n l u a 内 建的所有语法符号( 包括终结符与非终结符) ,如本例的n a m e 终结符和e n d 关键字以及 。p t i o n a l p a r l i s t 和b l o c k 非终结符但不可重定义它们。用户无需关心内建非终结 符如何解析,他只需明白解析器( p a r s e r ) 会在合适的时候根据内建非终结符的语法规则进 行解析并生成一个正确的语法变量这就使得内建非终结符在自定义语法里表现得就象一个 1 0 支持静态元编程的可扩展式开放编译器的研究与实现第3 章o p e n l u a 的设计与实现 终结符一样。对自定义语法的最后一点要求是:它必须是个l l ( 1 ) 语法,否则编译器将不 会接收它。 3 1 3 源代码转换子 源代码转换子定义的产生式为: t r a n s f o r m e r d e f:t r a n s f o r m e rn a m eb l o c ke n d 其中t r a n s f o r m e r 是关键字,n a m e 是转换子的名字,b l 。c k 是一个标准l u a 代码块, 在这里作为转换子的转换体用于执行具体的转换操作它的返回值要么是一个字符串要么是 n i l 。一个名字被定义为t r a n s f 。r m e r 后,它在源代码中就具有特殊的意义了:编译器遇 到一个己被定义为t r a n s 。f r m e r 的名字后,会把它从源代码输入流( i n p u ts t r e a m ) 中 取出并抛弃,然后立刻执行它的转换体f 即b l 。c k 代表的代码块) ,如果第一个返回值是 n i l ,编译器报错并退出如果第一个返回值是字符串,编译器就会把这一段字符串当作转 换后得到的程序文本插入到当前源码输入流的头部,这整个过程称作转换子的调用。在 o p e n l u a 中,静态元编程能力正是由转换子的定义与调用提供的。 假设有这么一段程序: 那么它被编译后得到的输出便是 由此可见转换予调用的结果就好象程序员自己在调用处写下了一些不同的代码( 这些代码 正是转换体的返回值) 一样。当然本例定义的转换子并没有任何实际意义但是它却演示 了转换子的一个基本作用:代码替换。在介绍完o p e n l u a 提供的编程接口后,读者会看到 转换子的另一个基本作用:代码转换。 1 1 支持静态元编程的可扩展式开放编译器的研究与实现第3 章o p e n l u a 的设计与实现 3 1 4 编译期模块导入 编译期模块导入语句的产生式为: i m p o r t m o d u l e : i m p o r tl i t e r a l i m p o r t 关谴字后是你要导入的模块文件名。当编译器遇到i m p o r t 语句时,它会立刻去找 相应的文件,如果找到了即会编译它( 是的。完全编译) ,但编译产生的那些运行期代码被 简单地抛弃,而只有文件中的语法定义、转换子定义得以保留。毫无疑问,编译期模块导入 机制的最大作用就是为了复用( r e u s e ) 那些自定义语法和转换子。 3 2o p e n l u 8 提供的可编程接口及元程序运行环境 o p e n l u a 通过t r a n s f o r m e r 提供了静态元编程能力,但是如果编译器没有开放出一 些必需的内部接口,并为元程序运行提供一个完善的运行环境那么元程序能够做的事情将 会很有限。因此作为开放式架构编译器的o p e n l u a 提供了一系列的关键接口。 让我们先来看一个例子: 1 2 交持静态元编程的可扩展式开放编译器的研究与实现第3 章o p e n l u a 的设计与实现 程序3 2m e t a 转换子的定义 请首先注意m e t a 转换子定义用到的p a r s e 函数,这是编译器开放给用户的最重要的接口。 它以某个自定义语法为参数,并有两个返回值:第一个代表生成的语法树,第二个代表可能 的出错信息。该函数被调用时会按照指定语法对当前源码输入流进行解析,如果成功则返回 生成的语法树和n i l ,如果失败就返回n i l 和出错信息。 一颗语法树可以通过保存其根节点来保存,而使用语法树亦是通过引用其根节点来进行 的。一颗语法树节点( s y n t a xt r e en o d e ) 是一个s y t n b 。l 类型对象,也即所谓的语法变 量( s y n t a c t i c a lv a r i a b l e ) ,在接下来的论述中作者对这三个概念将不加区分,混合 使用。s y m b o l 类型对象提供了t y p e 、n a m e 、v a l u e 、h a s c h i l d r e n 、c h i l d r e n c o
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 糖尿病合并外伤的护理
- 面部深导后的护理
- 腹腔镜胃癌切除术护理
- 公司消防知识安全培训
- 2025年重庆招标采购从业人员考试(招标采购专业实务初、中级)试题库及答案
- 渠道对账工作汇报
- 酒精戒断综合症患者的护理
- 结核性脑膜炎病人的护理
- 解读心理学书籍
- 2025建筑材料采购合同
- 客户隐私保护承诺函
- 宿舍改造经济效益分析报告
- 仪表施工全过程的管理
- 如何预防与处理跑步中的常见损伤
- MSOP(测量标准作业规范)测量SOP
- 001 220kV升压站事故油池施工方案
- 智慧停车场运营管理项目风险评估报告
- 九年义务教育全日制小学数学教学大纲(试用)
- 出资比例的协议合同
- GB/T 10345-2022白酒分析方法
- GB/T 19418-2003钢的弧焊接头缺陷质量分级指南
评论
0/150
提交评论