上下文依赖语法的xtext prase

时间:2017-01-29 17:54:50

标签: xtext

我有语法

Model:
    vars+=Vars*
    funcs+=Funcs*;

Name:
    name=ID;

VarName:
    Name;

FuncName:
    Name;

Funcs:
    'func' left=FuncName (bracket?='(' ')')? '=' right=[Name]';';

Vars:
    'var' VarName ';';

Func规则的右手大小可以是VarNameFuncName类型,具体取决于左侧大小的括号。

我必须修改xtext语法或进行一种验证/范围设计吗?

更新1

范围功能:

override getScope(EObject context, EReference reference) {
    if (context instanceof Funcs) {
        val func = context as Funcs
        if (reference == MultiNameDslPackage.Literals.FUNCS__RIGHT) {
            if (func.bracket) {
                val rootElement = EcoreUtil2.getRootContainer(context)
                val candidates = EcoreUtil2.getAllContentsOfType(rootElement, VarName)
                return Scopes.scopeFor(candidates)
            } else {
                val rootElement = EcoreUtil2.getRootContainer(context)
                val candidates = EcoreUtil2.getAllContentsOfType(rootElement, FuncName)
                return Scopes.scopeFor(candidates)
            }
        }
        return super.getScope(context, reference);
    }
}

左手大小与编辑器中括号的存在无关。

更新2

使用验证

@Check
def checkFuncContext(Funcs func) {
    if (func.bracket) {
        if (!(func.right instanceof VarName)) {
            warning("Right hand size must be of Var type", 
                MultiNameDslPackage.Literals.FUNCS__RIGHT
            )
        }
    } else {
        if (!(func.right instanceof FuncName)) {
            warning("Right hand size must be of Function type", 
                MultiNameDslPackage.Literals.FUNCS__RIGHT
            )
        }
    }
}

不执行警告声明。声明func.right instanceof FuncName)的行为不符合预期。

如何测试正确的实例?

更新3

使用修改后的语法

VarName:
    name=ID;

FuncName:
    name=ID;

Funcs:
    'func' left=FuncName (bracket?='(' ')')? '=' (right=[FuncName] | r1=[VarName]) ';';

无法编译:{{1​​}}

1 个答案:

答案 0 :(得分:1)

您需要更改语法以获取Name,FuncName和VarName的继承顺序(两者的名称超类型)

使用解析器片段

fragment Name: name=ID;

或使用

Name:VarName|FuncName;
VarName: name=ID;
FuncName:name=ID;