diff --git a/language/src/main/grammars/de/monticore/lang/SysMLExpressions.mc4 b/language/src/main/grammars/de/monticore/lang/SysMLExpressions.mc4 index 0968db618..bb1860b7e 100644 --- a/language/src/main/grammars/de/monticore/lang/SysMLExpressions.mc4 +++ b/language/src/main/grammars/de/monticore/lang/SysMLExpressions.mc4 @@ -110,8 +110,9 @@ component grammar SysMLExpressions * name of the function to be invoked and an argument list for any remaining arguments (see 7.4.9.4). This is * useful for chaining invocations in an effective data flow */ - SysMLFunctionOperationExpression implements Expression = - Expression "->" Name ("(" (SysMLParameter || ",")* ")")? ("{" SysMLElement* inner:Expression "}")? ; + SysMLFunctionOperationExpression implements Expression <291> = + Expression "->" SysMLQualifiedName (Arguments)? + ("{" SysMLElement* inner:Expression "}")? ; // Eigentlich ist "^" der Name einer CalcDef aus den Domain Libraries CalcDefPowerExpression implements Expression = diff --git a/language/src/test/java/parser/ExpressionParserTest.java b/language/src/test/java/parser/ExpressionParserTest.java index 393d83340..fa14a254c 100644 --- a/language/src/test/java/parser/ExpressionParserTest.java +++ b/language/src/test/java/parser/ExpressionParserTest.java @@ -12,6 +12,8 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; +import de.monticore.lang.sysmlexpressions._ast.ASTSysMLFunctionOperationExpression; +import de.monticore.expressions.commonexpressions._ast.ASTFieldAccessExpression; import java.io.IOException; @@ -82,4 +84,64 @@ public void testElementOf() throws IOException { assertThat(ast.get()).isInstanceOf(ASTElementOfExpression.class); } + @Test + public void testSysMLFunctionOperatorExprMinimal() throws IOException { + var ast = parser.parse_StringExpression("x->b()"); + + assertThat(ast).isPresent(); + assertThat(Log.getFindings()).isEmpty(); + assertThat(ast.get()) + .isInstanceOf(ASTSysMLFunctionOperationExpression.class); + } + + @Test + public void testSysMLFunctionOperatorExpr() throws IOException { + var ast = parser.parse_StringExpression("x->excludes(y)"); + + assertThat(ast).isPresent(); + assertThat(Log.getFindings()).isEmpty(); + assertThat(ast.get()) + .isInstanceOf(ASTSysMLFunctionOperationExpression.class); + } + + @Test + public void testSysMLFunctionOperatorExpr2() throws IOException { + var ast = parser.parse_StringExpression("x->excludes(y.z)"); + + assertThat(ast).isPresent(); + assertThat(Log.getFindings()).isEmpty(); + assertThat(ast.get()) + .isInstanceOf(ASTSysMLFunctionOperationExpression.class); + } + + /** + * Checks that qualified names on both sides of a function operation + * are parsed with the correct binding. + */ + @ParameterizedTest + @ValueSource(strings = { + "a.b->c.d", + "a::b->c::d", + "a::b->c.d", + "a.b->c::d" + }) + public void testQualifiedNamesInFunctionOperation(String expr) + throws IOException { + + var ast = parser.parse_StringExpression(expr); + + assertThat(ast).isPresent(); + assertThat(Log.getFindings()).isEmpty(); + assertThat(ast.get()) + .isInstanceOf(ASTSysMLFunctionOperationExpression.class); + + var functionOperation = + (ASTSysMLFunctionOperationExpression) ast.get(); + + assertThat(functionOperation.getExpression()) + .isInstanceOf(ASTFieldAccessExpression.class); + assertThat(functionOperation.getSysMLQualifiedName().getPartsList()) + .containsExactly("c", "d"); + } + }