2018-01-19 Xtext試用: 快速實現簡單領域專用語言(DSL)

来源:https://www.cnblogs.com/program-in-chinese/archive/2019/03/07/10488664.html
-Advertisement-
Play Games

環境搭建 使用的Eclipse版本: Oxygen.1a Release (4.7.1a) Build id: 20171005 1200, 通過添加 "Xtext Download" 上列出的Releases update site安裝xtext IDE和xtext SDK. 之後打開Eclips ...


環境搭建

使用的Eclipse版本: Oxygen.1a Release (4.7.1a) Build id: 20171005-1200, 通過添加Xtext - Download上列出的Releases update site安裝xtext IDE和xtext SDK. 之後打開Eclipse, 打開任何文件就報錯:

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-0600

官方教程原代碼試用

首先, 參考官方教程: 15 Minutes Tutorial

教程按部就班, 基本沒有問題. 唯一碰到的坑是最後將一個dsl文件拆分成多個時, 發現需要將項目轉換為xtext project才能支持(Xtext cross-reference across all files in project)

接著的第二個教程: 15 Minutes Tutorial - Extended, 問題多了些.

"Unit Testing the Language"部分中的文件在.tests項目的src/中, 只有個小坑. 下麵的parser就是原來模板文件中的parseHelper

    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).

框架對中文的支持

首先, 嘗試生成中文關鍵詞的DSL. 預設ID只包含英文,數字,下劃線, 因此自定義IDENTIFIER,

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時會警告如下, 但似乎不影響語言生成, 下劃線開頭支持也正確:

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中顯示正確:
2018-01-19-xtext高亮eclipse

並且生成Java Beans正確(需要將數據類型名稱由上面的"字元串"改為"String"):
2018-01-19-xtext_beans

另外, 經測試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();
        }
    }

演示如下:
2018-01-19-xtext重命名error

以上xtext項目源碼在program-in-chinese/xtext_tutorial_15_min_zh

測試DSL項目源碼: program-in-chinese/xtext_tutorial_15_min_zh

初步小結

長處:

短處:

  • 最大問題是語法規則中標識符不能中文命名, 直接導致相關的代碼生成器(generator)和驗證器使用的多數API只能是英文(如上面的.name, .features).
  • Eclipse版本或者插件衝突問題需要規避
  • 需要學習xtend語言, 雖然可能很像Java

未嘗試: 可否定製自動補全功能, 語法報錯信息(比如下麵)
2018-01-19-xtext語法error

另外希望有機會繼續嘗試下一篇教程: Five simple steps to your JVM language


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • (盜圖鎮樓) 多頁應用 每一次頁面跳轉的時候,後臺伺服器都會返回一個新的html文檔,這種類型的網站就是多頁網站,也叫多頁應用。{頁面跳轉——>返回html} 優點是:首屏時間快,seo效果好;缺點是:頁面切換慢; 為什麼多頁應用的首屏時間快? 首屏時間叫做頁面首個屏幕的內容展現時間,當我們訪問頁面 ...
  • "知乎原鏈" 本文為 "中文代碼示例之5分鐘入門TypeScript" 的 "CTS" 版本. CTS作者是@htwx(github). 它實現了關鍵詞和標準庫的所有命名漢化. 本文並未使用附帶的vscode相關插件(包括CTS語言插件和拼音輸入插件), 與原Typescript教程類似, 只用了命 ...
  • 前段時間做了微信自定義分享的功能,分享出的頁面存在邀請碼在ios手機上複製失敗的問題,然而在PC端和安卓機上是沒有問題的。百度了一下,基本給出的解決方案是:ios不單純支持on,為點擊的元素添加空點擊事件:onclick="",眾說芸芸,但是試了下沒一個有用! 如果你複製的文本內容來自是input的 ...
  • 題目 169. 求眾數 給定一個大小為 n 的數組,找到其中的眾數。眾數是指在數組中出現次數大於 ⌊ n/2 ⌋ 的元素。 你可以假設數組是非空的,並且給定的數組總是存在眾數。 示例 1: 示例 2: 眾數(Mode)是統計學名詞,在統計分佈上具有明顯集中趨勢點的數值,代表數據的一般水平(眾數可以不 ...
  • 一、什麼是橋接模式 橋接模式(Bridge Pattern):將抽象部分與它的實現部分分離,使它們都可以獨立地變化。它是一種對象結構型模式,又稱為柄體(Handle and Body)模式或介面(Interface)模式。 二、橋接模式的結構 在橋接模式結構圖中包含如下幾個角色: ●Abstract ...
  • 如果第二次看到我的文章,歡迎右側掃碼訂閱我喲~ 👉 本文長度為5389字,建議閱讀14分鐘。 堅持原創,每一篇都是用心之作~ 沒想到這篇文章寫了這麼長,一時半會沒消化完的話,可以收藏一下先。 這是「伸縮性」章節的第四篇,先給新來的小伙伴們簡單回顧下前三篇的內容。 做「伸縮性」最重要的就是先做好「無 ...
  • Gobelieve 架構 Gobelieve github地址 im 客戶連接伺服器 (可分散式部署,暫無負載均衡模塊) imr 路由查詢伺服器(主要解決im分散式部署的問題) ims 存儲伺服器 (主從部署) 基礎模塊 1.數據包協議 包:header(12)|body header:len(4) ...
  • 很久之前的讀書整理內容,躺在草稿里很久了。。。 一、 "開放-封閉"原則(OCP) Open-Closed Principle原則講的是:一個軟體實體應當對擴展開放,對修改關閉。 優點: 通過擴展已有軟體系統,可以提供新的行為,以滿足對軟體的新的需求,使變化中的軟體有一定的適應性和靈活性。 已有軟體 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...