使用的Eclipse版本: Oxygen.1a Release (4.7.1a) Build id: 20171005-1200, 經過添加Xtext - Download上列出的Releases update site安裝xtext IDE和xtext SDK. 以後打開Eclipse, 打開任何文件就報錯:html
An error has occurred. See error log for more details. loader constraint violation: loader (instance of org/eclipse/osgi/internal/loader/EquinoxClassLoader) previously initiated loading for a different type with name "org/aspectj/runtime/internal/AroundClosure" 複製代碼
爲避免現有插件和它的衝突, 新安裝了更新版Eclipse: Version: Oxygen.2 Release (4.7.2) Build id: 20171218-0600java
首先, 參考官方教程: 15 Minutes Tutorialgit
教程循序漸進, 基本沒有問題. 惟一碰到的坑是最後將一個dsl文件拆分紅多個時, 發現須要將項目轉換爲xtext project才能支持(Xtext cross-reference across all files in project)github
接着的第二個教程: 15 Minutes Tutorial - Extended, 問題多了些.bash
"Unit Testing the Language"部分中的文件在.tests項目的src/中, 只有個小坑. 下面的parser就是原來模板文件中的parseHelpermarkdown
val model = parser.parse( "entity MyEntity { parent: MyEntity }") 複製代碼
"Creating Custom Validation Rules"部分中的checkFeatureNameIsUnique 初一運行後, 在同一Entity內兩個同名Feature沒有報錯, ==改成.equals()也無用. 細一看以後, 才發覺它是檢查父子Entity內是否有同名Feature. 好比在Comment中添加'author'的Feature, 如期報錯.框架
這裏感受到xtend語言的特別, 發現它自己也是個JVM語言: Xtend - Modernized Java, 不過貌似遠沒有Kotlin的流行度(後發現本站的代碼塊語言選項中居然有xtend).dom
首先, 嘗試生成中文關鍵詞的DSL. 默認ID只包含英文,數字,下劃線, 所以自定義IDENTIFIER,eclipse
grammar org.example.domainmodel.Domainmodel with org.eclipse.xtext.common.Terminals
generate domainmodel "http://www.example.org/domainmodel/Domainmodel"
import "http://www.eclipse.org/emf/2002/Ecore" as ecore
Domainmodel:
(elements+=AbstractElement)*;
PackageDeclaration:
'包' name=QualifiedName '{'
(elements+=AbstractElement)*
'}';
AbstractElement:
PackageDeclaration | Type | Import;
QualifiedName:
IDENTIFIER ('.' IDENTIFIER)*;
Import:
'導入' importedNamespace=QualifiedNameWithWildcard;
QualifiedNameWithWildcard:
QualifiedName '.*'?;
Type:
DataType | Entity;
DataType:
'數據類型' name=IDENTIFIER;
Entity:
'類' name=IDENTIFIER ('擴展' superType=[Entity|QualifiedName])? '{'
(features+=Feature)*
'}';
Feature:
(many?='複數')? name=IDENTIFIER ':' type=[Type|QualifiedName];
terminal IDENTIFIER: '^'?('\u4E00'..'\u9FA5'|'\uF900'..'\uFA2D'|'a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'_'|'0'..'9'|'\u4E00'..'\u9FA5'|'\uF900'..'\uFA2D')*;
複製代碼
一個小問題. 因爲IDENTIFIER開頭支持下劃線, Generate Xtext Artifacts時會警告以下, 但彷佛不影響語言生成, 下劃線開頭支持也正確:jvm
error(208): ../org.example.mydsl/src-gen/org/example/domainmodel/parser/antlr/internal/InternalDomainmodel.g:571:1: The following token definitions can never be matched because prior tokens match the same input: RULE_ID
error(208): ../org.example.mydsl.ide/src-gen/org/example/domainmodel/ide/contentassist/antlr/internal/InternalDomainmodel.g:1258:1: The following token definitions can never be matched because prior tokens match the same input: RULE_ID
複製代碼
另外一個問題是, 語法規則中的規則名稱不能用中文命名(好比Feature改成'性狀', PackageDeclaration改成'包聲明'等), 不然在Generate Xtext Artifacts生成報錯並中斷:
java.lang.RuntimeException: Problems running workflow org.xtext.example.mydsl.GenerateMyDsl: Problem parsing 'file:/Users/xuanwu/work/workspace-xtext/org.example.mydsl/../org.example.mydsl/src/org/xtext/example/mydsl/MyDsl.xtext': XtextSyntaxDiagnostic: null:10 extraneous input '包' expecting ':' 複製代碼
經測試, DSL語言高亮在Eclipse中顯示正確:
而且生成Java Beans正確(須要將數據類型名稱由上面的"字符串"改成"String"):
另外, 經測試xtend也支持中文命名(節選DomainmodelValidator以下), 但因爲xtext語法文件不支持中文標識符, 影響有限:
@Check def void 檢驗子類無父類重名性狀(Feature f) { var 父類 = (f.eContainer as Entity).superType while (父類 !== null) { for (其餘 : 父類.features) { if (f.name == 其餘.name) { error("子類性狀不能與父類中性狀重名", DomainmodelPackage.Literals.FEATURE__NAME) return } } 父類 = 父類.getSuperType(); } } 複製代碼
演示以下:
以上xtext項目源碼在program-in-chinese/xtext_tutorial_15_min_zh
測試DSL項目源碼: program-in-chinese/xtext_tutorial_15_min_zh
長處:
短處:
何嘗試: 能否定製自動補全功能, 語法報錯信息(好比下面)
另外但願有機會繼續嘗試下一篇教程: Five simple steps to your JVM language
2018-01-19