如何重写此语法,使其不再有歧义
How to rewrite this grammar so it's not ambiguous anymore
我目前正在研究一种语法,它应该允许我定义本地和全局数组或变量。
本地的以下划线开头,这是名称中唯一的区别。没有特殊的关键字来定义它是局部的还是全局的,也没有关键字来指示声明是数组还是变量。
变量可以是一些普通类型和对另一个变量(局部或全局)的引用,数组可以用标准大括号声明或作为对现有数组的引用。
问题是如果 "name=reference" 是变量或数组,Xtext 无法分隔。
这是我现有的语法:
grammar org.declarations.dec.Dec with org.eclipse.xtext.common.Terminals
import "http://www.eclipse.org/emf/2002/Ecore" as ecore
generate dec "http://www.declarations.org/dec/Dec"
Model:
delarations+=(Declaration)*
;
Declaration:
Variable ";" | Array ";"
;
Variable:
LocalVar
| GlobalVar
;
LocalVar:
name=LOCALNAME "=" variableContent=VarContent
;
GlobalVar:
name=GLOBALNAME "=" variableContent=VarContent
;
VarContent:
stringContent=STRING
| IntContent=INT
| localRef=[LocalVar|LOCALNAME]
| globalRef=[GlobalVar|GLOBALNAME]
;
Array:
LocalArray
|GlobalArray
;
LocalArray:
name=LOCALNAME "=" content=ArrayLiteral
;
GlobalArray:
name=GLOBALNAME "=" content=ArrayLiteral
;
ArrayLiteral:
"[" (c1=ArrayContent ("," c2+=ArrayContent)*)? "]"
| localRef=[LocalArray|LOCALNAME]
| globalRef=[GlobalArray|GLOBALNAME]
;
ArrayContent:
varContent=VarContent
| localRef=[LocalArray|LOCALNAME]
| globalRef=[GlobalArray|GLOBALNAME]
;
terminal LOCALNAME:
"_" ('a'..'z'|'A'..'Z') ('a'..'z'|'A'..'Z'|'_'|'0'..'9')*
;
terminal GLOBALNAME:
('a'..'z'|'A'..'Z') ('a'..'z'|'A'..'Z'|'_'|'0'..'9')*
;
我要识别的代码例如是:
_localVar1 = "Test";
globalVar1 = _localVar1;
globalArray = ["hello",globalVar1];
nextArray = globalArray;
anotherArray = [globalArray, nextArray];
有没有人知道如何解决这个问题?
你好 Krzmbrzl
由于我的问题仅通过评论回答,所以我会写一个答案,这样问题就不会出现在未回答的部分。感谢 Christian Dietrich,我找到了解决方案:
解决方案是让解析器忽略声明是变量还是数组,也忽略声明是局部的还是全局的。生成的语法如下所示:
Model:
elements += Code*
;
Code:
dec=Declaration ";"
;
Declaration:
name = ID "=" decCon=DecContent
;
DecContent:
singleContent=VarContent (op+=OPERATOR nextCon+=VarContent)*
;
VarContent:
num = NUMBER
| string = STRING
| reference = [Declaration]
| "+"? arrayContent=ArrayLiteral
;
ArrayLiteral:
con = "[" (content = VarContent ("," nextContent += VarContent)*)? "]"
;
确定声明是变量、数组、局部还是全局是验证器的任务。
这里的规则是:尽可能少地使用解析器,而尽可能多地使用验证器。
希望在您遇到类似问题时能对您有所帮助。
你好 Krzmbrzl
我目前正在研究一种语法,它应该允许我定义本地和全局数组或变量。
本地的以下划线开头,这是名称中唯一的区别。没有特殊的关键字来定义它是局部的还是全局的,也没有关键字来指示声明是数组还是变量。
变量可以是一些普通类型和对另一个变量(局部或全局)的引用,数组可以用标准大括号声明或作为对现有数组的引用。
问题是如果 "name=reference" 是变量或数组,Xtext 无法分隔。
这是我现有的语法:
grammar org.declarations.dec.Dec with org.eclipse.xtext.common.Terminals
import "http://www.eclipse.org/emf/2002/Ecore" as ecore
generate dec "http://www.declarations.org/dec/Dec"
Model:
delarations+=(Declaration)*
;
Declaration:
Variable ";" | Array ";"
;
Variable:
LocalVar
| GlobalVar
;
LocalVar:
name=LOCALNAME "=" variableContent=VarContent
;
GlobalVar:
name=GLOBALNAME "=" variableContent=VarContent
;
VarContent:
stringContent=STRING
| IntContent=INT
| localRef=[LocalVar|LOCALNAME]
| globalRef=[GlobalVar|GLOBALNAME]
;
Array:
LocalArray
|GlobalArray
;
LocalArray:
name=LOCALNAME "=" content=ArrayLiteral
;
GlobalArray:
name=GLOBALNAME "=" content=ArrayLiteral
;
ArrayLiteral:
"[" (c1=ArrayContent ("," c2+=ArrayContent)*)? "]"
| localRef=[LocalArray|LOCALNAME]
| globalRef=[GlobalArray|GLOBALNAME]
;
ArrayContent:
varContent=VarContent
| localRef=[LocalArray|LOCALNAME]
| globalRef=[GlobalArray|GLOBALNAME]
;
terminal LOCALNAME:
"_" ('a'..'z'|'A'..'Z') ('a'..'z'|'A'..'Z'|'_'|'0'..'9')*
;
terminal GLOBALNAME:
('a'..'z'|'A'..'Z') ('a'..'z'|'A'..'Z'|'_'|'0'..'9')*
;
我要识别的代码例如是:
_localVar1 = "Test";
globalVar1 = _localVar1;
globalArray = ["hello",globalVar1];
nextArray = globalArray;
anotherArray = [globalArray, nextArray];
有没有人知道如何解决这个问题?
你好 Krzmbrzl
由于我的问题仅通过评论回答,所以我会写一个答案,这样问题就不会出现在未回答的部分。感谢 Christian Dietrich,我找到了解决方案:
解决方案是让解析器忽略声明是变量还是数组,也忽略声明是局部的还是全局的。生成的语法如下所示:
Model:
elements += Code*
;
Code:
dec=Declaration ";"
;
Declaration:
name = ID "=" decCon=DecContent
;
DecContent:
singleContent=VarContent (op+=OPERATOR nextCon+=VarContent)*
;
VarContent:
num = NUMBER
| string = STRING
| reference = [Declaration]
| "+"? arrayContent=ArrayLiteral
;
ArrayLiteral:
con = "[" (content = VarContent ("," nextContent += VarContent)*)? "]"
;
确定声明是变量、数组、局部还是全局是验证器的任务。
这里的规则是:尽可能少地使用解析器,而尽可能多地使用验证器。
希望在您遇到类似问题时能对您有所帮助。
你好 Krzmbrzl