0

我正在尝试创建一个包含数字和字符串的语法,如下所示:

日期:2013 年 3 月 2 日

我创建了一组或多或少适应这一点的规则:

Date:
     'Date': DAY Month YEAR
;

terminal DAY:
     ('1'..'9') | (('1'..'3')('0'..'9'))
;

Month:
     name = ('Jan'|'Feb'|'Mar'|'Apr)
;

terminal YEAR
     ('0'..'2)('0'..'9')('0'..'9')('0'..'9')
;

这套规则似乎有很多问题:

  1. 所写的日期规则似乎会产生错误:“不能在规则内更改类型两次”。我不知道这意味着什么,除了 Xtext 显然不允许在同一规则中使用数字和选择字符串。

  2. 如果我从 Date 中删除 Month 规则,Xtext 会编译,但语法似乎不能正常工作。DAY 规则应该提供从 1 到 9 的单个数字和两位数之间的选择,但由于某种原因,它只接受两位数。所以虽然我可以输入如下一行:

日期:2013 年 12 月

被接受,但日期如下:

日期:2013 年 2 月

不是。

我是否发现规则中的错误会破坏终端规则中的数字?或者是否缺少某些导致忽略“|”的内容 在我的号码里?另外:“不能在规则内两次更改类型”错误到底是什么意思,我该如何解决?

有人请指教。

4

1 回答 1

1

这里你有一个设计问题。通常,您必须尽可能少地使用自定义终端。自定义终端对您的语法具有全局影响,使语法不太灵活,错误恢复效率低下。

我理解你的意图:你想限制你的 DSL 以防止解析不敏感的数据。这是一个好主意,但自定义终端不是为此类任务设计的。经验法则是:

  • 尽可能多地使用标准终端
  • 让您的词法分析器解析几乎所有输入
  • 让您的解析器检测语法错误(例如缺少 ']'),但不检测域约束,例如 (1 <= Day <= 31)。
  • 添加验证以检查域约束并提供用户友好的错误和警告消息
  • 添加快速修复
  • 根据您的域限制调整内容助手

在您的情况下,我建议使用以下简单语法:

Date:
    'Date': day=INT month=Month year=INT
;

enum Month:
    JANUARY='Jan'
|   FEBRUARY='Feb'
|   MARCH='Mar'
|   APRIL='Apr'
;

比我实施一个自定义验证器来检查日期和年份是否在允许的范围内。这是一个文档,如何做到这一点:

于 2013-03-18T10:44:26.183 回答