XText键入的文字

时间:2014-10-26 11:35:14

标签: types xtext

另一个XText问题。在尝试使用XText时,我尝试创建一种能够进行基本变量声明和值赋值的语言。我的第一次尝试是这样的:

Grammar:
    elements+=Element*;

Element:
    Declaration | ValueAssignment;

Declaration:
    type=Type isArray='[]'? name=ID;

enum Type:
    int | string;

ValueAssignment:
    declaration=[Declaration] '=' ???;

所以一个简单的例子看起来像这样:

int foo
int[] bar
string fooBar

foo = 10
bar = { 10, 20, 30 }
fooBar = "Sample text"

所以我的问题:

  • 如果我们不考虑阵列部分 现在,我怎么能强制执行,如果Declaration有一个类型 int,那么只有这样的文字可以在一个右侧 赋值,什么匹配整数正则表达式? string相同吗?
  • 如果我们考虑阵列部分,怎么办呢? 当然,我可以写一条规则,比如ArrayLiteral: {ArrayLiteral}'{' elements+=???* '}'; 但是元素规则的类型是什么?我怎么能确保那里的类型?

我浏览了XText指南,但是在任何类型发挥作用的地方,它都使用了非常令人困惑的XBase元素。任何帮助,或指示从哪里开始将不胜感激!

更新

我设法对这个简单的例子进行基本类型检查,但是我不确定这是否是最佳解决方案:

稍微修改过的语法:

Grammar:
    elements+=Element*;

Element:
    Declaration | ValueAssignment;

Declaration:
    type=Type isArray?='[]'? name=ID;

enum Type:
    int | string;

ValueAssignment:
    declaration=[Declaration] '=' value=Literal;

IntLiteral:
    value=INT;

StringLiteral:
    value=STRING;

PrimitiveLiteral:
    IntLiteral | StringLiteral;

ArrayLiteral:
    {ArrayLiteral} '{' elements+=PrimitiveLiteral* '}';

Literal:
    PrimitiveLiteral | ArrayLiteral;

它上面有一个验证器(语法本身对类型没有约束):

class MyDslValidator extends AbstractMyDslValidator {

    public static val INVALID_TYPE = 'invalidType'

    @Check
    def checkTypeOfValueAssignment(ValueAssignment valAssign) {
        val isArray = valAssign.declaration.isArray
        val type = valAssign.declaration.type
        val literal = valAssign.value
        if (isArray) {
            if (!(literal instanceof ArrayLiteral)) {
                error(
                    "Invalid primitive literal, array required"
                    , MyDslPackage.Literals.VALUE_ASSIGNMENT__VALUE
                    , INVALID_TYPE
                )
                return
            }
            val arrLiteral = literal as ArrayLiteral
            arrLiteral.elements.forEach[l | l.checkType(type) ]
        } else {
            val primLiteral = literal as PrimitiveLiteral
            primLiteral.checkType(type)
        }
    }

    def checkType(PrimitiveLiteral element, Type type) {
        if (type == Type.INT && !(element instanceof IntLiteral)) {
            error(
                "Invalid primitive literal, int required"
                , MyDslPackage.Literals.VALUE_ASSIGNMENT__VALUE
                , INVALID_TYPE
            )
            return
        } 
        if (type == Type.STRING && !(element instanceof StringLiteral)) {
            error(
                "Invalid primitive literal, string required"
                , MyDslPackage.Literals.VALUE_ASSIGNMENT__VALUE
                , INVALID_TYPE
            )
        }
    }
}

我修改后的问题:这样做可以吗?

3 个答案:

答案 0 :(得分:2)

关于Xsemantics的一个小小的补充(我是它的作者,它仍然在积极开发):DSL的语法是为了模仿正式类型系统之一;所以如果你不熟悉正式的类型系统,可能很难理解。但是,我认为,如果你计划实施任何非平凡类型的系统,那么无论如何都需要对正式类型系统有一个小而基本的理解。

答案 1 :(得分:1)

使用语法,您可以编写语言的语法。源代码的语义通常不能用语法实现。因此,Xtext项目中有验证类。它应该用于检查源代码的语义。

是的,您解决了Xtext提供的问题。我不知道你的网络搜索是否那么深,但也许你已经读过一些关于' Xsemantics'这是另一个用于实现Xtext语言类型系统的Eclipse插件。它有一种花哨且难以理解的DSL写入类型规则,然后将其转换为Java源代码并集成到您的“... MyDslValidator”的类型层次结构中。类。

答案 2 :(得分:0)

我建议你也写一个类型的计算机类来提供预期的和实际的类型,然后在你的Validator中使用它。