From 4f136495a87fa7cd3ea11d805a48af681fd1ee3b Mon Sep 17 00:00:00 2001 From: Markus Amshove Date: Sat, 29 Apr 2023 19:10:52 +0200 Subject: [PATCH 1/4] Parse REDUCE --- docs/implemented-statements.md | 6 +- .../natparse/natural/IReduceArrayNode.java | 6 ++ .../natparse/natural/IReduceDynamicNode.java | 8 ++ .../natparse/parsing/ParserErrors.java | 9 +++ .../natparse/parsing/ReduceArrayNode.java | 20 +++++ .../natparse/parsing/ReduceDynamicNode.java | 32 ++++++++ .../natparse/parsing/StatementListParser.java | 74 +++++++++++++++++++ .../parsing/StatementListParserShould.java | 35 +++++++++ 8 files changed, 187 insertions(+), 3 deletions(-) create mode 100644 libs/natparse/src/main/java/org/amshove/natparse/natural/IReduceArrayNode.java create mode 100644 libs/natparse/src/main/java/org/amshove/natparse/natural/IReduceDynamicNode.java create mode 100644 libs/natparse/src/main/java/org/amshove/natparse/parsing/ReduceArrayNode.java create mode 100644 libs/natparse/src/main/java/org/amshove/natparse/parsing/ReduceDynamicNode.java diff --git a/docs/implemented-statements.md b/docs/implemented-statements.md index 5a7b4b505..c426870fc 100644 --- a/docs/implemented-statements.md +++ b/docs/implemented-statements.md @@ -4,9 +4,9 @@ This document tracks the implementation status of Natural statements. Legend: -:x: - not implemented (67) +:x: - not implemented (66) -:white_check_mark: - implemented or reporting (49) +:white_check_mark: - implemented or reporting (50) partial - partially implemented to prevent false positives (6) @@ -94,7 +94,7 @@ partial - partially implemented to prevent false positives (6) | READ RESULT SET (SQL) | :x: | | READ WORK FILE | :x: | | READLOB | :x: | -| REDUCE | :x: | +| REDUCE | :white_check_mark: | | REINPUT | :x: | | REJECT | :x: | | RELEASE | :x: | diff --git a/libs/natparse/src/main/java/org/amshove/natparse/natural/IReduceArrayNode.java b/libs/natparse/src/main/java/org/amshove/natparse/natural/IReduceArrayNode.java new file mode 100644 index 000000000..c19181d30 --- /dev/null +++ b/libs/natparse/src/main/java/org/amshove/natparse/natural/IReduceArrayNode.java @@ -0,0 +1,6 @@ +package org.amshove.natparse.natural; + +public interface IReduceArrayNode extends IStatementNode +{ + IVariableReferenceNode arrayToReduce(); +} diff --git a/libs/natparse/src/main/java/org/amshove/natparse/natural/IReduceDynamicNode.java b/libs/natparse/src/main/java/org/amshove/natparse/natural/IReduceDynamicNode.java new file mode 100644 index 000000000..bf4f9ad6f --- /dev/null +++ b/libs/natparse/src/main/java/org/amshove/natparse/natural/IReduceDynamicNode.java @@ -0,0 +1,8 @@ +package org.amshove.natparse.natural; + +public interface IReduceDynamicNode extends IStatementNode +{ + IVariableReferenceNode variableToReduce(); + + int sizeToReduceTo(); +} diff --git a/libs/natparse/src/main/java/org/amshove/natparse/parsing/ParserErrors.java b/libs/natparse/src/main/java/org/amshove/natparse/parsing/ParserErrors.java index 304920cfa..d65155c1f 100644 --- a/libs/natparse/src/main/java/org/amshove/natparse/parsing/ParserErrors.java +++ b/libs/natparse/src/main/java/org/amshove/natparse/parsing/ParserErrors.java @@ -421,6 +421,15 @@ public static IDiagnostic invalidLiteralType(ILiteralNode literal, SyntaxKind al ); } + public static IDiagnostic invalidNumericValue(ILiteralNode node, int actualValue, int allowedValue) + { + return ParserDiagnostic.create( + "Value %d is not allowed here, only %d can be used".formatted(actualValue, allowedValue), + node, + ParserError.INVALID_LITERAL_VALUE + ); + } + public static IDiagnostic invalidNumericRange(ILiteralNode node, int actualValue, int lowestValue, int highestValue) { return ParserDiagnostic.create( diff --git a/libs/natparse/src/main/java/org/amshove/natparse/parsing/ReduceArrayNode.java b/libs/natparse/src/main/java/org/amshove/natparse/parsing/ReduceArrayNode.java new file mode 100644 index 000000000..b6600c0a8 --- /dev/null +++ b/libs/natparse/src/main/java/org/amshove/natparse/parsing/ReduceArrayNode.java @@ -0,0 +1,20 @@ +package org.amshove.natparse.parsing; + +import org.amshove.natparse.natural.IReduceArrayNode; +import org.amshove.natparse.natural.IVariableReferenceNode; + +class ReduceArrayNode extends StatementNode implements IReduceArrayNode +{ + private IVariableReferenceNode arrayToReduce; + + @Override + public IVariableReferenceNode arrayToReduce() + { + return arrayToReduce; + } + + void setArrayToReduce(IVariableReferenceNode array) + { + arrayToReduce = array; + } +} diff --git a/libs/natparse/src/main/java/org/amshove/natparse/parsing/ReduceDynamicNode.java b/libs/natparse/src/main/java/org/amshove/natparse/parsing/ReduceDynamicNode.java new file mode 100644 index 000000000..0e2f6c39c --- /dev/null +++ b/libs/natparse/src/main/java/org/amshove/natparse/parsing/ReduceDynamicNode.java @@ -0,0 +1,32 @@ +package org.amshove.natparse.parsing; + +import org.amshove.natparse.natural.IReduceDynamicNode; +import org.amshove.natparse.natural.IVariableReferenceNode; + +class ReduceDynamicNode extends StatementNode implements IReduceDynamicNode +{ + private IVariableReferenceNode variableToReduce; + private int sizeToReduceTo; + + @Override + public IVariableReferenceNode variableToReduce() + { + return variableToReduce; + } + + @Override + public int sizeToReduceTo() + { + return sizeToReduceTo; + } + + void setVariableToResize(IVariableReferenceNode variableToReduce) + { + this.variableToReduce = variableToReduce; + } + + void setSizeToResizeTo(int sizeToReduceTo) + { + this.sizeToReduceTo = sizeToReduceTo; + } +} diff --git a/libs/natparse/src/main/java/org/amshove/natparse/parsing/StatementListParser.java b/libs/natparse/src/main/java/org/amshove/natparse/parsing/StatementListParser.java index 4fcd828a3..62d37ed4a 100644 --- a/libs/natparse/src/main/java/org/amshove/natparse/parsing/StatementListParser.java +++ b/libs/natparse/src/main/java/org/amshove/natparse/parsing/StatementListParser.java @@ -125,6 +125,9 @@ private StatementListNode statementList(SyntaxKind endTokenKind) case COMPUTE: statementList.addStatements(assignOrCompute(SyntaxKind.COMPUTE)); break; + case REDUCE: + statementList.addStatement(reduce()); + break; case RESIZE: statementList.addStatement(resize()); break; @@ -649,6 +652,64 @@ private CompressStatementNode compress() throws ParseError return compress; } + private StatementNode reduce() throws ParseError + { + if (peekAny(1, List.of(SyntaxKind.SIZE, SyntaxKind.DYNAMIC))) + { + return reduceDynamic(); + } + + var reduce = new ReduceArrayNode(); + consumeMandatory(reduce, SyntaxKind.REDUCE); + if (consumeOptionally(reduce, SyntaxKind.OCCURRENCES)) + { + consumeMandatory(reduce, SyntaxKind.OF); + } + + consumeMandatory(reduce, SyntaxKind.ARRAY); + var array = consumeVariableReferenceNode(reduce); + reduce.setArrayToReduce(array); + consumeMandatory(reduce, SyntaxKind.TO); + + if (consumeOptionally(reduce, SyntaxKind.LPAREN)) + { + while (!isAtEnd() && !peekKind(SyntaxKind.RPAREN)) + { + consume(reduce); + } + + consumeMandatory(reduce, SyntaxKind.RPAREN); + } + else + { + var literal = consumeLiteralNode(reduce, SyntaxKind.NUMBER_LITERAL); + checkIntLiteralValue(literal, 0); + } + + return reduce; + } + + private StatementNode reduceDynamic() throws ParseError + { + var reduce = new ReduceDynamicNode(); + consumeMandatory(reduce, SyntaxKind.REDUCE); + if (consumeOptionally(reduce, SyntaxKind.SIZE)) + { + consumeMandatory(reduce, SyntaxKind.OF); + } + + consumeMandatory(reduce, SyntaxKind.DYNAMIC); + consumeOptionally(reduce, SyntaxKind.VARIABLE); + + var toReduce = consumeVariableReferenceNode(reduce); + reduce.setVariableToResize(toReduce); + consumeMandatory(reduce, SyntaxKind.TO); + var newSize = consumeLiteralNode(reduce, SyntaxKind.NUMBER_LITERAL); + reduce.setSizeToResizeTo(newSize.token().intValue()); + + return reduce; + } + private StatementNode resize() throws ParseError { if (peekAny(1, List.of(SyntaxKind.SIZE, SyntaxKind.DYNAMIC))) @@ -2651,6 +2712,19 @@ private void checkStringLiteralValue(IOperandNode node, List allowedValu } } + private void checkIntLiteralValue(IOperandNode node, int allowedValue) + { + if (!(node instanceof ILiteralNode literalNode) || literalNode.token().kind() != SyntaxKind.NUMBER_LITERAL) + { + return; + } + + if (literalNode.token().intValue() != allowedValue) + { + report(ParserErrors.invalidNumericValue(literalNode, literalNode.token().intValue(), allowedValue)); + } + } + enum AllowedOperand { LITERAL, diff --git a/libs/natparse/src/test/java/org/amshove/natparse/parsing/StatementListParserShould.java b/libs/natparse/src/test/java/org/amshove/natparse/parsing/StatementListParserShould.java index 95fd428fa..60151ccc3 100644 --- a/libs/natparse/src/test/java/org/amshove/natparse/parsing/StatementListParserShould.java +++ b/libs/natparse/src/test/java/org/amshove/natparse/parsing/StatementListParserShould.java @@ -1793,4 +1793,39 @@ void raiseADiagnosticIfTerminateIsCalledWithNonNumericLiteral() { assertDiagnostic("TERMINATE 'Hi'", ParserError.TYPE_MISMATCH); } + + @ParameterizedTest + @ValueSource(strings = + { + "", "OCCURRENCES OF" + }) + void parseReduceArrayToZero(String source) + { + var reduce = assertParsesSingleStatement("REDUCE %s ARRAY #ARR TO 0".formatted(source), IReduceArrayNode.class); + assertThat(reduce.arrayToReduce().referencingToken().symbolName()).isEqualTo("#ARR"); + } + + @ParameterizedTest + @ValueSource(strings = + { + "", "OCCURRENCES OF" + }) + void parseReduceArrayToDimension(String source) + { + var reduce = assertParsesSingleStatement("REDUCE %s ARRAY #ARR TO (1:10,*:*,5:*)".formatted(source), IReduceArrayNode.class); + assertThat(reduce.arrayToReduce().referencingToken().symbolName()).isEqualTo("#ARR"); + } + + @ParameterizedTest + @ValueSource(strings = + { + "SIZE OF DYNAMIC VARIABLE", "DYNAMIC", "DYNAMIC VARIABLE", "SIZE OF DYNAMIC", + }) + void parseReduceDynamic(String combination) + { + // TODO(type-check): Has to be dynamic typed + var reduce = assertParsesSingleStatement("REDUCE %s #VAR TO 20".formatted(combination), IReduceDynamicNode.class); + assertThat(reduce.variableToReduce().referencingToken().symbolName()).isEqualTo("#VAR"); + assertThat(reduce.sizeToReduceTo()).isEqualTo(20); + } } From 66269bed984508757fcbe6cb3e22ba3bd0fb9914 Mon Sep 17 00:00:00 2001 From: Markus Amshove Date: Sat, 29 Apr 2023 19:19:53 +0200 Subject: [PATCH 2/4] Parse EXPAND --- .../natparse/natural/IExpandArrayNode.java | 6 ++ .../natparse/natural/IExpandDynamicNode.java | 8 +++ .../natparse/parsing/ExpandArrayNode.java | 20 ++++++ .../natparse/parsing/ExpandDynamicNode.java | 32 ++++++++++ .../natparse/parsing/StatementListParser.java | 61 +++++++++++++++++++ .../parsing/StatementListParserShould.java | 24 ++++++++ 6 files changed, 151 insertions(+) create mode 100644 libs/natparse/src/main/java/org/amshove/natparse/natural/IExpandArrayNode.java create mode 100644 libs/natparse/src/main/java/org/amshove/natparse/natural/IExpandDynamicNode.java create mode 100644 libs/natparse/src/main/java/org/amshove/natparse/parsing/ExpandArrayNode.java create mode 100644 libs/natparse/src/main/java/org/amshove/natparse/parsing/ExpandDynamicNode.java diff --git a/libs/natparse/src/main/java/org/amshove/natparse/natural/IExpandArrayNode.java b/libs/natparse/src/main/java/org/amshove/natparse/natural/IExpandArrayNode.java new file mode 100644 index 000000000..3d17d5fff --- /dev/null +++ b/libs/natparse/src/main/java/org/amshove/natparse/natural/IExpandArrayNode.java @@ -0,0 +1,6 @@ +package org.amshove.natparse.natural; + +public interface IExpandArrayNode extends IStatementNode +{ + IVariableReferenceNode arrayToExpand(); +} diff --git a/libs/natparse/src/main/java/org/amshove/natparse/natural/IExpandDynamicNode.java b/libs/natparse/src/main/java/org/amshove/natparse/natural/IExpandDynamicNode.java new file mode 100644 index 000000000..39e1ae0ea --- /dev/null +++ b/libs/natparse/src/main/java/org/amshove/natparse/natural/IExpandDynamicNode.java @@ -0,0 +1,8 @@ +package org.amshove.natparse.natural; + +public interface IExpandDynamicNode extends IStatementNode +{ + IVariableReferenceNode variableToExpand(); + + int sizeToExpandTo(); +} diff --git a/libs/natparse/src/main/java/org/amshove/natparse/parsing/ExpandArrayNode.java b/libs/natparse/src/main/java/org/amshove/natparse/parsing/ExpandArrayNode.java new file mode 100644 index 000000000..487e330e2 --- /dev/null +++ b/libs/natparse/src/main/java/org/amshove/natparse/parsing/ExpandArrayNode.java @@ -0,0 +1,20 @@ +package org.amshove.natparse.parsing; + +import org.amshove.natparse.natural.IExpandArrayNode; +import org.amshove.natparse.natural.IVariableReferenceNode; + +class ExpandArrayNode extends StatementNode implements IExpandArrayNode +{ + private IVariableReferenceNode arrayToExpand; + + @Override + public IVariableReferenceNode arrayToExpand() + { + return arrayToExpand; + } + + void setArrayToExpand(IVariableReferenceNode array) + { + arrayToExpand = array; + } +} diff --git a/libs/natparse/src/main/java/org/amshove/natparse/parsing/ExpandDynamicNode.java b/libs/natparse/src/main/java/org/amshove/natparse/parsing/ExpandDynamicNode.java new file mode 100644 index 000000000..b590365ad --- /dev/null +++ b/libs/natparse/src/main/java/org/amshove/natparse/parsing/ExpandDynamicNode.java @@ -0,0 +1,32 @@ +package org.amshove.natparse.parsing; + +import org.amshove.natparse.natural.IExpandDynamicNode; +import org.amshove.natparse.natural.IVariableReferenceNode; + +class ExpandDynamicNode extends StatementNode implements IExpandDynamicNode +{ + private IVariableReferenceNode variableToExpand; + private int sizeToExpandTo; + + @Override + public IVariableReferenceNode variableToExpand() + { + return variableToExpand; + } + + @Override + public int sizeToExpandTo() + { + return sizeToExpandTo; + } + + void setVariableToResize(IVariableReferenceNode variableToExpand) + { + this.variableToExpand = variableToExpand; + } + + void setSizeToResizeTo(int sizeToExpandTo) + { + this.sizeToExpandTo = sizeToExpandTo; + } +} diff --git a/libs/natparse/src/main/java/org/amshove/natparse/parsing/StatementListParser.java b/libs/natparse/src/main/java/org/amshove/natparse/parsing/StatementListParser.java index 62d37ed4a..cb906b0d4 100644 --- a/libs/natparse/src/main/java/org/amshove/natparse/parsing/StatementListParser.java +++ b/libs/natparse/src/main/java/org/amshove/natparse/parsing/StatementListParser.java @@ -201,6 +201,9 @@ private StatementListNode statementList(SyntaxKind endTokenKind) statementList.addStatement(end()); break; + case EXPAND: + statementList.addStatement(expand()); + break; case DEFINE: switch (peek(1).kind()) { @@ -710,6 +713,64 @@ private StatementNode reduceDynamic() throws ParseError return reduce; } + private StatementNode expand() throws ParseError + { + if (peekAny(1, List.of(SyntaxKind.SIZE, SyntaxKind.DYNAMIC))) + { + return expandDynamic(); + } + + var expand = new ExpandArrayNode(); + consumeMandatory(expand, SyntaxKind.EXPAND); + if (consumeOptionally(expand, SyntaxKind.OCCURRENCES)) + { + consumeMandatory(expand, SyntaxKind.OF); + } + + consumeMandatory(expand, SyntaxKind.ARRAY); + var array = consumeVariableReferenceNode(expand); + expand.setArrayToExpand(array); + consumeMandatory(expand, SyntaxKind.TO); + + if (consumeOptionally(expand, SyntaxKind.LPAREN)) + { + while (!isAtEnd() && !peekKind(SyntaxKind.RPAREN)) + { + consume(expand); + } + + consumeMandatory(expand, SyntaxKind.RPAREN); + } + else + { + var literal = consumeLiteralNode(expand, SyntaxKind.NUMBER_LITERAL); + checkIntLiteralValue(literal, 0); + } + + return expand; + } + + private StatementNode expandDynamic() throws ParseError + { + var expand = new ExpandDynamicNode(); + consumeMandatory(expand, SyntaxKind.EXPAND); + if (consumeOptionally(expand, SyntaxKind.SIZE)) + { + consumeMandatory(expand, SyntaxKind.OF); + } + + consumeMandatory(expand, SyntaxKind.DYNAMIC); + consumeOptionally(expand, SyntaxKind.VARIABLE); + + var toReduce = consumeVariableReferenceNode(expand); + expand.setVariableToResize(toReduce); + consumeMandatory(expand, SyntaxKind.TO); + var newSize = consumeLiteralNode(expand, SyntaxKind.NUMBER_LITERAL); + expand.setSizeToResizeTo(newSize.token().intValue()); + + return expand; + } + private StatementNode resize() throws ParseError { if (peekAny(1, List.of(SyntaxKind.SIZE, SyntaxKind.DYNAMIC))) diff --git a/libs/natparse/src/test/java/org/amshove/natparse/parsing/StatementListParserShould.java b/libs/natparse/src/test/java/org/amshove/natparse/parsing/StatementListParserShould.java index 60151ccc3..a8b486ca8 100644 --- a/libs/natparse/src/test/java/org/amshove/natparse/parsing/StatementListParserShould.java +++ b/libs/natparse/src/test/java/org/amshove/natparse/parsing/StatementListParserShould.java @@ -1828,4 +1828,28 @@ void parseReduceDynamic(String combination) assertThat(reduce.variableToReduce().referencingToken().symbolName()).isEqualTo("#VAR"); assertThat(reduce.sizeToReduceTo()).isEqualTo(20); } + + @ParameterizedTest + @ValueSource(strings = + { + "", "OCCURRENCES OF" + }) + void parseExpandArrayToDimension(String source) + { + var reduce = assertParsesSingleStatement("EXPAND %s ARRAY #ARR TO (1:10,*:*,5:*)".formatted(source), IExpandArrayNode.class); + assertThat(reduce.arrayToExpand().referencingToken().symbolName()).isEqualTo("#ARR"); + } + + @ParameterizedTest + @ValueSource(strings = + { + "SIZE OF DYNAMIC VARIABLE", "DYNAMIC", "DYNAMIC VARIABLE", "SIZE OF DYNAMIC", + }) + void parseExpandDynamic(String combination) + { + // TODO(type-check): Has to be dynamic typed + var reduce = assertParsesSingleStatement("EXPAND %s #VAR TO 20".formatted(combination), IExpandDynamicNode.class); + assertThat(reduce.variableToExpand().referencingToken().symbolName()).isEqualTo("#VAR"); + assertThat(reduce.sizeToExpandTo()).isEqualTo(20); + } } From a4ca48b0dea922e3b27fc9b5175cfecf061655e0 Mon Sep 17 00:00:00 2001 From: Markus Amshove Date: Sat, 29 Apr 2023 19:33:10 +0200 Subject: [PATCH 3/4] Parse error variable for REDUCE, EXPAND and RESIZE --- .../natparse/natural/IExpandArrayNode.java | 5 +++ .../natparse/natural/IExpandDynamicNode.java | 5 +++ .../natparse/natural/IReduceArrayNode.java | 5 +++ .../natparse/natural/IReduceDynamicNode.java | 5 +++ .../natparse/natural/IResizeArrayNode.java | 5 +++ .../natparse/natural/IResizeDynamicNode.java | 5 +++ .../natparse/parsing/ExpandArrayNode.java | 12 ++++++ .../natparse/parsing/ExpandDynamicNode.java | 12 ++++++ .../natparse/parsing/ReduceArrayNode.java | 12 ++++++ .../natparse/parsing/ReduceDynamicNode.java | 12 ++++++ .../natparse/parsing/ResizeArrayNode.java | 12 ++++++ .../natparse/parsing/ResizeDynamicNode.java | 13 ++++++ .../natparse/parsing/StatementListParser.java | 43 ++++++++++++++----- .../parsing/StatementListParserShould.java | 42 ++++++++++++++++++ 14 files changed, 178 insertions(+), 10 deletions(-) diff --git a/libs/natparse/src/main/java/org/amshove/natparse/natural/IExpandArrayNode.java b/libs/natparse/src/main/java/org/amshove/natparse/natural/IExpandArrayNode.java index 3d17d5fff..06d54dbce 100644 --- a/libs/natparse/src/main/java/org/amshove/natparse/natural/IExpandArrayNode.java +++ b/libs/natparse/src/main/java/org/amshove/natparse/natural/IExpandArrayNode.java @@ -1,6 +1,11 @@ package org.amshove.natparse.natural; +import javax.annotation.Nullable; + public interface IExpandArrayNode extends IStatementNode { IVariableReferenceNode arrayToExpand(); + + @Nullable + IVariableReferenceNode errorVariable(); } diff --git a/libs/natparse/src/main/java/org/amshove/natparse/natural/IExpandDynamicNode.java b/libs/natparse/src/main/java/org/amshove/natparse/natural/IExpandDynamicNode.java index 39e1ae0ea..1f108c3d8 100644 --- a/libs/natparse/src/main/java/org/amshove/natparse/natural/IExpandDynamicNode.java +++ b/libs/natparse/src/main/java/org/amshove/natparse/natural/IExpandDynamicNode.java @@ -1,8 +1,13 @@ package org.amshove.natparse.natural; +import javax.annotation.Nullable; + public interface IExpandDynamicNode extends IStatementNode { IVariableReferenceNode variableToExpand(); int sizeToExpandTo(); + + @Nullable + IVariableReferenceNode errorVariable(); } diff --git a/libs/natparse/src/main/java/org/amshove/natparse/natural/IReduceArrayNode.java b/libs/natparse/src/main/java/org/amshove/natparse/natural/IReduceArrayNode.java index c19181d30..ca58dee41 100644 --- a/libs/natparse/src/main/java/org/amshove/natparse/natural/IReduceArrayNode.java +++ b/libs/natparse/src/main/java/org/amshove/natparse/natural/IReduceArrayNode.java @@ -1,6 +1,11 @@ package org.amshove.natparse.natural; +import javax.annotation.Nullable; + public interface IReduceArrayNode extends IStatementNode { IVariableReferenceNode arrayToReduce(); + + @Nullable + IVariableReferenceNode errorVariable(); } diff --git a/libs/natparse/src/main/java/org/amshove/natparse/natural/IReduceDynamicNode.java b/libs/natparse/src/main/java/org/amshove/natparse/natural/IReduceDynamicNode.java index bf4f9ad6f..5b2e11603 100644 --- a/libs/natparse/src/main/java/org/amshove/natparse/natural/IReduceDynamicNode.java +++ b/libs/natparse/src/main/java/org/amshove/natparse/natural/IReduceDynamicNode.java @@ -1,8 +1,13 @@ package org.amshove.natparse.natural; +import javax.annotation.Nullable; + public interface IReduceDynamicNode extends IStatementNode { IVariableReferenceNode variableToReduce(); int sizeToReduceTo(); + + @Nullable + IVariableReferenceNode errorVariable(); } diff --git a/libs/natparse/src/main/java/org/amshove/natparse/natural/IResizeArrayNode.java b/libs/natparse/src/main/java/org/amshove/natparse/natural/IResizeArrayNode.java index c130c68fa..d7b57a9ec 100644 --- a/libs/natparse/src/main/java/org/amshove/natparse/natural/IResizeArrayNode.java +++ b/libs/natparse/src/main/java/org/amshove/natparse/natural/IResizeArrayNode.java @@ -1,6 +1,11 @@ package org.amshove.natparse.natural; +import javax.annotation.Nullable; + public interface IResizeArrayNode extends IStatementNode { IVariableReferenceNode arrayToResize(); + + @Nullable + IVariableReferenceNode errorVariable(); } diff --git a/libs/natparse/src/main/java/org/amshove/natparse/natural/IResizeDynamicNode.java b/libs/natparse/src/main/java/org/amshove/natparse/natural/IResizeDynamicNode.java index f93d4f148..1467c03ee 100644 --- a/libs/natparse/src/main/java/org/amshove/natparse/natural/IResizeDynamicNode.java +++ b/libs/natparse/src/main/java/org/amshove/natparse/natural/IResizeDynamicNode.java @@ -1,8 +1,13 @@ package org.amshove.natparse.natural; +import javax.annotation.Nullable; + public interface IResizeDynamicNode extends IStatementNode { IVariableReferenceNode variableToResize(); int sizeToResizeTo(); + + @Nullable + IVariableReferenceNode errorVariable(); } diff --git a/libs/natparse/src/main/java/org/amshove/natparse/parsing/ExpandArrayNode.java b/libs/natparse/src/main/java/org/amshove/natparse/parsing/ExpandArrayNode.java index 487e330e2..bfb7123e8 100644 --- a/libs/natparse/src/main/java/org/amshove/natparse/parsing/ExpandArrayNode.java +++ b/libs/natparse/src/main/java/org/amshove/natparse/parsing/ExpandArrayNode.java @@ -6,6 +6,7 @@ class ExpandArrayNode extends StatementNode implements IExpandArrayNode { private IVariableReferenceNode arrayToExpand; + private IVariableReferenceNode errorVariable; @Override public IVariableReferenceNode arrayToExpand() @@ -13,8 +14,19 @@ public IVariableReferenceNode arrayToExpand() return arrayToExpand; } + @Override + public IVariableReferenceNode errorVariable() + { + return errorVariable; + } + void setArrayToExpand(IVariableReferenceNode array) { arrayToExpand = array; } + + void setErrorVariable(IVariableReferenceNode errorVariable) + { + this.errorVariable = errorVariable; + } } diff --git a/libs/natparse/src/main/java/org/amshove/natparse/parsing/ExpandDynamicNode.java b/libs/natparse/src/main/java/org/amshove/natparse/parsing/ExpandDynamicNode.java index b590365ad..e01db6508 100644 --- a/libs/natparse/src/main/java/org/amshove/natparse/parsing/ExpandDynamicNode.java +++ b/libs/natparse/src/main/java/org/amshove/natparse/parsing/ExpandDynamicNode.java @@ -6,6 +6,7 @@ class ExpandDynamicNode extends StatementNode implements IExpandDynamicNode { private IVariableReferenceNode variableToExpand; + private IVariableReferenceNode errorVariable; private int sizeToExpandTo; @Override @@ -20,6 +21,12 @@ public int sizeToExpandTo() return sizeToExpandTo; } + @Override + public IVariableReferenceNode errorVariable() + { + return errorVariable; + } + void setVariableToResize(IVariableReferenceNode variableToExpand) { this.variableToExpand = variableToExpand; @@ -29,4 +36,9 @@ void setSizeToResizeTo(int sizeToExpandTo) { this.sizeToExpandTo = sizeToExpandTo; } + + void setErrorVariable(IVariableReferenceNode errorVariable) + { + this.errorVariable = errorVariable; + } } diff --git a/libs/natparse/src/main/java/org/amshove/natparse/parsing/ReduceArrayNode.java b/libs/natparse/src/main/java/org/amshove/natparse/parsing/ReduceArrayNode.java index b6600c0a8..74133cd97 100644 --- a/libs/natparse/src/main/java/org/amshove/natparse/parsing/ReduceArrayNode.java +++ b/libs/natparse/src/main/java/org/amshove/natparse/parsing/ReduceArrayNode.java @@ -6,6 +6,7 @@ class ReduceArrayNode extends StatementNode implements IReduceArrayNode { private IVariableReferenceNode arrayToReduce; + private IVariableReferenceNode errorVariable; @Override public IVariableReferenceNode arrayToReduce() @@ -13,8 +14,19 @@ public IVariableReferenceNode arrayToReduce() return arrayToReduce; } + @Override + public IVariableReferenceNode errorVariable() + { + return errorVariable; + } + void setArrayToReduce(IVariableReferenceNode array) { arrayToReduce = array; } + + void setErrorVariable(IVariableReferenceNode errorVariable) + { + this.errorVariable = errorVariable; + } } diff --git a/libs/natparse/src/main/java/org/amshove/natparse/parsing/ReduceDynamicNode.java b/libs/natparse/src/main/java/org/amshove/natparse/parsing/ReduceDynamicNode.java index 0e2f6c39c..cf1782ca9 100644 --- a/libs/natparse/src/main/java/org/amshove/natparse/parsing/ReduceDynamicNode.java +++ b/libs/natparse/src/main/java/org/amshove/natparse/parsing/ReduceDynamicNode.java @@ -6,6 +6,7 @@ class ReduceDynamicNode extends StatementNode implements IReduceDynamicNode { private IVariableReferenceNode variableToReduce; + private IVariableReferenceNode errorVariable; private int sizeToReduceTo; @Override @@ -14,6 +15,12 @@ public IVariableReferenceNode variableToReduce() return variableToReduce; } + @Override + public IVariableReferenceNode errorVariable() + { + return errorVariable; + } + @Override public int sizeToReduceTo() { @@ -29,4 +36,9 @@ void setSizeToResizeTo(int sizeToReduceTo) { this.sizeToReduceTo = sizeToReduceTo; } + + void setErrorVariable(IVariableReferenceNode errorVariable) + { + this.errorVariable = errorVariable; + } } diff --git a/libs/natparse/src/main/java/org/amshove/natparse/parsing/ResizeArrayNode.java b/libs/natparse/src/main/java/org/amshove/natparse/parsing/ResizeArrayNode.java index b11c10eb7..f0d18fbeb 100644 --- a/libs/natparse/src/main/java/org/amshove/natparse/parsing/ResizeArrayNode.java +++ b/libs/natparse/src/main/java/org/amshove/natparse/parsing/ResizeArrayNode.java @@ -6,6 +6,7 @@ class ResizeArrayNode extends StatementNode implements IResizeArrayNode { private IVariableReferenceNode arrayToResize; + private IVariableReferenceNode errorVariable; @Override public IVariableReferenceNode arrayToResize() @@ -13,8 +14,19 @@ public IVariableReferenceNode arrayToResize() return arrayToResize; } + @Override + public IVariableReferenceNode errorVariable() + { + return errorVariable; + } + void setArrayToResize(IVariableReferenceNode array) { arrayToResize = array; } + + void setErrorVariable(IVariableReferenceNode errorVariable) + { + this.errorVariable = errorVariable; + } } diff --git a/libs/natparse/src/main/java/org/amshove/natparse/parsing/ResizeDynamicNode.java b/libs/natparse/src/main/java/org/amshove/natparse/parsing/ResizeDynamicNode.java index e6d28c68a..b1bcb7781 100644 --- a/libs/natparse/src/main/java/org/amshove/natparse/parsing/ResizeDynamicNode.java +++ b/libs/natparse/src/main/java/org/amshove/natparse/parsing/ResizeDynamicNode.java @@ -6,6 +6,8 @@ class ResizeDynamicNode extends StatementNode implements IResizeDynamicNode { private IVariableReferenceNode variableToResize; + private IVariableReferenceNode errorVariable; + private int sizeToResizeTo; @Override @@ -20,6 +22,12 @@ public int sizeToResizeTo() return sizeToResizeTo; } + @Override + public IVariableReferenceNode errorVariable() + { + return errorVariable; + } + void setVariableToResize(IVariableReferenceNode variableToResize) { this.variableToResize = variableToResize; @@ -29,4 +37,9 @@ void setSizeToResizeTo(int sizeToResizeTo) { this.sizeToResizeTo = sizeToResizeTo; } + + void setErrorVariable(IVariableReferenceNode errorVariable) + { + this.errorVariable = errorVariable; + } } diff --git a/libs/natparse/src/main/java/org/amshove/natparse/parsing/StatementListParser.java b/libs/natparse/src/main/java/org/amshove/natparse/parsing/StatementListParser.java index cb906b0d4..3444a8332 100644 --- a/libs/natparse/src/main/java/org/amshove/natparse/parsing/StatementListParser.java +++ b/libs/natparse/src/main/java/org/amshove/natparse/parsing/StatementListParser.java @@ -689,6 +689,11 @@ private StatementNode reduce() throws ParseError checkIntLiteralValue(literal, 0); } + if (consumeOptionally(reduce, SyntaxKind.GIVING)) + { + reduce.setErrorVariable(consumeVariableReferenceNode(reduce)); + } + return reduce; } @@ -710,6 +715,11 @@ private StatementNode reduceDynamic() throws ParseError var newSize = consumeLiteralNode(reduce, SyntaxKind.NUMBER_LITERAL); reduce.setSizeToResizeTo(newSize.token().intValue()); + if (consumeOptionally(reduce, SyntaxKind.GIVING)) + { + reduce.setErrorVariable(consumeVariableReferenceNode(reduce)); + } + return reduce; } @@ -732,19 +742,16 @@ private StatementNode expand() throws ParseError expand.setArrayToExpand(array); consumeMandatory(expand, SyntaxKind.TO); - if (consumeOptionally(expand, SyntaxKind.LPAREN)) + consumeMandatory(expand, SyntaxKind.LPAREN); + while (!isAtEnd() && !peekKind(SyntaxKind.RPAREN)) { - while (!isAtEnd() && !peekKind(SyntaxKind.RPAREN)) - { - consume(expand); - } - - consumeMandatory(expand, SyntaxKind.RPAREN); + consume(expand); } - else + consumeMandatory(expand, SyntaxKind.RPAREN); + + if (consumeOptionally(expand, SyntaxKind.GIVING)) { - var literal = consumeLiteralNode(expand, SyntaxKind.NUMBER_LITERAL); - checkIntLiteralValue(literal, 0); + expand.setErrorVariable(consumeVariableReferenceNode(expand)); } return expand; @@ -768,6 +775,11 @@ private StatementNode expandDynamic() throws ParseError var newSize = consumeLiteralNode(expand, SyntaxKind.NUMBER_LITERAL); expand.setSizeToResizeTo(newSize.token().intValue()); + if (consumeOptionally(expand, SyntaxKind.GIVING)) + { + expand.setErrorVariable(consumeVariableReferenceNode(expand)); + } + return expand; } @@ -802,6 +814,12 @@ private StatementNode resize() throws ParseError } consumeMandatory(resize, SyntaxKind.RPAREN); + + if (consumeOptionally(resize, SyntaxKind.GIVING)) + { + resize.setErrorVariable(consumeVariableReferenceNode(resize)); + } + return resize; } @@ -822,6 +840,11 @@ private StatementNode resizeDynamic() throws ParseError var newSize = consumeLiteralNode(resize, SyntaxKind.NUMBER_LITERAL); resize.setSizeToResizeTo(newSize.token().intValue()); + if (consumeOptionally(resize, SyntaxKind.GIVING)) + { + resize.setErrorVariable(consumeVariableReferenceNode(resize)); + } + return resize; } diff --git a/libs/natparse/src/test/java/org/amshove/natparse/parsing/StatementListParserShould.java b/libs/natparse/src/test/java/org/amshove/natparse/parsing/StatementListParserShould.java index a8b486ca8..095c93883 100644 --- a/libs/natparse/src/test/java/org/amshove/natparse/parsing/StatementListParserShould.java +++ b/libs/natparse/src/test/java/org/amshove/natparse/parsing/StatementListParserShould.java @@ -1852,4 +1852,46 @@ void parseExpandDynamic(String combination) assertThat(reduce.variableToExpand().referencingToken().symbolName()).isEqualTo("#VAR"); assertThat(reduce.sizeToExpandTo()).isEqualTo(20); } + + @Test + void parseResizeArrayWithErrorNr() + { + var stmt = assertParsesSingleStatement("RESIZE ARRAY #ARR TO (*) GIVING #ERR", IResizeArrayNode.class); + assertIsVariableReference(stmt.errorVariable(), "#ERR"); + } + + @Test + void parseResizeDynamicWithErrorNr() + { + var stmt = assertParsesSingleStatement("RESIZE DYNAMIC #VAR TO 20 GIVING #ERR", IResizeDynamicNode.class); + assertIsVariableReference(stmt.errorVariable(), "#ERR"); + } + + @Test + void parseExpandArrayWithErrorNr() + { + var stmt = assertParsesSingleStatement("EXPAND ARRAY #ARR TO (*) GIVING #ERR", IExpandArrayNode.class); + assertIsVariableReference(stmt.errorVariable(), "#ERR"); + } + + @Test + void parseExpandDynamicWithErrorNr() + { + var stmt = assertParsesSingleStatement("EXPAND DYNAMIC #VAR TO 20 GIVING #ERR", IExpandDynamicNode.class); + assertIsVariableReference(stmt.errorVariable(), "#ERR"); + } + + @Test + void parseReduceArrayWithErrorNr() + { + var stmt = assertParsesSingleStatement("REDUCE ARRAY #ARR TO 0 GIVING #ERR", IReduceArrayNode.class); + assertIsVariableReference(stmt.errorVariable(), "#ERR"); + } + + @Test + void parseReduceDynamicWithErrorNr() + { + var stmt = assertParsesSingleStatement("REDUCE DYNAMIC #VAR TO 20 GIVING #ERR", IReduceDynamicNode.class); + assertIsVariableReference(stmt.errorVariable(), "#ERR"); + } } From a1edb4b79a7e36fd923237ac989c34dc576a6959 Mon Sep 17 00:00:00 2001 From: Markus Amshove Date: Sat, 29 Apr 2023 20:16:06 +0200 Subject: [PATCH 4/4] Update implemented-statements.md --- docs/implemented-statements.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/implemented-statements.md b/docs/implemented-statements.md index c426870fc..ad591971d 100644 --- a/docs/implemented-statements.md +++ b/docs/implemented-statements.md @@ -4,9 +4,9 @@ This document tracks the implementation status of Natural statements. Legend: -:x: - not implemented (66) +:x: - not implemented (65) -:white_check_mark: - implemented or reporting (50) +:white_check_mark: - implemented or reporting (51) partial - partially implemented to prevent false positives (6) @@ -55,7 +55,7 @@ partial - partially implemented to prevent false positives (6) | END TRANSACTION | :x: | | ESCAPE | :white_check_mark: | | EXAMINE | :white_check_mark: | -| EXPAND | :x: | +| EXPAND | :white_check_mark: | | FETCH | :white_check_mark: | | FIND | :white_check_mark: | | FOR | :white_check_mark: |