diff --git a/monticore-grammar/src/main/grammars/de/monticore/expressions/StreamExpressions.mc4 b/monticore-grammar/src/main/grammars/de/monticore/expressions/StreamExpressions.mc4 index e51ed9b895..27e84abb99 100644 --- a/monticore-grammar/src/main/grammars/de/monticore/expressions/StreamExpressions.mc4 +++ b/monticore-grammar/src/main/grammars/de/monticore/expressions/StreamExpressions.mc4 @@ -49,14 +49,28 @@ component grammar StreamExpressions extends CommonExpressions { * Stream constructor has to bind harder than name expressions to avoid * the scanner recognizing timing keywords as names */ - StreamConstructorExpression implements Expression <360> = + interface StreamConstructorExpression extends Expression <360>; + + SimpleStreamConstructorExpression implements StreamConstructorExpression <360> = + ({noSpace(2)}? + timing:[key("Sync") | key("Untimed")])? + "<" (Expression || ",")* ">"; + + ToptStreamConstructorExpression implements StreamConstructorExpression <360> = ({noSpace(2)}? - timing:[key("Event") | key("Sync") | key("Topt") | key("Untimed")])? + timing:[key("Topt")])? + "<" + ((Expression | AbsentInStreamConstructor) ("," (Expression | AbsentInStreamConstructor))*) + ">"; + + EventStreamConstructorExpression implements StreamConstructorExpression <360> = + ({noSpace(2)}? + timing:[key("Event")])? "<" - (TickInStreamConstructor* (Expression ( + TickInStreamConstructor* (Expression ( ("," | TickInStreamConstructor+) Expression | TickInStreamConstructor)* )? - ) ">"; + ">"; TickInStreamConstructor = ";"; AbsentInStreamConstructor = "~"; diff --git a/monticore-grammar/src/main/java/de/monticore/expressions/streamexpressions/_ast/ASTEventStreamConstructorExpression.java b/monticore-grammar/src/main/java/de/monticore/expressions/streamexpressions/_ast/ASTEventStreamConstructorExpression.java new file mode 100644 index 0000000000..93f61e72d4 --- /dev/null +++ b/monticore-grammar/src/main/java/de/monticore/expressions/streamexpressions/_ast/ASTEventStreamConstructorExpression.java @@ -0,0 +1,48 @@ +package de.monticore.expressions.streamexpressions._ast; + +import de.monticore.ast.ASTNode; +import de.monticore.expressions.expressionsbasis._ast.ASTExpression; +import de.monticore.expressions.streamexpressions.StreamExpressionsMill; +import de.monticore.expressions.streamexpressions._ast.util.ASTNodeSiblingComparator; +import de.monticore.expressions.streamexpressions._util.IStreamExpressionsTypeDispatcher; + +import java.util.ArrayList; +import java.util.List; + +public class ASTEventStreamConstructorExpression extends ASTEventStreamConstructorExpressionTOP { + + @Override + public boolean isEventTimed() { + return true; + } + + /** + * each inner List represents a time slice, + * each time slice may hold any number of ASTExpressions. + */ + public List> getExpressionsPerTimeSlice() { + List> result = + new ArrayList<>(sizeTickInStreamConstructors() + 1); + List nodes = new ArrayList<>(); + nodes.addAll(getExpressionList()); + nodes.addAll(getTickInStreamConstructorList()); + nodes.sort(new ASTNodeSiblingComparator()); + IStreamExpressionsTypeDispatcher dispatcher = + StreamExpressionsMill.typeDispatcher(); + List currentTimeSlice = new ArrayList(); + for (int i = 0; i < nodes.size(); i++) { + ASTNode node = nodes.get(i); + if (dispatcher.isExpressionsBasisASTExpression(node)) { + currentTimeSlice.add(dispatcher.asExpressionsBasisASTExpression(node)); + } + // Tick + else { + result.add(currentTimeSlice); + currentTimeSlice = new ArrayList(); + } + } + result.add(currentTimeSlice); + return result; + } + +} diff --git a/monticore-grammar/src/main/java/de/monticore/expressions/streamexpressions/_ast/ASTSimpleStreamConstructorExpression.java b/monticore-grammar/src/main/java/de/monticore/expressions/streamexpressions/_ast/ASTSimpleStreamConstructorExpression.java new file mode 100644 index 0000000000..d9350c48e4 --- /dev/null +++ b/monticore-grammar/src/main/java/de/monticore/expressions/streamexpressions/_ast/ASTSimpleStreamConstructorExpression.java @@ -0,0 +1,7 @@ +package de.monticore.expressions.streamexpressions._ast; + +public class ASTSimpleStreamConstructorExpression extends ASTSimpleStreamConstructorExpressionTOP { + + + +} diff --git a/monticore-grammar/src/main/java/de/monticore/expressions/streamexpressions/_ast/ASTStreamConstructorExpression.java b/monticore-grammar/src/main/java/de/monticore/expressions/streamexpressions/_ast/ASTStreamConstructorExpression.java index 871c7fa012..31c5cba4a2 100644 --- a/monticore-grammar/src/main/java/de/monticore/expressions/streamexpressions/_ast/ASTStreamConstructorExpression.java +++ b/monticore-grammar/src/main/java/de/monticore/expressions/streamexpressions/_ast/ASTStreamConstructorExpression.java @@ -1,28 +1,34 @@ package de.monticore.expressions.streamexpressions._ast; -public class ASTStreamConstructorExpression extends ASTStreamConstructorExpressionTOP { +import de.monticore.expressions.expressionsbasis._ast.ASTExpression; + +import java.util.List; + +public interface ASTStreamConstructorExpression extends ASTStreamConstructorExpressionTOP { /** * If default and not specified otherwise, Event should be chosen. */ - public boolean isDefaultTimed() { - return getTiming() == ASTConstantsStreamExpressions.DEFAULT; + default boolean isDefaultTimed() { + return false; } - public boolean isEventTimed() { - return getTiming() == ASTConstantsStreamExpressions.EVENT; + default boolean isEventTimed() { + return false; } - public boolean isSyncTimed() { - return getTiming() == ASTConstantsStreamExpressions.SYNC; + default boolean isSyncTimed() { + return false; } - public boolean isToptTimed() { - return getTiming() == ASTConstantsStreamExpressions.TOPT; + default boolean isToptTimed() { + return false; } - public boolean isUntimed() { - return getTiming() == ASTConstantsStreamExpressions.UNTIMED; + default boolean isUntimed() { + return false; } + List getExpressionList(); + } diff --git a/monticore-grammar/src/main/java/de/monticore/expressions/streamexpressions/_ast/ASTToptStreamConstructorExpression.java b/monticore-grammar/src/main/java/de/monticore/expressions/streamexpressions/_ast/ASTToptStreamConstructorExpression.java new file mode 100644 index 0000000000..9599de1255 --- /dev/null +++ b/monticore-grammar/src/main/java/de/monticore/expressions/streamexpressions/_ast/ASTToptStreamConstructorExpression.java @@ -0,0 +1,11 @@ +package de.monticore.expressions.streamexpressions._ast; + +public class ASTToptStreamConstructorExpression extends ASTToptStreamConstructorExpressionTOP { + + @Override + public boolean isToptTimed() { + return true; + } + + +} diff --git a/monticore-grammar/src/main/java/de/monticore/expressions/streamexpressions/_ast/util/ASTNodeSiblingComparator.java b/monticore-grammar/src/main/java/de/monticore/expressions/streamexpressions/_ast/util/ASTNodeSiblingComparator.java new file mode 100644 index 0000000000..5939bf5d06 --- /dev/null +++ b/monticore-grammar/src/main/java/de/monticore/expressions/streamexpressions/_ast/util/ASTNodeSiblingComparator.java @@ -0,0 +1,38 @@ +package de.monticore.expressions.streamexpressions._ast.util; + +import de.monticore.ast.ASTNode; +import de.se_rwth.commons.SourcePosition; +import de.se_rwth.commons.logging.Log; + +import java.util.Comparator; + +/** + * Sorting based on source Position, + * intended to sort siblings/cousins/etc. and nothing else. + * If useful, this could be moved elsewhere. + */ +public class ASTNodeSiblingComparator implements Comparator { + + @Override + public int compare(ASTNode o1, ASTNode o2) { + int start = compare(o1.get_SourcePositionStart(), o2.get_SourcePositionStart()); + int end = compare(o1.get_SourcePositionEnd(), o2.get_SourcePositionEnd()); + // check if we are indeed sorting siblings or similar + if (!((start < 0 && end < 0) + || (start == 0 && end == 0) + || (start > 0 || end > 0) + )) { + Log.error("0xFD54C internal error: unexpected ASTNodes compared"); + } + return start; + } + + protected int compare(SourcePosition o1, SourcePosition o2) { + // check if we are indeed sorting siblings or similar + if (o1.getFileName() != o2.getFileName()) { + Log.error("0xFD54D internal error: unexpected ASTNodes compared"); + } + return o1.compareTo(o2); + } + +} diff --git a/monticore-grammar/src/main/java/de/monticore/expressions/streamexpressions/_prettyprint/StreamExpressionsPrettyPrinter.java b/monticore-grammar/src/main/java/de/monticore/expressions/streamexpressions/_prettyprint/StreamExpressionsPrettyPrinter.java new file mode 100644 index 0000000000..c445192608 --- /dev/null +++ b/monticore-grammar/src/main/java/de/monticore/expressions/streamexpressions/_prettyprint/StreamExpressionsPrettyPrinter.java @@ -0,0 +1,47 @@ +/* (c) https://github.com/MontiCore/monticore */ + +package de.monticore.expressions.streamexpressions._prettyprint; + +import de.monticore.expressions.expressionsbasis._ast.ASTExpression; +import de.monticore.expressions.streamexpressions._ast.ASTEventStreamConstructorExpression; +import de.monticore.prettyprint.CommentPrettyPrinter; +import de.monticore.prettyprint.IndentPrinter; + +import java.util.List; + +public class StreamExpressionsPrettyPrinter extends StreamExpressionsPrettyPrinterTOP { + + public StreamExpressionsPrettyPrinter(IndentPrinter printer, boolean printComments) { + super(printer, printComments); + } + + public void handle(ASTEventStreamConstructorExpression node) { + if (this.isPrintComments()) { + CommentPrettyPrinter.printPreComments(node, getPrinter()); + } + if (node.isTiming()) { + getPrinter().print("Event"); + } + getPrinter().print("<"); + List> expressionsPerTimeSlice = + node.getExpressionsPerTimeSlice(); + for (int i = 0; i < expressionsPerTimeSlice.size(); i++) { + if (i != 0) { + getPrinter().print(";"); + } + for (int j = 0; j < expressionsPerTimeSlice.get(i).size(); j++) { + if (j != 0) { + getPrinter().print(","); + } + expressionsPerTimeSlice.get(i).get(j).accept(getTraverser()); + } + } + getPrinter().print(">"); + if (this.isPrintComments()) { + CommentPrettyPrinter.printPostComments(node, getPrinter()); + } + } + +} + + diff --git a/monticore-grammar/src/main/java/de/monticore/expressions/streamexpressions/types3/StreamExpressionsCTTIVisitor.java b/monticore-grammar/src/main/java/de/monticore/expressions/streamexpressions/types3/StreamExpressionsCTTIVisitor.java index af3e0a992f..847020f39d 100644 --- a/monticore-grammar/src/main/java/de/monticore/expressions/streamexpressions/types3/StreamExpressionsCTTIVisitor.java +++ b/monticore-grammar/src/main/java/de/monticore/expressions/streamexpressions/types3/StreamExpressionsCTTIVisitor.java @@ -74,7 +74,8 @@ public void handle(ASTStreamConstructorExpression expr) { !getType4Ast().getPartialTypeOfExpr(expr).isObscureType() ) { visit(expr); - traverse(expr); + // todo FDr + //traverse(expr); endVisit(expr); } } diff --git a/monticore-grammar/src/test/java/de/monticore/expressions/prettyprint/StreamExpressionsPrettyPrinterTest.java b/monticore-grammar/src/test/java/de/monticore/expressions/prettyprint/StreamExpressionsPrettyPrinterTest.java index ed71ed1c11..e4826cce8a 100644 --- a/monticore-grammar/src/test/java/de/monticore/expressions/prettyprint/StreamExpressionsPrettyPrinterTest.java +++ b/monticore-grammar/src/test/java/de/monticore/expressions/prettyprint/StreamExpressionsPrettyPrinterTest.java @@ -2,15 +2,12 @@ package de.monticore.expressions.prettyprint; import de.monticore.expressions.expressionsbasis._ast.ASTExpression; -import de.monticore.expressions.streamexpressions._prettyprint.StreamExpressionsFullPrettyPrinter; import de.monticore.expressions.teststreamexpressions.TestStreamExpressionsMill; import de.monticore.expressions.teststreamexpressions._parser.TestStreamExpressionsParser; -import de.monticore.prettyprint.IndentPrinter; import de.se_rwth.commons.logging.Log; import de.se_rwth.commons.logging.LogStub; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -20,7 +17,6 @@ public class StreamExpressionsPrettyPrinterTest { protected TestStreamExpressionsParser parser; - protected StreamExpressionsFullPrettyPrinter prettyPrinter; @BeforeEach public void init() { @@ -29,9 +25,6 @@ public void init() { TestStreamExpressionsMill.reset(); TestStreamExpressionsMill.init(); parser = TestStreamExpressionsMill.parser(); - prettyPrinter = - new StreamExpressionsFullPrettyPrinter(new IndentPrinter()); - prettyPrinter.getPrinter().clearBuffer(); } @ParameterizedTest @@ -39,6 +32,10 @@ public void init() { "<>", "", "", + "<;;1>", + "<1;;>", + "<;1;>", + "<;1,2;3>", "Event", "A:", "stream1 : stream2", @@ -51,7 +48,7 @@ public void testPrettyPrint(String input) throws IOException { Assertions.assertTrue(result.isPresent()); ASTExpression ast = result.get(); - String output = prettyPrinter.prettyprint(ast); + String output = TestStreamExpressionsMill.prettyPrint(ast, true); result = parser.parse_StringExpression(output); Assertions.assertFalse(parser.hasErrors()); diff --git a/monticore-grammar/src/test/java/de/monticore/expressions/streamexpressions/parser/CombinedStreamsExpressionsParserTest.java b/monticore-grammar/src/test/java/de/monticore/expressions/streamexpressions/parser/CombinedStreamsExpressionsParserTest.java index 9ceabfd970..b7a0b00de5 100644 --- a/monticore-grammar/src/test/java/de/monticore/expressions/streamexpressions/parser/CombinedStreamsExpressionsParserTest.java +++ b/monticore-grammar/src/test/java/de/monticore/expressions/streamexpressions/parser/CombinedStreamsExpressionsParserTest.java @@ -138,6 +138,27 @@ public void testFalseBitshiftInteraction2() throws IOException { assertInstanceOf(ASTStreamConstructorExpression.class, greater.getLeft()); } + @ParameterizedTest + @MethodSource + public void testConstructorWithAbsent(String model) throws IOException { + Optional expr = p.parse_StringExpression(model); + assertFalse(p.hasErrors()); + assertTrue(expr.isPresent()); + assertInstanceOf(ASTStreamConstructorExpression.class, expr.get()); + } + + protected static Stream testConstructorWithAbsent() { + return Stream.of( + Arguments.of("<>"), + Arguments.of("<~>"), + Arguments.of("<~,~>"), + Arguments.of("<1,~>"), + Arguments.of("<~,1>"), + Arguments.of("<1,1>"), + Arguments.of("<~, ~, ~, ~>") + ); + } + @ParameterizedTest @MethodSource public void testConstructorWithTick(String model) throws IOException { @@ -182,7 +203,11 @@ protected static Stream testInvalidConstructor() { Arguments.of("<1,,1>"), Arguments.of("<;,1>"), Arguments.of("<1,;>"), - Arguments.of("<;,;>") + Arguments.of("<;,;>"), + Arguments.of("<;,~>"), + Arguments.of("<~,;>"), + Arguments.of("<;~>"), + Arguments.of("<~;>") ); }