MDSF:LOP-使用MPS来做个计算器的示例
在上一篇面向語言編程LOP(Language Oriented Programming)方法介紹中介紹了LOP以及一種LOP的實現方法MPS,本篇主要講解一下使用MPS1.5的一個示例,以便大家能更好的理解是如何使用MPS實現LOP項目的。
需求
計算一個Java/PHP開發人員的收入,輸入在Java和PHP項目投入的時間,計算器自動計算收入值,界面表示如下:
目標
通過寫以下4行代碼來生成這個計算器(10和5是常量)
?
view sourceprint?| 1 | calculator MySalary |
| 2 | input PHP Hours |
| 3 | input Java Hours |
| 4 | output Java Hours*10 + PHP Hours*5 |
?
主要步驟
- 生成前面目標中提到的語法的一種語言來實現計算器。語言定義基本的邏輯概念、組成規范、關系以及各自的行為
- 生成一個生成器,定義構建swing應用程序的規則
- 使用我們創建的語言來實現一個計算器
下面主要講解一下語言定義部分,代碼生成器部分請參考MPS1.5的示例
生成項目
生成一個新的項目,項目名為:calculator
按Next后,生成一種新的語言,設定語言命名空間為:?jetbrains.mps.tutorial.calculator(命名空間一般為companyName.meaningful.name)
再按Next,生成一種新的方案(方案是一套特定語言的模型):
理想情況下,語言和使用語言的方案是分離的兩個項目,但是建議在生成語言時把這個項目放在一起,便于測試新的語言。
按Finish后進入項目視圖,默認展開語言項目jetbrains.mps.tutorial.calculator()節點:
語言項目下有多個節點,這些節點前面都帶有M圖標,分別代表模型的不同方面:
- structure:描述語言語法
- editor:描述編寫語言時的編輯器
- constraints:描述一些約束
- type system:描述如何計算節點類型
jetbrains.mps.tutorial.calculator.sandbox()表示我們的測試方案節點,Modules Pool() 包含一系列可以參考使用的語言和方案,后面會再介紹這些內容。
?
下面我們開始來建立Calculator語言
Calculator概念(concept)
就像類定義它的實例字段、方法和其他成員的結構一樣,概念定義它的實例屬性、引用和子概念定義的結構。概念是可以繼承的,缺省每一個概念都從BaseConcept繼承下來,它將會繼承父概念的所有屬性、子概念和引用等結構。首先我們需要生成一個新的概念:Calculator。設置instance can be root為true,實現INamedConcepts接口以便具有Name屬性,
?
提示:按Tab/Shift+Tab可以導航編輯焦點<> ;按Ctrl+Space可以打開自動完成提示列表
生成一個編輯器
MPS編輯器看上去是文本編輯器,但是它是一個直接使用語法樹的一個結構化編輯器。編輯器使用單元格(cells)來表示概念節點,這里有以下幾種節點類型:
- 屬性單元格: 編輯節點屬性
- 常量單元格:顯示常量值
- 集合單元格:在內部嵌套其他單元格
前面定義了概念calculator,它的編輯器應該為:calculator name
選擇Calculator概念的【Editor】頁簽,新增一個概念編輯器,
在‘calculator’常量單元格編輯器后按Enter鍵,通過‘{’選擇屬性name:{name}
測試一下概念編輯器
在語言項目中,點擊右鍵選擇 Generate Language 來生成語言。生成之后,我們在方案項目新建一個模型:
在 Model name中輸入類型 jetbrains.mps.tutorial.calculator.sandbox
把jetbrains.mps.tutorial.calculator語言加入到Model Properties對話框的Used Languages中,這樣才能使用這個語言來編寫應用:
在測試模型sandbox中新建一個Calculator概念測試應用,顯示如下:
?
到現在我們已經簡單建立了第一條語言,下面建立輸入字段概念
給Calculator加上子概念InputField
新建一個InputField概念,設置instance can be root為false,實現INamedConcepts接口以便具有Name屬性,然后再生成編輯器:[- input { name } -]
為了使得計算器包含輸入字段,需要把InputField類型作為Calculator概念子對象:
選擇在Calculator編輯器中的屬性name,按Alt+Enter彈出意圖列表,選擇Add New Line
為了每個輸入字段顯示一行,我們可以對子對象InputField選擇Add newline for children意圖:
按Ctrl+F9重新生成語言后,再次進入應用界面:
輸出概念:OutputField
生成一個默認的輸出概念:OutputField,編輯器如下:
把OutputField添加到calculator概念子對象中:
Calculator編輯器更改如下:
現在我們能夠在outfield中輸入任何表達式:
添加表達式支持
MPS中有基礎語言,新的語言使用它們需要讓自己的語言擴展基礎語言?,F在我們需要使用表達式功能,打開語言屬性對話框:
在Dependencies 頁簽中的Extended Languages 列表選擇jetbrains.mps.baseLanguage:
BaseLanguage包含一個Expression概念,它表示一個表達式,格式如"2", "2+3", "abc+abc"等。這個就是我們這里示例中output需要的。
現在給OutputField添加expression子類型:
更改編輯器:
現在可以輸入表達式,但是還不能通過input計算,應用界面如下:
擴展表達式概念
為了支持通過input來計算,我們需要生成自己的表達式類型。建立概念InputFieldReference,從Expression繼承下來,添加InputField為引用概念field
生成InputFieldReference編輯器:%field%-> {name}表示引用概念屬性
應用界面如下:MPS的智能引用會在當前上下文決定哪些引用可以使用,這里自動完成列表會列出width
定義生成器
MPS生成器語言使用兩種參數引用:property macros (marked with $) andnode macros ($$)。
我更關注的是前面語言定義部分,這部分還沒有具體看,剛興趣的可以參考MPS1.5的示例
?
?
MPS網站
?Download MPS
?A Language Workbench in Action - MPS
?
歡迎轉載,轉載請注明:轉載自周金根 [ http://zhoujg.cnblogs.com/ ]
轉載于:https://blog.51cto.com/zhoujg/517108
總結
以上是生活随笔為你收集整理的MDSF:LOP-使用MPS来做个计算器的示例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 企业文件服务器资源管理方案
- 下一篇: 各大型网站架构分析收集Z