From 42c58bbeead1dae09c51f47abc8e10dfbb9c3f9f Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Tue, 23 Jun 2020 15:17:00 +0200 Subject: New configuration language parser WIP --- .../solver/language/GenerateSolverLanguage.mwe2 | 2 +- .../viatra/solver/language/SolverLanguage.xtext | 215 ++++++++++++--------- .../parser/antlr/SolverLanguageTokenSource.java | 47 +++-- 3 files changed, 156 insertions(+), 108 deletions(-) (limited to 'Application/org.eclipse.viatra.solver.language/src/org/eclipse/viatra/solver/language') diff --git a/Application/org.eclipse.viatra.solver.language/src/org/eclipse/viatra/solver/language/GenerateSolverLanguage.mwe2 b/Application/org.eclipse.viatra.solver.language/src/org/eclipse/viatra/solver/language/GenerateSolverLanguage.mwe2 index 50072f0d..644e681d 100644 --- a/Application/org.eclipse.viatra.solver.language/src/org/eclipse/viatra/solver/language/GenerateSolverLanguage.mwe2 +++ b/Application/org.eclipse.viatra.solver.language/src/org/eclipse/viatra/solver/language/GenerateSolverLanguage.mwe2 @@ -32,7 +32,7 @@ Workflow { language = StandardLanguage { name = "org.eclipse.viatra.solver.language.SolverLanguage" fileExtensions = "vsc" - referencedResource = "platform:/resource/org.eclipse.viatra.solver.language/model/SolverLanguage.genmodel" + referencedResource = "platform:/resource/org.eclipse.viatra.solver.language.model/model/model.genmodel" serializer = { generateStub = false diff --git a/Application/org.eclipse.viatra.solver.language/src/org/eclipse/viatra/solver/language/SolverLanguage.xtext b/Application/org.eclipse.viatra.solver.language/src/org/eclipse/viatra/solver/language/SolverLanguage.xtext index d0578d78..51115da0 100644 --- a/Application/org.eclipse.viatra.solver.language/src/org/eclipse/viatra/solver/language/SolverLanguage.xtext +++ b/Application/org.eclipse.viatra.solver.language/src/org/eclipse/viatra/solver/language/SolverLanguage.xtext @@ -3,66 +3,80 @@ import "http://www.eclipse.org/emf/2002/Ecore" as ecore import "http://www.eclipse.org/viatra/solver/language/SolverLanguage" Problem: - (statements+=Statement)*; + ("problem" name=QualifiedName FULL_STOP)? + imports+=Import* + statements+=Statement*; Statement: ( - AssertionOrDefinition | PredicateDefinition | UnnamedErrorPrediateDefinition | DefaultDefinition | MetricDefinition | - ExternPredicateDefinition | ExternMetricDefinition | ExternAggregatorDefinition | ExternDatatypeDefinition | - ClassDefinition | ScopeDefinition | ObjectiveDefinition - ) FULL_STOP; + AssertionOrDefinition | PredicateDefinition | UnnamedErrorPredicateDefintion | DefaultAssertion | + FunctionDefinition | Attribute | ExternDeclaration | ScopeDeclaration | ObjectiveDeclaration | + ClassDeclaration | EnumDeclaration + ); + +Import: + UriImport | NamespaceImport; + +UriImport: + "import" uri=STRING ("as" alias=QualifiedName) FULL_STOP; + +NamespaceImport: + "import" importedNamespace=QualifiedName ("as" alias=QualifiedName) FULL_STOP; AssertionOrDefinition returns Statement: Expression ( - {Interpretation.body=current} ":" range=Expression | + {Assertion.expression=current} (":" range=Expression)? | {PredicateDefinition.head=current} ":-" body=Expression | - {MetricDefinition.head=current} "=" body=Expression - )?; + {FunctionDefinition.head=current} ":=" body=Expression + ) FULL_STOP; PredicateDefinition: - (functional?="functional" error?="error"? | error?="error" functional?="functional"?) head=Call ":-" body=Expression; + (functional?="functional" error?="error"? | error?="error" functional?="functional"?) head=Call ":-" body=Expression FULL_STOP; -UnnamedErrorPrediateDefinition: - "error" argumentList=ArgumentList ":-" body=Expression; +UnnamedErrorPredicateDefintion: + "error" argumentList=ArgumentList ":-" body=Expression FULL_STOP; -DefaultDefinition: - "default" head=Call ":" range=Expression; +DefaultAssertion: + "default" expression=Call (":" range=Expression)? FULL_STOP; -MetricDefinition: - type=[NamedElement|QualifiedName] head=Call "=" body=Expression; +FunctionDefinition: + resultType=[Symbol|QualifiedName] head=Call ":=" body=Expression FULL_STOP; -ExternPredicateDefinition: - "extern" name=QualifiedName argumentList=ArgumentList; +TypeReference: + type=[Symbol|QualifiedName] forceObjectType?="object"?; -ExternMetricDefinition: - "extern" type=[NamedElement|QualifiedName] name=QualifiedName argumentList=ArgumentList; +enum AttributeKind: + FUNCTIONAL="functional" | ERROR="error" | ROOT="root" | CONTAINMENT="containment"; -ExternAggregatorDefinition: - "extern" type=[NamedElement|QualifiedName] name=QualifiedName "{" inputType=[NamedElement|QualifiedName] "..." "}"; +Attribute: + kind=AttributeKind target=[Symbol|QualifiedName] FULL_STOP; -ExternDatatypeDefinition: - "extern" "datatype" name=QualifiedName ("extends" supertypes+=[NamedElement|QualifiedName] ("," supertypes+=[NamedElement|QualifiedName])*); +ExternDeclaration: + ExternPredicateDeclaration | ExternFunctionDeclaration | ExternAggregationOperatorDeclaration | ExternDatatypeDeclaration; -Variable: - type=[NamedElement|QualifiedName]? name=ID; +ExternPredicateDeclaration: + "extern" (functional?="functional"? & error?="error"?) name=QualifiedName argumentList=ArgumentList FULL_STOP; + +ExternFunctionDeclaration: + "extern" resultType=[Symbol|QualifiedName] name=QualifiedName argumentList=ArgumentList FULL_STOP; + +ExternAggregationOperatorDeclaration: + "extern" resultType=[Symbol|QualifiedName] name=QualifiedName "{" argumentType=[Symbol|QualifiedName] "..." "}" FULL_STOP; + +ExternDatatypeDeclaration: + "extern" "datatype" name=QualifiedName FULL_STOP; Expression: - IfElse | Let | ImplicationExpression; + ConditionalExpression | LetExpression | DisjunctiveExpression ({Forall.condition=current} "=>" body=DisjunctiveExpression)?; -IfElse: - "if" condition=Expression "then" then=Expression "else" else=Expression; +ConditionalExpression: + "if" condition=DisjunctiveExpression "then" then=Expression "else" else=Expression; -Let: +LetExpression: "let" bindings+=LetBinding ("," bindings+=LetBinding)* "in" body=Expression; LetBinding: - variable=Variable "=" value=AdditiveExpression; - -enum ImplicationOperator returns BinaryOperator: - IMPLIES = "=>"; - -ImplicationExpression returns Expression: - DisjunctiveExpression ({BinaryExpression.left=current} op=ImplicationOperator right=ImplicationExpression)?; + type=[Symbol|QualifiedName]? name=ID "=" value=AdditiveExpression; DisjunctiveExpression returns Expression: ConjunctiveExpression ( @@ -77,19 +91,19 @@ ConjunctiveExpression returns Expression: ComparisonExpression ({Conjunction.children+=current} ("," children+=ComparisonExpression)+)?; enum ComparisonOperator returns BinaryOperator: - EQ="==" | NOT_EQ="!=" | LESS="<" | LESS_EQ="<=" | GREATER=">" | GREATER_EQ=">=" | IN="in"; + EQUALS="==" | NOT_EQUALS="!=" | LESS="<" | LESS_EQUALS="<=" | GREATER=">" | GREATER_EQUALS=">=" | IN="in"; ComparisonExpression returns Expression: - AdditiveExpression ({Comparison.left=current} op=ComparisonOperator right=AdditiveExpression)?; + AdditiveExpression ({BinaryExpression.left=current} op=ComparisonOperator right=AdditiveExpression)?; enum AdditiveBinaryOperator returns BinaryOperator: - ADD="+" | SUB="-"; + PLUS="+" | MINUS="-"; AdditiveExpression returns Expression: MultiplicativeExpression ({BinaryExpression.left=current} op=AdditiveBinaryOperator right=MultiplicativeExpression)*; enum MultiplicativeBinaryOperator returns BinaryOperator: - MUL="*" | DIV="/"; + MULTIPLY="*" | DIVIDE="/"; MultiplicativeExpression returns Expression: ExponentialExpression ({BinaryExpression.left=current} op=MultiplicativeBinaryOperator right=ExponentialExpression)*; @@ -101,61 +115,59 @@ ExponentialExpression returns Expression: CastExpression ({BinaryExpression.left=current} op=ExponentialOp right=CastExpression)?; CastExpression returns Expression: - UnaryExpression ({CastExpression.body=current} "as" type=[NamedElement|QualifiedName])?; + UnaryExpression ({CastExpression.body=current} "as" targetType=[Symbol|QualifiedName])?; -enum UnaryOp: - NEG="!" | PLUS="+" | MINUS="-" | MAY="may" | MUST="must" | CURRENT="current"; +enum UnaryOperator: + NOT="!" | PLUS="+" | MINUS="-" | MAYBE="?"; UnaryExpression returns Expression: - AggregationExpression | {UnaryExpression} op=UnaryOp body=AggregationExpression; - -AggregationExpression returns Expression: - AtomicExpression | QuantifiedExpression | Aggregation; + BracedAggregateExpression | {UnaryExpression} op=UnaryOperator body=BracedAggregateExpression; -LocalVariables: - {LocalVariables} "[" (variables+=Variable ("," variables+=Variable)*)? "]"; - -enum Quantifier: - EXISTS="exists" | FORALL="forall" | COUNT="count"; - -QuantifiedExpression: - quantifier=Quantifier localVariables=LocalVariables? "{" body=Expression "}"; +BracedAggregateExpression returns Expression: + AtomicExpression | Aggregation | Count ; Aggregation: - op=[NamedElement|QualifiedName] localVariables=LocalVariables? "{" body=Expression ("|" condition=Expression)? "}"; + op=[Symbol|QualifiedName] "{" value=Expression "|" condition=Expression "}"; + +Count: + "count" "{" condition=Expression "}"; AtomicExpression returns Expression: Reference | Call | Interval | Literal | "(" Expression ")"; Call: - functor=Reference (transitiveClosure?=TRANSITIVE_CLOSURE | reflexiveTransitiveClosure?=REFLEXIVE_TRANSITIVE_CLOSURE)? argumentList=ArgumentList; + functor=Reference argumentList=ArgumentList; ArgumentList: {ArgumentList} "(" (arguments+=Argument ("," arguments+=Argument)*)? ")"; Argument: - ExpressionArgument | StarArgument | TypedArgument | TypedStarArgument; + ExpressionArgument | StarArgument | TypedVariableArgument | TypedStarArgument; ExpressionArgument: - body=ComparisonExpression; + expression=ComparisonExpression; StarArgument: {StarArgument} "*"; -TypedArgument: - type=[NamedElement|QualifiedName] variable=[NamedElement|QualifiedName]; +TypedVariableArgument: + typeReference=TypeReference name=ID; TypedStarArgument: - type=[NamedElement|QualifiedName] "*"; + typeReference=TypeReference "*"; Reference: - referred=[NamedElement|QualifiedName]; + components+=PathComponent ("." components+=PathComponent)*; + +PathComponent: + inverse?="~"? symbol=[Symbol|QualifiedName] + (transitiveClosure?=TRANSITIVE_CLOSURE | reflexiveTransitiveClosure?=REFLEXIVE_TRANSITIVE_CLOSURE)?; Interval: - "[" lowerBound=Expression ".." upperBound=Expression "]"; + "[" lowerBound=AdditiveExpression "," upperBound=AdditiveExpression "]"; Literal: - LogicLiteral | NumericLiteral | InfinityLiteral | EmptyIntervalLiteral | StringLiteral; + LogicLiteral | IntLiteral | RealLiteral | InfinityLiteral | EmptyLiteral | StringLiteral; enum LogicValue: TRUE="true" | FALSE="false" | UNKNOWN="unknown" | ERROR="error"; @@ -163,69 +175,82 @@ enum LogicValue: LogicLiteral: value=LogicValue; -NumericLiteral: +IntLiteral: + value=INT; + +RealLiteral: value=Real; InfinityLiteral: {InfinityLiteral} "inf"; -EmptyIntervalLiteral: - {EmptyIntervalLiteral} "empty"; +EmptyLiteral: + {EmptyLiteral} "empty"; StringLiteral: value=STRING; -ClassDefinition: - abstract?="abstract"? "class" name=ID ("extends" superclasses+=[NamedElement|QualifiedName] ("," superclasses+=[NamedElement|QualifiedName])*)? - "{" members+=MemberDefinition* "}"; +ClassDeclaration: + (abstract?="abstract"? & root?="root"?) "class" name=ID ("extends" supertypes+=[Symbol|QualifiedName] ("," supertypes+=[Symbol|QualifiedName])*)? + ("{" fields+=Field* "}" | FULL_STOP); -MemberDefinition: - containment?="contains"? type=[NamedElement|QualifiedName] multiplicity=Multiplicity? name=ID ("opposite" opposite=[NamedElement|QualifiedName])? ";"?; +Field: + (containment?="contains" | crossReference?="refers")? type=[Symbol|QualifiedName] multiplicity=Multiplicity? + name=ID ("opposite" opposite=[Symbol|QualifiedName])? ";"?; Multiplicity: - ManyMultiplicity | ExactMultiplicity | BoundedMultiplicity; + UnboundedMultiplicity | ExactMultiplicity | BoundedMultiplicity; -ManyMultiplicity: - {ManyMultiplicity} "[" "]"; +UnboundedMultiplicity: + {UnboundedMultiplicity} "[" "]"; ExactMultiplicity: - "[" multiplicity=UpperMultiplicty "]"; + "[" value=UpperMultiplicty "]"; BoundedMultiplicity: - "[" lowerBound=INT ".." upperBound=UpperMultiplicty "]"; + "[" lowerBound=INT "," upperBound=UpperMultiplicty "]"; + +EnumDeclaration: + "enum" name=ID ("{" (literals+=EnumLiteral (","? literals+=EnumLiteral)*)? "}" | FULL_STOP); -ScopeDefinition: - ExactScopeDefinition | BoundedScopeDefinition | LowerBoundedScopeDefinition; +EnumLiteral: + name=ID; -ExactScopeDefinition: - "scope" type=[NamedElement|QualifiedName] "==" exactScope=INT; +ScopeDeclaration: + ExactScope | BoundedScope | LowerBoundedScope; -BoundedScopeDefinition: +ExactScope: + "scope" type=[Symbol|QualifiedName] "==" size=INT FULL_STOP; + +BoundedScope: "scope" ( - (lowerBound=INT "<=")? type=[NamedElement|QualifiedName] "<=" upperBound=INT | - upperBound=INT ">=" type=[NamedElement|QualifiedName] (">=" lowerBound=INT)? - ); + (lowerBound=INT "<=")? type=[Symbol|QualifiedName] "<=" upperBound=INT | + upperBound=INT ">=" type=[Symbol|QualifiedName] (">=" lowerBound=INT)? + ) FULL_STOP; -LowerBoundedScopeDefinition: +LowerBoundedScope: "scope" ( - lowerBound=INT "<=" type=[NamedElement|QualifiedName] | - type=[NamedElement|QualifiedName] ">=" lowerBound=INT - ); + lowerBound=INT "<=" type=[Symbol|QualifiedName] | + type=[Symbol|QualifiedName] ">=" lowerBound=INT + ) FULL_STOP; enum ObjectiveKind: - MINIMIZE="minimize" | MAXIMIZE="maximize"; + MINIMIZATION="minimize" | MAXIMIZATION="maximize"; -ObjectiveDefinition: - kind=ObjectiveKind objective=Expression; +ObjectiveDeclaration: + kind=ObjectiveKind objective=Expression FULL_STOP; UpperMultiplicty returns ecore::EInt: INT | "*"; Real returns ecore::EBigDecimal hidden(): - INT ("." INT)?; + INT "." INT; + +QualifiedNameSegment: + ID | QUOTED_ID | "object"; QualifiedName hidden(): - ID ("." ID)* | QUOTED_ID; + QualifiedNameSegment ("::" QualifiedNameSegment)*; @Override terminal STRING returns ecore::EString: diff --git a/Application/org.eclipse.viatra.solver.language/src/org/eclipse/viatra/solver/language/parser/antlr/SolverLanguageTokenSource.java b/Application/org.eclipse.viatra.solver.language/src/org/eclipse/viatra/solver/language/parser/antlr/SolverLanguageTokenSource.java index 4c1dacd5..70e7e492 100644 --- a/Application/org.eclipse.viatra.solver.language/src/org/eclipse/viatra/solver/language/parser/antlr/SolverLanguageTokenSource.java +++ b/Application/org.eclipse.viatra.solver.language/src/org/eclipse/viatra/solver/language/parser/antlr/SolverLanguageTokenSource.java @@ -29,6 +29,7 @@ public class SolverLanguageTokenSource implements TokenSource { private int plusTokenId = -1; private int starTokenId = -1; private int dotTokenId = -1; + private int tildeTokenId = -1; private int openParenTokenId = -1; public SolverLanguageTokenSource(TokenSource delegate) { @@ -42,33 +43,49 @@ public class SolverLanguageTokenSource implements TokenSource { @Override public Token nextToken() { - Token token = internalNextToken(); + Token token; + if (acceptor.hasNext()) { + token = acceptor.next(); + } else { + token = delegate.nextToken(); + } + postProcessToken(token); lastTokenId = token.getType(); return token; } - protected Token internalNextToken() { - if (acceptor.hasNext()) { - return acceptor.next(); - } - Token token = delegate.nextToken(); + protected void postProcessToken(Token token) { int type = token.getType(); if (type == plusTokenId) { - if ((lastTokenId == RULE_ID || lastTokenId == RULE_QUOTED_ID) - && peekUntilVisible().getType() == openParenTokenId) { + if (isTransitiveClosureInReferenceContext()) { token.setType(RULE_TRANSITIVE_CLOSURE); } } else if (type == starTokenId) { - if ((lastTokenId == RULE_ID || lastTokenId == RULE_QUOTED_ID) - && peekUntilVisible().getType() == openParenTokenId) { + if (isTransitiveClosureInReferenceContext()) { token.setType(RULE_REFLEXIVE_TRANSITIVE_CLOSURE); } } else if (type == dotTokenId) { - if ((lastTokenId != RULE_ID && lastTokenId != RULE_INT) || peekToken().getType() != lastTokenId) { + if (isFullStopContext()) { token.setType(RULE_FULL_STOP); } } - return token; + } + + private boolean isIdFragment(int tokenId) { + return tokenId == RULE_ID || tokenId == RULE_QUOTED_ID; + } + + private boolean isTransitiveClosureInReferenceContext() { + int nextVisibleTokenId = peekUntilVisible().getType(); + return isIdFragment(lastTokenId) + && (nextVisibleTokenId == dotTokenId || nextVisibleTokenId == openParenTokenId); + } + + private boolean isFullStopContext() { + int nextTokenId = peekToken().getType(); + boolean inReference = isIdFragment(lastTokenId) && (isIdFragment(nextTokenId) || nextTokenId == tildeTokenId); + boolean inReal = lastTokenId == RULE_INT && nextTokenId == RULE_INT; + return !(inReference || inReal); } protected Token peekUntilVisible() { @@ -101,6 +118,9 @@ public class SolverLanguageTokenSource implements TokenSource { case "'.'": dotTokenId = entry.getKey(); break; + case "'~'": + tildeTokenId = entry.getKey(); + break; case "'('": openParenTokenId = entry.getKey(); break; @@ -115,6 +135,9 @@ public class SolverLanguageTokenSource implements TokenSource { if (dotTokenId == -1) { throw new IllegalStateException("Token '.' was not found"); } + if (tildeTokenId == -1) { + throw new IllegalStateException("Token '~' was not found"); + } if (openParenTokenId == -1) { throw new IllegalStateException("Token '(' was not found"); } -- cgit v1.2.3-54-g00ecf