在Xtext中为2个不同的句法规则使用相同的关键字

时间:2016-01-11 10:42:12

标签: eclipse model grammar xtext

我正在使用Xtext来指定语法,并且在编写可能以相同关键字开头且既没有相同语法也没有相同语义的2条规则时遇到问题。但在发电时,发电机表示这两条规则的超级规则没有LLF决定。 当我从一个规则中抑制含糊不清的关键字时,它会正确生成。 我怎样才能确定它?

以下是详细信息:

关键字设置:

enum QuantifiedComplexExpressionQuantifier returns QuantifiedComplexExpressionQuantifier:
            all = 'all' | sum = 'sum' | no = 'no' | one = 'one' | lone = 'lone'  | some = 'some';

enum QuantifiedTerminalExpressionQuantifier returns QuantifiedTerminalExpressionQuantifier:
            seq = 'seq' | set = 'set' | no = 'no' | one = 'one' | lone = 'lone'  | some = 'some';

2条规则及其超级规则:

QuantifiedExpression returns QuantifiedExpression:
QuantifiedComplexExpression |
QuantifiedTerminalExpression;   

QuantifiedComplexExpression returns QuantifiedComplexExpression :   
quantifier=QuantifiedComplexExpressionQuantifier =>varDeclaration+=VarDeclaration ( =>"," =>varDeclaration+=VarDeclaration)* =>blockOrBar=BlockOrBar;

QuantifiedTerminalExpression returns QuantifiedTerminalExpression:  
quantifier=QuantifiedTerminalExpressionQuantifier =>expr=TerminalExpression;

当我尝试使用这样的枚举生成时,规则QuantifiedExpression具有非LLF决策。但是当我从一组或另一组中抑制(如下所示)共享关键字时,语法就会生成。

Normaly,它应该是可能的,因为语法是不同的;在一种情况下,它是一元表达式,另一种情况是对一组元素的约束声明。

enum QuantifiedComplexExpressionQuantifier returns QuantifiedComplexExpressionQuantifier:
            all = 'all' | sum = 'sum' ;

enum QuantifiedTerminalExpressionQuantifier returns QuantifiedTerminalExpressionQuantifier:
            seq = 'seq' | set = 'set' | no = 'no' | one = 'one' | lone = 'lone'  | some = 'some';

完整的语法:

// automatically generated by Xtext
grammar org.xtext.alloy.Alloy with org.eclipse.xtext.common.Terminals

import "http://fr.cuauh.als/1.0" 
import "http://www.eclipse.org/emf/2002/Ecore" as ecore

//specification ::= [module] open* paragraph* 
//ok
Specification returns Specification:
{Specification}
(module=Module)?
(opens+=Library (opens+=Library)*)?
(paragraphs+=Paragraph (paragraphs+=Paragraph)*)?;

//module ::= "module" name  [ "["  ["exactly"] name  ("," ["exactly"] num)*    "]" ]
//module ::= "module" name?  [ "["  ["exactly"] name  ("," ExactlyNum )* "]" ]
//ok
Module returns Module:
{Module}
'module' (name=IDName)? ('['(exactly?='exactly')? extensionName=[Ref] (nums+=ExactlyNums ( "," nums+=ExactlyNums)*)?']')?
;


terminal ID         : '^'?('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'_'|'0'..'9'|'/')*;
//open ::= ["private"]  "open"  name  [ "[" ref,+ "]" ]  [ "as" name ]
//open ::= ["private"]  "open"  path  [ "[" ref,+ "]" ]  [ "as" name ]
//ok
Library returns Library:
{Library}
(private?='private')? 'open' path=EString ('['references+=Reference (',' references+=Reference)*']')? ('as' alias=Alias)? 
;
//a path 
//ok
//terminal PATH returns ecore::EString :
//  ('a'..'z'|'A'..'Z'|'_'|'.')+('/'('a'..'z'|'A'..'Z'|'_'|'.')+)*
//;

//paragraph ::= factDecl | assertDecl | funDecl | cmdDecl | enumDecl | sigDecl
//paragraph ::= factDecl | assertDecl | funDecl | predDecl | cmdDecl | enumDecl | sigDecl
//ok
Paragraph returns Paragraph:
FactDeclaration | AssertDeclaration | FunctionDeclaration | PredicatDeclaration | CmdDeclaration | EnumerationDeclaration | SignatureDeclaration;

//cmdDecl ::= [name ":"] ("run"|"check") (name|block) scope
//cmdDecl ::= [name ":"] command (ref|block) scope ["expect (0|1)"]
//ok
CmdDeclaration returns CmdDeclaration:
(name=IDName ':')? operation=cmdOp referenceOrBlock=ReferenceOrBlock (scope=Scope)? (expect?='expect' expectValue=EInt)?;

//ok
ReferenceOrBlock returns ReferenceOrBlock:
BlockExpr | ReferenceName;  

//sigDecl ::= sigQual* "sig" name,+ [sigExt] "{" decl,* "}" [block]
//sigDecl ::= ["private"] ["abstract"] [quant] "sig" name [sigExt] "{" relDecl,* "}" [block]
//ok
SignatureDeclaration returns SignatureDeclaration:
{SignatureDeclaration}
(isPrivate?='private')? (isAbstract?='abstract')? (quantifier=SignatureQuantifier)? 'sig' name=IDName (extension=SignatureExtension)? '{'
(relations+=RelationDeclaration ( ',' =>relations+=RelationDeclaration)* )? 
'}'
(block=Block)?;

//ok
SignatureExtension returns SignatureExtension:
SignatureinInheritance | SignatureInclusion;


TypeScopeTarget returns TypeScopeTarget:
Int0 | Seq | ReferenceName;

//EBoolean returns ecore::EBoolean:
//  'true' | 'false';

//["exactly"] num
//ok
ExactlyNums returns ExactlyNums:
exactly?='exactly' num=Number;

//ok do not need to be part of the concrete syntax
//  IDName | IDref;

Ref returns Ref : 
This | IDRef
;

IDRef returns IDRef:
namedElement=[IDName] ("/"refs=IDRef)?
;

IDName returns IDName:
name=ID
;   

This returns This:
{This}
'this' ("/"refs=IDRef)?
;

EString returns ecore::EString:
STRING | ID;

//ok
EInt returns ecore::EInt:
'-'? INT;

Alias returns Alias:
{Alias}
name=IDName;



//factDecl ::= "fact" [name] block
//ok
FactDeclaration returns FactDeclaration:
'fact' (name=IDName)? block=Block;

//assertDecl ::= "assert" [name] block
//ok
AssertDeclaration returns AssertDeclaration:
'assert' (name=IDName)? block=Block ;

//funDecl ::= ["private"] "fun" [ref "."] name "(" decl,* ")" ":" expr block
//funDecl ::= ["private"] "fun" [ref "."] name "[" decl,* "]" ":" expr block
//funDecl ::= ["private"] "fun" [ref "."] name                ":" expr block
//
//funDecl ::= ["private"] "fun" [ref "."] name ["(" paramDecl,* ")" | "[" paramDecl,* "]" ] ":" expr block
//ok
FunctionDeclaration returns FunctionDeclaration:
(private?='private')? 'fun' (reference=[Reference] ".")?    name=IDName
    ('(' (parameters+=ParameterDeclaration ( "," parameters+=ParameterDeclaration)*)? ')'|
     '[' (parameters+=ParameterDeclaration ( "," parameters+=ParameterDeclaration)*)? ']')?
    ':' ^returns=Expression
    block=Block;

//funDecl ::= ["private"] "pred" [ref "."] name "(" decl,* ")" block
//funDecl ::= ["private"] "pred" [ref "."] name "[" decl,* "]" block
//funDecl ::= ["private"] "pred" [ref "."] name                block
//
//predDecl ::= ["private"] "pred" [ref "."] name ["(" paramDecl,* ")" | "[" paramDecl,* "]" ] ":" block
//ok
PredicatDeclaration returns PredicatDeclaration:
(private?='private')? 'pred' (reference=[Reference|EString] ".")? name=IDName
    ('(' (parameters+=ParameterDeclaration ( "," parameters+=ParameterDeclaration)*)? ')'|
     '[' (parameters+=ParameterDeclaration ( "," parameters+=ParameterDeclaration)*)? ']')?
    block=Block;


//enumDecl ::= "enum" name "{" name  ("," name)*  "}"
//enumDecl ::= "enum" name "{" enumEl  ("," enumEl)*  "}"
//ok
EnumerationDeclaration returns EnumerationDeclaration:
'enum' name=IDName '{' enumeration+=EnumerationElement ( "," enumeration+=EnumerationElement)* '}';


//ok
EnumerationElement returns EnumerationElement:
{EnumerationElement}
name=IDName;

//"lone" | "one" | "some" 
//ok
enum SignatureQuantifier returns SignatureQuantifier:
lone = 'lone' | one = 'one' | some = 'some';


//decl ::= ["private"] ["disj"] name,+ ":" ["disj"] expr
//decl ::= ["private"] ["disj"] name,+ ":" ["disj"] expr
//ok
RelationDeclaration returns RelationDeclaration:
(isPrivate?='private')? (varsAreDisjoint?='disj')? names+=VarDecl (',' names+=VarDecl)* ':' (expressionIsDisjoint?='disj')? expression=Expression;

//sigExt ::= "extends" ref
//ok
SignatureinInheritance returns SignatureinInheritance:
'extends' extends=Reference;
//sigExt ::= "in" ref ["+" ref]*
//ok
SignatureInclusion returns SignatureInclusion:
'in' includes+=Reference ( "+" includes+=Reference)* ;

//ok
VarDecl returns VarDecl:
{VarDecl}
name=IDName;

//decl ::= ["private"] ["disj"] name,+ ":" ["disj"] expr
//ok
ParameterDeclaration returns ParameterDeclaration:
(isPrivate?='private')? (varsAreDisjoint?='disj')? names+=VarDecl ( "," names+=VarDecl)* ':' (expressionIsDisjoint?='disj')? expression=Expression;

//("run"|"check")
//ok
enum cmdOp returns cmdOp:
run = 'run' | check = 'check';


//expr ::= 
//1)          "let" letDecl,+ blockOrBar
//2)        | quant decl,+    blockOrBar
//3)        | unOp expr
//4)        | expr binOp   expr
//5)        | expr arrowOp expr
//6)        | expr ["!"|"not"] compareOp expr
//7)        | expr ("=>"|"implies") expr "else" expr
//8)        | expr "[" expr,* "]"
//9)        |     number
//10)       | "-" number
//11)       | "none"
//12)       | "iden"
//13)       | "univ"
//14)       | "Int"
//15)       | "seq/Int"
//16)       | "(" expr ")"
//17)       | ["@"] Name
//18)       | block
//19)       | "{" decl,+ blockOrBar "}" 

//  expr ::= leftPart [rightPart]
Expression returns Expression:
lhs=NonLeftRecursiveExpression (=>parts=NaryPart)?;     

//4)        | expr binOp   expr
//5)        | expr arrowOp expr
//6)        | expr ["!"|"not"] compareOp expr
//7)        | expr ("=>"|"implies") expr "else" expr
//8)        | expr "[" expr,* "]"
//ok
NaryPart returns NaryPart:
BinaryOrElsePart | CallPart;

//4)        | expr binOp   expr
//5)        | expr arrowOp expr
//6)        | expr ["!"|"not"] compareOp expr
//7)        | expr ("=>"|"implies") expr "else" expr
//
//7)        | expr ("=>"|"implies") expr "else" expr
//4)5)6)    | expr binaryOperator expr*
//ok
BinaryOrElsePart returns BinaryOrElsePart:
=>('=>'|'implies') rhs=Expression (=>'else' else=Expression)? |
operator=BinaryOperator rhs=Expression ;

//8)        | expr "[" expr,* "]"
//it is just the right part
//ok
CallPart returns CallPart:
{CallPart}
'['(params+=Expression ( "," params+=Expression)*)?']';


//1)          "let" letDecl,+ blockOrBar
//2)        | quant decl,+    blockOrBar
//19)       | "{" decl,+ blockOrBar "}" 
//18)       | block
//          | terminalExpression
NonLeftRecursiveExpression returns NonLeftRecursiveExpression:
 TerminalExpression | 
 LetExpression | CurlyBracketsExpression | BlockExpr  | 
 QuantifiedExpression  ;

//1)          "let" letDecl,+ blockOrBar
//ok
LetExpression returns LetExpression:
'let' letDeclarations+=LetDeclaration ( ","     letDeclarations+=LetDeclaration)* blockOrBar=BlockOrBar;


//
//binOp ::= "||" | "or" | "&&" | "and" | "&" | "<=>" | "iff" | "=>" |     "implies" | "+" | "-" | "++" | "<:" | ":>" | "." | "<<" | ">>" | ">>>"
//compareOp ::= "=" | "in" | "<" | ">" | "=<" | ">="
//arrowOp ::= ["some"|"one"|"lone"|"set"] "->" ["some"|"one"|"lone"|"set"]
//ok
BinaryOperator returns BinaryOperator:
RelationalOperator | CompareOperator | ArrowOperator;

//ok
RelationalOperator returns RelationalOperator:
operator=RelationalOp;

//binOp ::= "||" | "or" | "&&" | "and" | "&" | "<=>" | "iff" | "=>" | "implies" | "+" | "-" | "++" | "<:" | ":>" | "." | "<<" | ">>" | ">>>"
//ok
enum RelationalOp returns RelationalOp:
            or = '||' | and = '&&' | union = '+' | intersection = '&' |     difference = '-' | equivalence = '<=>' | override = '++' 
            | domain = '<:' | range = ':>' | join = '.' ; // | lshift = '<<' | rshift = '>>' | rrshift = '>>>'; 

//["!"|"not"] compareOp
//ok
CompareOperator returns CompareOperator:
(negated?='!' | negated?='not')? operator=CompareOp;

//compareOp ::= "=" | "in" | "<" | ">" | "=<" | ">="
enum CompareOp returns CompareOp:
            equal = '=' | inclusion = 'in' | lesser = '<' | greater = '>' | lesserOrEq = '<=' | greaterOrEq = '>=';

//arrowOp ::= ["some"|"one"|"lone"|"set"] "->" ["some"|"one"|"lone"|"set"]
//ok
ArrowOperator returns ArrowOperator:
{ArrowOperator}
(leftQuantifier=ArrowQuantifier)? '->' (=>rightQuantifier=ArrowQuantifier)?;

//"some"|"one"|"lone"|"set"
//ok
enum ArrowQuantifier returns ArrowQuantifier: 
            lone = 'lone' | one = 'one' | some = 'some' | set = 'set' ; 

//19)       | "{" decl,+ blockOrBar "}" 
//ok
CurlyBracketsExpression returns CurlyBracketsExpression:
'{' varDeclarations+=VarDeclaration ( ","     varDeclarations+=VarDeclaration)* blockOrBar=BlockOrBar '}';

//blockOrBar ::= block
//blockOrBar ::= "|" expr
//ok
BlockOrBar returns BlockOrBar:
BlockExpr | Bar;    

//blockOrBar ::= "|" expr
//ok
Bar returns Bar:
'|' expression=Expression;

//block ::= "{" expr* "}"
//ok
BlockExpr returns BlockExpr:
{BlockExpr}
'{' (expressions+=Expression ( "," expressions+=Expression)*)?'}';

//3)         unOp expr
//         | finalExpression    
TerminalExpression returns TerminalExpression:
finalExpression  | 
UnaryExpr   ;   

//2)        | quant decl,+    blockOrBar
//ok
QuantifiedExpression returns QuantifiedExpression:
QuantifiedComplexExpression |
QuantifiedTerminalExpression;


QuantifiedComplexExpression returns QuantifiedComplexExpression :   
quantifier=QuantifiedComplexExpressionQuantifier =>varDeclaration+=VarDeclaration ( =>"," =>varDeclaration+=VarDeclaration)* =>blockOrBar=BlockOrBar;

QuantifiedTerminalExpression returns QuantifiedTerminalExpression:  
quantifier=QuantifiedTerminalExpressionQuantifier =>expr=TerminalExpression;


//3)         unOp expr
//ok
UnaryExpr returns UnaryExpr:
unOp=UnaryOperator  =>expression=finalExpression;


//unOp ::= "!" | "not" | "no" | "some" | "lone" | "one" | "set" | "seq" | "#" | "~" | "*" | "^"
//unOp ::= "!" | "not" |"#" | "~" | "*" | "^"
//ok
enum UnaryOperator returns UnaryOperator:
            not = 'not' | card = '#' | transpose = '~' | reflexiveClosure = '*' | closure = '^' | not2 = '!' ;//|



//16)       | "(" expr ")"
//9)        |     number
//10)       | "-" number
//17)       | ["@"] Name
//11)       | "none"
//12)       | "iden"
//13)       | "univ"
//14)       | "Int"
//15)       | "seq/Int"

//16)       | "(" expr ")"
//10)       | ["-"] number
//17)       | "@" Name
//17)       | reference
//12)13)    | constante
finalExpression returns TerminalExpression: 
BracketExpression | NumberExpression | NotExpandedExpression |     ConstantExpression | ReferenceExpression ;   

//16)       | "(" expr ")"
//ok    
BracketExpression returns BracketExpression:
'('expression=Expression')';

//9)        |     number
//10)       | "-" number
//ok    
Number returns Number:
NumberExpression;

//ok
NumberExpression returns NumberExpression:
value=EInt;

//17)       | ["@"] Name
//17)       | "@" Name
//ok
NotExpandedExpression returns NotExpandedExpression:
'@' name=[IDRef];

//ok
ReferenceExpression returns ReferenceExpression:
reference=Reference;

//ref ::= name | "univ" | "Int" | "seq/Int"
//ok
Reference returns Reference:
ConstanteReference | ReferenceName ;

//ok
ConstanteReference returns ConstanteReference:
cst=constanteRef;

//13)       | "univ"
//14)       | "Int"
//15)       | "seq/Int"
//ok
enum constanteRef returns constanteRef:
            int = 'Int' | seqint = 'seq/Int' | univ = 'univ';

//ok
ReferenceName returns ReferenceName:
name=Ref;

//ok
ConstantExpression returns ConstantExpression:
constante=Constant;

//11)       | "none"
//12)       | "iden"
//ok    
enum Constant returns Constant:
            none = 'none' | iden = 'iden';


//ok    
Block returns Block:
    BlockExpr;

//letDecl ::= name "=" expr
//ok
LetDeclaration returns LetDeclaration:
varName=VarDecl '=' expression=Expression;

//quant ::= "all" | "no" | "some" | "lone" | "one" | "sum"
//quant ::= "all" | "no" | "some" | "lone" | "one" | "null"
//ok
enum QuantifiedComplexExpressionQuantifier returns QuantifiedComplexExpressionQuantifier:
            all = 'all' | sum = 'sum' | no = 'no' | one = 'one' | lone = 'lone'  | some = 'some';

enum QuantifiedTerminalExpressionQuantifier returns QuantifiedTerminalExpressionQuantifier:
            seq = 'seq' | set = 'set' | no = 'no' | one = 'one' | lone = 'lone'  | some = 'some';

//enum QuantifiedAmbigusExpressionQuantifier returns     QuantifiedAmbigusExpressionQuantifier:
//              no = 'no' | one = 'one' | lone = 'lone'  | some = 'some';               

//decl ::= ["private"] ["disj"] name,+ ":" ["disj"] expr
//ok
VarDeclaration returns VarDeclaration:
(=>isPrivate?='private')? (=>varsAreDisjoint?='disj')? =>names+=VarDecl ( =>"," =>names+=VarDecl)* ":" (=>expressionIsDisjoint?='disj') expression=Expression; 


//scope ::= "for" number                   ["expect" (0|1)]
//scope ::= "for" number "but" typescope,+ ["expect" (0|1)]
//scope ::= "for"              typescope,+ ["expect" (0|1)]
//scope ::=                                ["expect" (0|1)]
//
//scope ::= "for" [number] ["but"] typescope,* 
//ok
Scope returns Scope:
{Scope}
    'for' (number=Number)? (but?='but')? (typeScope+=TypeScope ( ","     typeScope+=TypeScope)*)?;

//typescope ::= ["exactly"] number [name|"int"|"seq"]
//typescope ::= ExactlyNumber target
TypeScope returns TypeScope:
num=ExactlyNums target=[TypeScopeTarget];


//[name|"int"|"seq"]
//[Validname|"int"|"seq"]
//ok
TypeScopeTarget_Impl returns TypeScopeTarget:
{TypeScopeTarget}
;

Int0 returns Int:
{Int}
'Int'
;

Seq returns Seq:
{Seq}
'Seq'
;

提前谢谢。

1 个答案:

答案 0 :(得分:1)

你可以围绕这个

包装另一个句法谓词
=>(quantifier=QuantifiedComplexExpressionQuantifier varDeclaration+=VarDeclaration)

但是使用长时间的脚趾会使错误恢复和内容辅助更糟糕。您应该修改并尝试摆脱许多其他谓词'=&gt;'。另请注意,在许多情况下,替代的第一组谓词(' - &gt;')足够好并且更可取。

我在这个特殊情况下的建议是统一这两个规则,并有一个包含所有运算符的枚举。如果他/她错误地使用它们,请使用验证来向用户提供反馈。

E.g:

QuantifiedExpression returns QuantifiedExpression:
  quantifier=QuantifiedExpressionQuantifier (varDeclaration+=VarDeclaration ( "," varDeclaration+=VarDeclaration)* blockOrBar=BlockOrBar | expr=TerminalExpression);