我有以下问题: 我正在为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'))*;
这是编辑器中的结果。 texture
和abs
未被识别为标识符。
完整的参考语法: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;
}
}
答案 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 覆盖此行为。