您的位置:首页 > 编程语言

代码生成(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.



......

代码生成定义语言

  在特定领域建模 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




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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  职场 休闲 MDD