环境搭建

使用的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中显示正确:

并且生成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

初步小结

长处:

短处:

  • 最大问题是语法规则中标识符不能中文命名, 直接导致相关的代码生成器(generator)和验证器使用的多数API只能是英文(如上面的.name, .features).
  • Eclipse版本或者插件冲突问题需要规避
  • 需要学习xtend语言, 虽然可能很像Java

未尝试: 可否定制自动补全功能, 语法报错信息(比如下面)

另外希望有机会继续尝试下一篇教程: Five simple steps to your JVM language

2018-01-19 Xtext试用: 快速实现简单领域专用语言(DSL)的更多相关文章

  1. 2018.08.19 NOIP模拟 change(简单模拟)

    Change 题目背景 SOURCE:NOIP2015-SHY-10 题目描述 Alice 和 Bob 又聚在一起了!他们已经厌倦了取石子游戏,现在他们热衷于切题.于是,Alice 找到了一道题让 B ...

  2. 2018-01-19 Xtext试用: 5步实现一个(中文)JVM语言

    续上文Xtext试用: 快速实现简单领域专用语言(DSL). 基于官方教程: Five simple steps to your JVM language 达成如下语言: 它被Quan6JvmMode ...

  3. 解题报告:poj 3070 - 矩阵快速幂简单应用

    2017-09-13 19:22:01 writer:pprp 题意很简单,就是通过矩阵快速幂进行运算,得到斐波那契数列靠后的位数 . 这是原理,实现部分就是矩阵的快速幂,也就是二分来做 矩阵快速幂可 ...

  4. 拿nodejs快速搭建简单Oauth认证和restful API server攻略

    拿nodejs快速搭建简单Oauth认证和restful API server攻略:http://blog.csdn.net/zhaoweitco/article/details/21708955 最 ...

  5. Ext.Net学习笔记19:Ext.Net FormPanel 简单用法

    Ext.Net学习笔记19:Ext.Net FormPanel 简单用法 FormPanel是一个常用的控件,Ext.Net中的FormPanel控件同样具有非常丰富的功能,在接下来的笔记中我们将一起 ...

  6. springmvc 项目完整示例01 需求与数据库表设计 简单的springmvc应用实例 web项目

    一个简单的用户登录系统 用户有账号密码,登录ip,登录时间 打开登录页面,输入用户名密码 登录日志,可以记录登陆的时间,登陆的ip 成功登陆了的话,就更新用户的最后登入时间和ip,同时记录一条登录记录 ...

  7. IDC Digital Transition Annual Festival(2018.10.19)

    时间:2018.10.19地点:北京万达文化酒店

  8. 2018.10.19浪在ACM 集训队第一次测试赛

    2018.10.19浪在ACM 集训队第一次测试赛 待参考资料: [1]:https://blog.csdn.net/XLno_name/article/details/78559973?utm_so ...

  9. 20172319 2018.10.19《Java程序设计教程》第7周课堂实践(补写博客)

    20172319 2018.10.19 <Java程序设计教程>第7周课堂实践 课程:<程序设计与数据结构> 班级:1723 学生:唐才铭 学号:20172319 指导老师:王 ...

随机推荐

  1. 2月第3周业务风控关注|上海网信办复测23个被约谈APP 涉及1号店、小红书等

    易盾业务风控周报每周呈报值得关注的安全技术和事件,包括但不限于内容安全.移动安全.业务安全和网络安全,帮助企业提高警惕,规避这些似小实大.影响业务健康发展的安全风险. 1.上海网信办复测23个被约谈A ...

  2. 调用redis的时候二维码不断刷新的排查

    一.背景和现象. 项目是PHP开发的,点击登录的时候就根据随机数生成了二维码,缓存在了redis.用户用微信扫描了二维码分析出需要请求的链接,然后微信浏览器就请求了服务器,服务器通过了随机数认证.正当 ...

  3. 深圳scala-meetup-20180902(1)- Monadic 编程风格

    刚完成了9月份深圳scala-meetup,趁刮台风有空,把我在meetup里的分享在这里发表一下.我这次的分享主要分三个主题:“Monadic编程风格“.”Future vs Task and Re ...

  4. WannaCry勒索病毒全解读,权威修复指南大集合

    多地的出入境.派出所等公安网络疑似遭遇了勒索蠕虫病毒袭击,已暂时停办出入境业务:加油站突然断网,不能支持支付宝.微信.银联卡等联网支付:大批高校师生电脑中的文件被蠕虫病毒加密,需要支付相应的赎金方可解 ...

  5. JavaScript实现单张图片上传功能

    前台jsp代码 <%@ page language="java" pageEncoding="UTF-8" contentType="text/ ...

  6. 《JavaScript面向对象编程指南》读书笔记①

    概述 JavaScript快忘完了,想看一本专业书拾遗,所以看了这本<JavaScript面向对象编程指南>. 个人觉得这本书讲的很透彻很易懂,一些原来有疑惑的地方在这本书里面豁然开朗,看 ...

  7. JavaScript 交换数组元素位置的几种方式

    前言 交换数组元素位置是开发项目中经常用到的场景,总结下用过的几种方式. 第三方变量 最基础的方式,创建一个变量作为中转. let temp = array[index1]; array[index1 ...

  8. 内存管理cpuset,mempolicy[原理]

    介绍cpuset,mbind,set_mempolicy在内存管理上的应用 change log :确定先从mempolicy的man 手册翻译开始研究,计划如下 .先从man手册入手,通过实现mem ...

  9. Go语言之Interface(一)

    Go语言之Interface(一) 什么是interface 在面向对象语言中接口是:接口定义了一个对象的行为,但在Go中接口就是方法签名的集合,当一个类型提供了这个接口中的所有的方法,就可以说这个类 ...

  10. [视频]K8飞刀 Google黑客功能教程

    [视频]K8飞刀 Google黑客功能教程 链接:https://pan.baidu.com/s/1kbK5jNH8ZaddUEeQ9IwTaw 提取码:lwl6