我目前正在使用xText创建DSL,但我正在绊倒一个可能与歧义或左递归问题有关的问题。我不确定这两个问题中的哪一个适用于我的情况(我在网上发现的类似主题也提到这些问题似乎经常相关),但我想这与左递归有关。
在DSL代码的第100行中,我声明了一个名为Expression的规则。如您所见,它聚合了多种其他类型(它们又聚合了多种其他类型,最终也可以聚合称为Factor的类型(第130行))。最终,整个“聚合树”归结为这种因子类型的问题。如您所见,此类型可以再次聚合一个表达式。所以有一个循环;表达式类型最终可以包含一个因子类型,然后该因子类型可以再次包含一个表达式类型(此后理论上该循环可以无限地继续;我猜这是问题所在,因为xText使用的ANTLR解析器不是为此设计的一种递归)。我试图通过在Expression类型中使用语法谓词(=>符号)解决此问题(请参见
(=> "endSimpleExpression")
,但仍然无法正常工作。我肯定知道这与类型Expressions和Factor之间的关系有关(因为如果不在Factor类型中添加Expression类型,则DSL可以正常工作)。我假设我没有将语法谓词放在正确的位置。我考虑过的另一个解决方案是使用左因子分解,但是在这种情况下,我不知道如何应用左因子分解。我很好奇您对这个问题的想法。
grammar org.xtext.example.mydsl.FinalDsl with org.eclipse.xtext.common.Terminals
generate finalDsl "http://www.xtext.org/example/mydsl/FinalDsl"
Model:
'functionName' name = STRING
functions += FunctionElements*
;
// Function elements of which the model exists. The model can contain
// library functions, for loops, and if/else statements.
FunctionElements:
ifElseStatements += IfElseStatements |
statements += Statement
;
// IfElse Statements requiring if statements and optionally followed by
// one else statement.
IfElseStatements:
ifStatements += IfStatements
(elseStatement = ElseStatement)?
;
// If statements requiring conditions and optionally followed by
// library functions or for loops.
IfStatements:
'if'
expression = Expression
(ifFunctions += libraryFunctionsEnum | forLoops += ForLoops)
;
// Else statement requiring one or multiple library functions.
ElseStatement:
'else' elseFunctions += libraryFunctionsEnum
;
// For loops requiring one condition and followed by zero or more
// library functions
ForLoops:
'for'
expressions = Expression
libraryFunctions += libraryFunctionsEnum*
;
Statement:
//compoundStatement += CompoundStatement | //left out of Statement because
// otherwise a recursive call exists (statement += compoundstatement += statement
simpleStatement += SimpleStatement |
structuredStatement += StructuredStatement
;
SimpleStatement:
classOperationStatement += ClassOperationStatement |
libraryInterFaceMethodStatement += LibraryInterFaceMethodStatement |
libraryPersistenceMethodStatement += LibraryPersistenceMethodStatement
;
StructuredStatement:
forLoops += ForLoops | ifElseStatements += IfElseStatements
;
ClassOperationStatement:
classOperationName += libraryFunctionsEnum
;
LibraryInterFaceMethodStatement:
interfaceMethods += libraryInterFaceMethodStatementEnum
;
LibraryPersistenceMethodStatement:
persistenceMethods += libraryPersistenceMethodStatementEnum
;
//*Eventually filled with details from class diagram, but for now we manually fill it for the sake of testing.
enum libraryFunctionsEnum:
login='login'|
hasCode= 'encrypt'|
display='display'
;
enum libraryPersistenceMethodStatementEnum:
createInstance = "createInstance" |
log = "log"
;
enum libraryInterFaceMethodStatementEnum:
mesasge = "message" |
error = "error"
;
Expression:
simpleExpression = SimpleExpression
(relationalOperator = RelationalOperator
additionalSimpleExpression = SimpleExpression)?
(=> "endSimpleExpression")
;
SimpleExpression:
term = Term
additionalExpressions += AdditionalExpressions*
;
AdditionalExpressions:
additionOperator = AdditionOperator
term = Term
;
Term:
factorTerm = Factor
additionalTerm += AdditionalTerm*
;
AdditionalTerm:
multiplicationOperator = MultiplicationOperator
factor = Factor
;
// We can optionally integrate Java types right here (int, boolean, string, etc.)
Factor: {Factor} (
"(" expression = Expression ")" |
//'not' factor += Factor |
operationParameterName = OperationParameterName |
classAttributeName += ClassAttributeName |
INT //| STRING //| set = Set
)
;
OperationParameterName: // We can use identifiers right here, but for now I put in a string
'operationParameter' STRING
;
ClassAttributeName: // We can use identifiers right here, but for now I put in a string
STRING
;
RelationalOperator:
"=" | "<>" | "<" | "<=" | ">" | ">=" | "in"
;
AdditionOperator:
"+" | "-" | "or"
;
MultiplicationOperator:
"*" | "/" | "and"
;
enum logicalOperators:
greaterThan='>'|
smallerThan='<'|
greaterOrEqualThan='=>'|
smallerOrEqualThan='<='|
equalTo='=='
;
答案 0 :(得分:0)
InternalFinalDsl.g:139:2:[致命]规则ruleFunctionElements具有非LL(*)决策,这是因为可以从alt 1,2到达的递归规则调用。
所以让我们看一下规则FunctionElements
:
FunctionElements:
ifElseStatements += IfElseStatements |
statements += Statement
;
好的,因此FunctionElements
可以是IfElseStatement
或Statement
。这听起来很可疑且足够肯定:Statement
可以是StructuredStatement
,而后者又可以是IfElseStatement
。因此,上述内容是不明确的,因为IfElseStatement
可以直接通过FunctionElements -> IfElseStatement
导出,也可以通过FunctionElements -> Statement -> StructuredStatement -> IfElseStatement
间接导出。
因此您应该简单地删除IfElseStatement
替代方案,因为它是多余的。