代码生成(Code Generation)介绍
2010-10-10 08:04
423 查看
在实现模型驱动开发中,我们可以解释模型直接运行在领域框架之上,也可以把模型通过代码生成技术转换成代码之后编译运行在框架之上。这两种方式都有利弊,可以搭配使用,在OpenExpessApp中将采用这两种方法,类库通过代码生成,UI等元模型通过框架解释执行。由于代码生成是MDD中很重要的一项技术,所以本篇我将介绍一下代码生成相关的知识。
在EMF中,Metamodel为EMF元模型,Model为EMF模型;在MS DSL Tools中,MetaModel为DSL元模型,模板为T4模板
Antlr3
Antlr是一个非常著名的开源语言生成工具,官方网站是这么介绍的:
ANTLR, ANother Tool for Language Recognition, is a languagetool that provides a framework for constructing recognizers,interpreters, compilers, and translators from grammatical descriptionscontaining actions in a variety of targetlanguages. ANTLR provides excellent support for treeconstruction, tree walking, translation, error recovery, and errorreporting. There are currently about 5,000 ANTLR sourcedownloads a month.
研究过一阵子Antlr,用它来写过一个.Net下的表达式引擎,参考使用Antlr实现表达式引擎。
使用Antlr的一般经过如下步骤:
写语法
写StringTemplate模板(可选)
在AntlrWorks调试语法
从语法生成类
使用生成的类来写应用程序
作者写了一本介绍Antlr的专著 The Definitive Antlr Reference,我只是几年前大概看过一遍,觉得作者很牛。不过作者又出的另外一本书Language Implementation Patterns,有人说这本书更好,它将ANTLR内部的设计思想也讲得很清楚了。相比而言,之前那本书只能算是ANTLR的用户手册,而新书算是ANTLR的设计思想。
Irony - .NET Language Implementation Kit
Irony是在Codeplex网站上的一个开源语言实现工具,官方介绍如下: Irony is a development kit for implementing languages on .NET platform. It uses the flexibility and power of c# language and .NET Framework 3.5 to implement a completely new and streamlined technology of compiler construction. Unlike most existing yacc/lex-style solutions Irony does not employ any scanner or parser code generation from grammar specifications written in a specialized meta-language. In Irony the target language grammar is coded directly in c# using operator overloading to express grammar constructs. Irony's scanner and parser modules use the grammar encoded as c# class to control the parsing process. See the expression grammar sample for an example of grammar definition in c# class, and using it in a working parser.
......
MetaEdit+的MERL语言
MetaEdit+提供代码生成编辑器,还支持生成的调试。OpenExpressApp采用类似MetaEdit+的元元模型来编写语言,所以将来的代码生成可能也会主要参考它来做。具体可参考安装程序目录中的User's Guides 的 MetaEdit+ Workbench 代码生成章节内容。
它的一个Report示例:
view sourceprint?
它的语法定义如下:
view sourceprint?
微软的T4
T4: Text Template Transformation Toolkit
What's Inside:
Code generation basics
CG techniques and best practices
Patterns of CG design
How to deploy generators
Many example generators
Includes generators for:
Database access
RPC
Unit tests
Documentation
Business logic
Data translation
Code Generation by Model Transformation - A Case Study in Transformation Modularity
模型驱动中的代码生成
在EMF中,Metamodel为EMF元模型,Model为EMF模型;在MS DSL Tools中,MetaModel为DSL元模型,模板为T4模板
代码生成技术
Antlr3
Antlr是一个非常著名的开源语言生成工具,官方网站是这么介绍的:
ANTLR, ANother Tool for Language Recognition, is a languagetool that provides a framework for constructing recognizers,interpreters, compilers, and translators from grammatical descriptionscontaining actions in a variety of targetlanguages. ANTLR provides excellent support for treeconstruction, tree walking, translation, error recovery, and errorreporting. There are currently about 5,000 ANTLR sourcedownloads a month.
研究过一阵子Antlr,用它来写过一个.Net下的表达式引擎,参考使用Antlr实现表达式引擎。
使用Antlr的一般经过如下步骤:
写语法
写StringTemplate模板(可选)
在AntlrWorks调试语法
从语法生成类
使用生成的类来写应用程序
作者写了一本介绍Antlr的专著 The Definitive Antlr Reference,我只是几年前大概看过一遍,觉得作者很牛。不过作者又出的另外一本书Language Implementation Patterns,有人说这本书更好,它将ANTLR内部的设计思想也讲得很清楚了。相比而言,之前那本书只能算是ANTLR的用户手册,而新书算是ANTLR的设计思想。
Irony - .NET Language Implementation Kit
Irony是在Codeplex网站上的一个开源语言实现工具,官方介绍如下: Irony is a development kit for implementing languages on .NET platform. It uses the flexibility and power of c# language and .NET Framework 3.5 to implement a completely new and streamlined technology of compiler construction. Unlike most existing yacc/lex-style solutions Irony does not employ any scanner or parser code generation from grammar specifications written in a specialized meta-language. In Irony the target language grammar is coded directly in c# using operator overloading to express grammar constructs. Irony's scanner and parser modules use the grammar encoded as c# class to control the parsing process. See the expression grammar sample for an example of grammar definition in c# class, and using it in a working parser.
......
代码生成定义语言
在特定领域建模 DSM(Domain Specific)介绍中介绍了DSM的不同工具的比较,其中代码生成定义语言也可以从表中看到,下面将会介绍一下DSL tools的T4和MetaEdit+的MERL(MetaEdit+ Reporting Language):MetaEdit+的MERL语言
MetaEdit+提供代码生成编辑器,还支持生成的调试。OpenExpressApp采用类似MetaEdit+的元元模型来编写语言,所以将来的代码生成可能也会主要参考它来做。具体可参考安装程序目录中的User's Guides 的 MetaEdit+ Workbench 代码生成章节内容。
它的一个Report示例:
view sourceprint?
01 | Report 'Test' |
02 | foreach .State [Watch] |
03 | { 'State : ' |
04 | :State name; |
05 | newline |
06 | 'Connects to: ' |
07 | newline |
08 | do ~From>()~To.State [Watch] |
09 | { '' |
10 | :State name; |
11 | newline |
12 | } |
13 | newline |
14 | } |
15 | endreport |
view sourceprint?
001 | STRING : "'" CHAR* "'" |
002 | where CHAR is any character; a ' character must be doubled |
003 | NUMBER : ( "0" .. "9" )+ |
004 | NAMECHAR : "a" .. "z" | "0" .. "9" | " " |{_+-[]?} |INTLNAMECHAR |ESCAPECHAR |
005 | INTLNAMECHAR : {äëïöü} |{áéíóú} |{àèìòù} |{âêîôû} |{ñãœçÿ} |{߀} |{¿¡«»} |
006 | ESCAPECHAR : "\" ECHAR |
007 | where ECHAR is anything that is not a letter number or underscore |
008 | NAME : NAMECHAR+ |
009 | If NAME contains a space, the whole name should have a ";" after it, or one of ".>~#" forming the start of the next element in a chainClause |
010 | WILDNAME : [ "^" ](NAMECHAR | "*" | "#" )+ |
011 | If WILDNAME contains a space, the whole name should have a ";" after it. |
012 | #Design element access and output commands (5.3.2) |
013 | chainOutputClause: (propClauseWithLevel |propClause |(graphEltClause+ propClause)) [ ";" ][translatorNames][ ";" ]; |
014 | translatorNames : ( "%" <NAMECHAR>+)+; |
015 | propClauseWithLevel : propClause levelNumber [ ";" ]; |
016 | levelNumber : [ ";" ] " " * [ "-" ]<NUMBER>+; |
017 | propClause : ":" (<NAME>| "()" ); |
018 | graphEltClause : (objClause |relClause |roleClause |portClause) [ ";" ] |
019 | objClause: "." typeChoiceClause |
020 | relClause: ">" typeChoiceClause |
021 | roleClause : "~" typeChoiceClause |
022 | portClause : "#" typeChoiceClause |
023 | typeChoiceClause : NAME |
024 | | "()" |
025 | | "( " WILDNAME { " |" WILDNAME}* ")" |
026 | #General commands (5.3.3) |
027 | report : oldreport |newreport; |
028 | oldreport: "report" <STRING> clause* "endreport" ; |
029 | newreport: [newheadersection]clause*; |
030 | newheadersection : <NAME>[ "(" [<NAME>( "," <NAME>)*] ")" ]; |
031 | clause : (comment |
032 | |basicClause |
033 | |ifClause |
034 | |loop |
035 | |subreportClause |
036 | |fileClause |
037 | |md5Clause |
038 | |executeClause |
039 | |promptAskClause |
040 | |variableAssign |
041 | |variableClause |
042 | |translationClause |
043 | |mathClause |
044 | |chainOutputClause |
045 | ; |
046 | comment : <comment>; |
047 | basicClause : atomicClause |iterableClause; |
048 | atomicClause : newlineClause |separatorClause |literal |variableRef |simpleClause; |
049 | newlineClause: "newline" [ ";" ]; |
050 | separatorClause : "sep" [ ";" ]; |
051 | literal : <STRING> [translatorNames][ ";" ]; |
052 | variableRef : "$" <NAME>[translatorNames][ ";" ]; |
053 | simpleClause : ( "id" | "type" | "metatype" | "oid" | "projectid" | "objectid" | "project" ) [levelNumber][ ";" ][translatorNames][ ";" ] |
054 | | |
055 | ( "x" | "y" | "left" | "right" | "top" | "bottom" | "centerX" | "centerY" | "width" | "height" | "area" ) [levelNumber][ ";" ][translatorNames][ ";" ]; |
056 | iterableClause : ( "decompositions" | "explosions" | "containers" | "contents" | "stack" | "graphs" ) [ ";" ]; |
057 | #Control and navigation commands (5.3.4) |
058 | ifClause : "if" [condition] |
059 | "then" [ ";" ](clause*| ";" ) |
060 | [ "else" [ ";" ]clause*] |
061 | "endif" [ ";" ]; |
062 | condition: ( "not" condition) |
063 | |(condition "and" condition) |
064 | |(condition "or" condition) |
065 | |( "(" condition ")" ) |
066 | |expression; |
067 | expression : comparison |unary; |
068 | unary: comparableClause; |
069 | comparison : comparableClause comp comparableClause |
070 | [ "num" ]; |
071 | comparableClause : atomicClause |chainClause; |
072 | comp : "<" | ">" | "<=" | ">=" | "=" | "<>" | "=~" | "=/" ; |
073 | loop : ( "do" | "dowhile" ) |
074 | (chainClause |atomicClause) |
075 | [whereClause][filterClause] |
076 | "{" clause* "}" [ ";" ] |
077 | | |
078 | "foreach" |
079 | graphEltClause [ ";" ] |
080 | [whereClause][filterClause] |
081 | "{" clause* "}" [ ";" ]; |
082 | chainClause : (chainElementClause [levelNumber][ ";" ])+; |
083 | chainElementClause : graphEltClause |propClause |iterableClause; |
084 | whereClause : "where" condition; |
085 | filterClause : orderbyClause [uniqueClause] |
086 | |uniqueClause; |
087 | orderbyClause: "orderby" orderCriterion ( "," orderCriterion)*; |
088 | uniqueClause : "unique" [clause+ ( "," clause+)*]; |
089 | orderCriterion : clause+ [ "num" ][ "asc" | "desc" ]; |
090 | subreportClause : ( "subreport" | "subgenerator" ) [ ";" ]clause* "run" [ ";" ]; |
091 | #External I/O commands (5.3.5) |
092 | fileClause : outputFileClause |filenameReadClause |filenamePrintClause; |
093 | outputFileClause : "filename" [ ";" ]clause* |
094 | [ "encoding" [ ";" ]clause+] |
095 | [ "md5start" [ ";" ]clause+] |
096 | [ "md5stop" [ ";" ]clause+] |
097 | modeClause clause* |
098 | "close" [ ";" ]; |
099 | modeClause : ( "write" | "merge" | "append" ) [ ";" ]; |
100 | filenameReadClause : "filename" [ ";" ]clause* |
101 | [ "encoding" [ ";" ]clause+] |
102 | "read" [ ";" ]; |
103 | filenamePrintClause : "filename" [ ";" ]clause* "print" [ ";" ]; |
104 | md5Clause: "md5id" [ ";" ]clause* "md5Block" [ ";" ] |
105 | clause* |
106 | "md5sum" [ ";" ]; |
107 | executeClause: ( "external" | "internal" ) [ ";" ] |
108 | clause* |
109 | ( "execute" | "executeBlocking" ) [ ";" ]; |
110 | promptAskClause : "prompt" [ ";" ]clause* "ask" [ ";" ]; |
111 | #String and number commands (5.3.6) |
112 | variableClause : variableReadClause |variableWriteClause; |
113 | variableReadClause : "variable" [ ";" ]clause+ "read" [ ";" ]; |
114 | variableWriteClause : "variable" [ ";" ]clause+ |
115 | variableModeClause clause*[ ";" ] |
116 | "close" [ ";" ]; |
117 | variableModeClause : ( "write" | "append" ) [ ";" ]; |
118 | variableAssign : "$" <NAME> "=" [ ";" ](variableAssign |basicClause |chainOutputClause); |
119 | translationClause: "to" [ ";" ]clause* |
120 | [ "translate" [ ";" ]clause*] |
121 | "endto" [ ";" ]; |
122 | mathClause : "math" [ ";" ]clause* "evaluate" [ ";" ]; |
T4: Text Template Transformation Toolkit
书籍
What's Inside:
Code generation basics
CG techniques and best practices
Patterns of CG design
How to deploy generators
Many example generators
Includes generators for:
Database access
RPC
Unit tests
Documentation
Business logic
Data translation
LOP中的代码生成
LOP中的代码生成有三种主要的方法,我们将结合使用它们来定义模型转换;第一种是遍历方式,你枚举源模型中所有节点,检视每一个,并基于检视到的信息生成目标模型中的一些目标节点;第二种方式是使用模板和宏来定义如何生成目标语言;第三种方式是使用模式匹配来查找在源模型中的哪些节点上应用转换。Code Generation by Model Transformation - A Case Study in Transformation Modularity
相关文章推荐
- MDSF:代码生成(Code Generation)介绍
- MDSF:代码生成(Code Generation)介绍
- 代码自动生成框架----CodeAutomaticGenerationFramework
- VC.NET 的链接时代码生成 LTCG - Link-time Code Generation
- Coarunsoft Code Generation代码生成工具
- 代码生成(Code Generation with Bake)
- 代码生成工具系列-----代码生成工具(CodeEasy)介绍
- Automatically Code Generation 【自动代码生成】
- SNF开发平台-SNF.CodeGenerator-升级生成BS页面代码-支持视图-数据库配置-快速开发者的利器
- codeTool代码自动生成工具(参数类sql数据增删改查语句,实体类,接口代码)
- CODE ---代码助手 (保存代码、搜代码、生成网页、自由界面)
- 用 Java 生成 Java - CodeModel 介绍
- 对比两款VS代码生成工具 CodeRush&ReSharper
- ibatis - 自动代码生成工具abator 使用介绍
- [Java Code] 时间维度循环生成代码片段
- 使用NuGet助您玩转代码生成数据————Entity Framework 之 Code First
- 生成对抗网络介绍(附TensorFlow代码)
- entity framework codefirst 用户代码未处理DataException,InnerException基础提供程序在open上失败,数据库生成失败
- Android Parcelable代码自动生成插件 Parcelable code generator
- Entity Framework 5.0系列之自动生成Code First代码