代码生成(Code Generation)介绍

简介:

在实现模型驱动开发中,我们可以解释模型直接运行在领域框架之上,也可以把模型通过代码生成技术转换成代码之后编译运行在框架之上。这两种方式都有利弊,可以搭配使用,在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的一般经过如下步骤:

  1. 写语法
  2. 写StringTemplate模板(可选)
  3. 在AntlrWorks调试语法
  4. 从语法生成类
  5. 使用生成的类来写应用程序

  作者写了一本介绍Antlr的专著 The Definitive Antlr Reference,我只是几年前大概看过一遍,觉得作者很牛。不过作者又出的另外一本书Language Implementation Patterns,有人说这本书更好,它将ANTLR内部的设计思想也讲得很清楚了。相比而言,之前那本书只能算是ANTLR的用户手册,而新书算是ANTLR的设计思想。

        

  • Irony - .NET Language Implementation KitIrony是在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):

它的一个Report示例:

 

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

 

它的语法定义如下:

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" [";"];

书籍

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




















 本文转自 jingen_zhou 51CTO博客,原文链接:http://blog.51cto.com/zhoujg/403113,如需转载请自行联系原作者


相关文章
|
13天前
|
前端开发 开发者
【翻译】再见, Clean Code!
该文章源自React核心开发者Dan的博客《再见,清洁代码》。文中讲述了一个场景,作者的同事完成了一个功能,虽然代码运行正常但显得冗余。作者试图通过重构消除重复,使代码更整洁,但第二天被上司要求恢复原状。作者后来认识到,追求“清洁代码”是成长过程中的一个阶段,虽然抽象和消除重复有其价值,但应考虑代码的可维护性和团队协作。真正的目标不是绝对的“清洁”,而是适应变化和良好沟通。
17 0
|
7月前
|
测试技术 应用服务中间件 数据库
一些 Next Generation ABAP Platform 的新语法用例
什么是 NGAP(Next Generation ABAP Platform)? SAP NetWeaver 7.40 发布,并附带其 ABAP 应用服务器 AS ABAP 7.40。 在 AS ABAP 7.40 中,ABAP 语言具有一些不错的新特性。 AS ABAP 7.40 是 AS ABAP 7.31(又名 AS ABAP 7.03)的继承者,后者是基于 AS ABAP 7.0 构建的 AS ABAP 7.02 的继承者。
42 0
|
7月前
|
存储 开发框架 自然语言处理
关于 ABAP 开发对象的原始语言版本(Original Language)
关于 ABAP 开发对象的原始语言版本(Original Language)
33 0
关于 ABAP 开发对象的原始语言版本(Original Language)
|
C++
VS Code注释插件doxygen documentation generator
VS Code注释插件doxygen documentation generator
565 0
VS Code注释插件doxygen documentation generator
|
开发框架 安全 IDE
Visual Studio Code 保存代码时报Applying code action Organize Imports
Visual Studio Code 保存代码时报Applying code action Organize Imports
Visual Studio Code 保存代码时报Applying code action Organize Imports
BUG! exception in phase semantic analysis in source unit
BUG! exception in phase semantic analysis in source unit
313 0
BUG! exception in phase semantic analysis in source unit
|
Java API
SAP ABAP CGLIB(Code Generation Library)的模拟实现
SAP ABAP CGLIB(Code Generation Library)的模拟实现
139 0
SAP ABAP CGLIB(Code Generation Library)的模拟实现
《The Art of Readable Code》学习笔记(一)
什么样的代码才算好呢? 有一个判断的标准:缩短别人能看明白你代码的时间。这时候估计又有同学会问了,我写的就是给自己看的,或者团队里就我一个人,设计到实现到测试全是我一个人,要写给别人明白干什么?好吧,老实说,我之前也是这样想的。“别人”不一定是其他人,也可能是三个月后的你自己。
1372 0