Xtext:关键字作为标识符

时间:2014-07-26 12:12:11

标签: glsl xtext

我有以下问题: 我正在为GLSL着色语言创建一个编辑器。我想在某些情况下允许关键字作为标识符,因为内置函数的名称可以用作标识符。

例如:vec3 texture=vec3(1,2,3);有效,即使texture是内置函数。

这是内置函数的规则:

BuiltInFunction:
'abs' |
'acos' |
'acosh' |
'all' |
'any' |
'asin' |
'asinh' |
'atan' |
'atanh' |
'atomicAdd' |
'atomicAnd' |
//etc...

这是标识符终端规则:

terminal IDENTIFIER: (('a'..'z')|('A'..'Z')|'_') (('a'..'z')|('A'..'Z')|'_'|('0'..'9'))*;

这是编辑器中的结果。 textureabs未被识别为标识符。

完整的参考语法:http://paste2.org/YwDNkBYW

解决方案:

我创建了一个包含所有内置函数的源文件:

common void abs(); 
common void acos(); 
common void acosh(); 
common void all(); 
common void any(); 
common void asin(); 
common void asinh(); 
common void atan(); 
common void atanh(); 
common void atomicAdd(); 
common void atomicAnd(); 
common void atomicCompSwap(); 
//etc...

我使用保留的关键字common来区分内置函数和本地创建的函数:

BuiltInFunctionDeclaration returns FunctionDeclaration:
    'common' qualifier=TypeQualifier? type=Type name=BuiltInFunction LEFT_PAREN (args+=Parameter (COMMA args+=Parameter)*)? RIGHT_PAREN (functionBlock=BlockStatement|SEMICOLON)
;

BuiltInFunction returns Function:
    ({BuiltInFunction}name=IDENTIFIER)
;

FunctionDeclaration:
    qualifier=TypeQualifier? type=Type name=Function LEFT_PAREN (args+=Parameter (COMMA args+=Parameter)*)? RIGHT_PAREN (functionBlock=BlockStatement|SEMICOLON)
;

Function:
    ({Function}name=IDENTIFIER)
;

...在ScopeProvider中添加了这些:

public IScope scope_CallFunction_name(CallFunction context,EReference reference){
    ... add local functions to list ...
    if(builtInFunctions==null){
        ResourceSet set=file.eResource().getResourceSet();
        Resource r=set.createResource(URI.createURI("internal:/builtin.glsl"));
        try {
            //Internals.builtInFunctions is a String of the source file.
            r.load(new ByteArrayInputStream(Internals.builtInFunctions.getBytes()), set.getLoadOptions());
        } catch (IOException e) {
            e.printStackTrace();
        }
        builtInFunctions=((GLSLFile) r.getContents().get(0)).getFunctions().stream()
                .map(FunctionDeclaration::getName)
                .collect(Collectors.toList());
    }
    functions.addAll(builtInFunctions);
    return Scopes.scopeFor(functions);
}

并在ISemanticHighlightingCalculator中我在迭代器循环中添加了这个检查:

        if(current instanceof CallFunction){
            if(((CallFunction) current).getName() instanceof BuiltInFunction){
                acceptor.addPosition(node.getOffset(), node.getLength(), "CallBuiltInFunction");
                continue;
            }
        }

1 个答案:

答案 0 :(得分:2)

在xtext中,关键字会覆盖IDENTIFIER规则。在规则中使用IDENTIFIER时,它永远不会匹配关键字。

如果你想要这样做,你必须将这些规则组合成一个新规则:

keywordOrIdentifier:
    BuiltInFunction | IDENTIFIER
;

然后你必须使用这个规则而不是IDENTIFIER规则:

Function:
    {Function} name=keywordOrIdentifier
;

通过此修改,您的语法将解析您想要的内容,例如:

vec3 texture(float x, float y) {
    return vec(1,2,3)
}

此解决方案的唯一问题是,纹理一词将被着色为关键字,而在此上下文中,它不是关键字。我认为您可以使用自定义 SemanticHighlighingCalculator 覆盖此行为。