文章目錄
- 模型驅動中的代碼產生
- 代碼產生技術
- 代碼組建定義語言
- 書籍
在實現模型驅動開發中,我們可以解釋模型直接運行在領域架構之上,也可以把模型通過代碼產生技術轉換成代碼之後編譯運行在架構之上。這兩種方式都有利弊,可以搭配使用,在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 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):
- MetaEdit+的MERL語言
MetaEdit+提供代碼產生編輯器,還支援產生的調試。OpenExpressApp採用類似MetaEdit+的元元模型來編寫語言,所以將來的代碼產生可能也會主要參考它來做。具體可參考安裝程式目錄中的User's Guides 的 MetaEdit+ Workbench 代碼產生章節內容。
它的一個Report樣本:
Report 'Test' foreach .State [Watch] { 'State : ' :State name; newline 'Connects to: ' newline do ~From>()~To.State [Watch] { ' ' :State name; newline } newline } endreport
它的文法定義如下:
STRING: "'" CHAR* "'"where CHAR is any character; a ' character must be doubledNUMBER: ("0".."9")+NAMECHAR: "a".."z" | "0".."9" | " " | {_+-[]?} | INTLNAMECHAR | ESCAPECHARINTLNAMECHAR: {äëïöü} | {áéíóú} | {àèìòù} | {âêîôû} | {ñãœçÿ} | {߀} | {¿¡«»}ESCAPECHAR: "\" ECHARwhere ECHAR is anything that is not a letter number or underscoreNAME: NAMECHAR+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 chainClauseWILDNAME: ["^"] (NAMECHAR | "*" | "#")+If WILDNAME contains a space, the whole name should have a ";" after it.# Design element access and output commands (5.3.2)chainOutputClause: (propClauseWithLevel | propClause | (graphEltClause+ propClause)) [";"] [translatorNames] [";"];translatorNames: ("%" <NAMECHAR>+)+;propClauseWithLevel: propClause levelNumber [";"];levelNumber: [";"] " "* ["-"] <NUMBER>+;propClause: ":" (<NAME> | "()");graphEltClause: (objClause | relClause | roleClause | portClause) [";"]objClause: "." typeChoiceClauserelClause: ">" typeChoiceClauseroleClause: "~" typeChoiceClauseportClause: "#" typeChoiceClausetypeChoiceClause: NAME| "()"| "( " WILDNAME {" | " WILDNAME}* ")"# General commands (5.3.3)report: oldreport | newreport;oldreport: "report" <STRING> clause* "endreport";newreport: [newheadersection] clause*;newheadersection: <NAME> ["(" [<NAME> ("," <NAME>)*] ")" ];clause: (comment| basicClause| ifClause| loop| subreportClause| fileClause| md5Clause| executeClause| promptAskClause| variableAssign| variableClause| translationClause| mathClause| chainOutputClause;comment: <comment>;basicClause: atomicClause | iterableClause;atomicClause: newlineClause | separatorClause | literal | variableRef | simpleClause;newlineClause: "newline" [";"];separatorClause: "sep" [";"];literal: <STRING> [translatorNames] [";"];variableRef : "$" <NAME> [translatorNames] [";"];simpleClause: ("id" | "type" | "metatype" | "oid" | "projectid" | "objectid" | "project") [levelNumber] [";"] [translatorNames] [";"]|("x" | "y" | "left" | "right" | "top" | "bottom" | "centerX" | "centerY" | "width" | "height" | "area") [levelNumber] [";"] [translatorNames] [";"];iterableClause: ("decompositions" | "explosions" | "containers" | "contents" | "stack" | "graphs") [";"];# Control and navigation commands (5.3.4)ifClause: "if" [condition]"then" [";"] (clause* | ";")["else" [";"] clause*]"endif" [";"];condition: ("not" condition)| (condition "and" condition)| (condition "or" condition)| ("(" condition ")")| expression;expression: comparison | unary;unary: comparableClause;comparison: comparableClause comp comparableClause["num"];comparableClause : atomicClause | chainClause;comp: "<" | ">" | "<=" | ">=" | "=" | "<>" | "=~" | "=/";loop: ("do" | "dowhile")(chainClause | atomicClause)[whereClause] [filterClause]"{" clause* "}" [";"]|"foreach"graphEltClause [";"][whereClause] [filterClause]"{" clause* "}" [";"];chainClause: (chainElementClause [levelNumber] [";"])+;chainElementClause: graphEltClause | propClause | iterableClause;whereClause: "where" condition;filterClause: orderbyClause [uniqueClause]| uniqueClause;orderbyClause : "orderby" orderCriterion ("," orderCriterion)*;uniqueClause : "unique" [clause+ ("," clause+)*];orderCriterion: clause+ ["num"] ["asc" | "desc"];subreportClause: ("subreport" | "subgenerator") [";"] clause* "run" [";"];# External I/O commands (5.3.5)fileClause: outputFileClause | filenameReadClause | filenamePrintClause;outputFileClause: "filename" [";"] clause*["encoding" [";"] clause+]["md5start" [";"] clause+]["md5stop" [";"] clause+]modeClause clause*"close" [";"];modeClause: ("write" | "merge" | "append") [";"];filenameReadClause: "filename" [";"] clause*["encoding" [";"] clause+]"read" [";"];filenamePrintClause: "filename" [";"] clause* "print" [";"];md5Clause: "md5id" [";"] clause* "md5Block" [";"]clause*"md5sum" [";"];executeClause: ("external" | "internal") [";"]clause*("execute" | "executeBlocking") [";"];promptAskClause: "prompt" [";"] clause* "ask" [";"];# String and number commands (5.3.6)variableClause: variableReadClause | variableWriteClause;variableReadClause: "variable" [";"] clause+ "read" [";"];variableWriteClause: "variable" [";"] clause+variableModeClause clause* [";"]"close" [";"];variableModeClause: ("write" | "append") [";"];variableAssign: "$" <NAME> "=" [";"] (variableAssign | basicClause | chainOutputClause);translationClause: "to" [";"] clause*["translate" [";"] clause*]"endto" [";"];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
推薦:你可能需要的線上電子書
歡迎轉載,轉載請註明:轉載自周金根 [ http://zhoujg.cnblogs.com/ ]