diff --git a/eo-parser/src/main/java/org/eolang/parser/RedundantParentheses.java b/eo-parser/src/main/java/org/eolang/parser/RedundantParentheses.java deleted file mode 100644 index db8c0751c8..0000000000 --- a/eo-parser/src/main/java/org/eolang/parser/RedundantParentheses.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2016-2023 Objectionary.com - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package org.eolang.parser; - -import com.jcabi.log.Logger; -import java.util.ArrayDeque; -import java.util.Deque; -import java.util.function.Consumer; -import java.util.function.Predicate; -import java.util.regex.Pattern; - -/** - * The class that checks redundant parentheses for object expression. - * - * @since 0.28.12 - */ -final class RedundantParentheses implements Predicate { - - /** - * Pattern for string literals. - */ - private static final Pattern PATTERN = Pattern.compile("(?ms)#.*?\\n|\"\"\".*?\"\"\"|\".*?\""); - - /** - * The callback that will be called in case if redundant parentheses is found. - */ - private final Consumer reaction; - - /** - * Constructor with default reaction that writes warning to the log. - */ - RedundantParentheses() { - this(s -> Logger.warn("Redundant parentheses", s)); - } - - /** - * The main constructor. - * - * @param reaction Will be called in case if redundant parentheses is found. - */ - RedundantParentheses(final Consumer reaction) { - this.reaction = reaction; - } - - /** - * Checks if the expression contains redundant parentheses. - * Examples of expressions to check: - *
{@code
-     *  1.plus 2 > x
-     *  "Text" > y
-     *  (1.plus 2).plus 3
-     * }
-     * 
- * @param expression Raw object expression from parser. - * @return True if the expression contains redundant parentheses. - */ - public boolean test(final String expression) { - final Deque stack = new ArrayDeque<>(); - boolean res = false; - for (final char symbol : RedundantParentheses.expressionChars(expression)) { - if (symbol == ')') { - boolean operation = false; - char current = stack.pop(); - while (current != '(') { - if (current == '.' || current == ' ' || current == '-') { - operation = true; - } - current = stack.pop(); - } - if (!operation) { - res = true; - } - } else { - stack.push(symbol); - } - } - if (stack.isEmpty()) { - res = true; - } - if (res) { - this.reaction.accept(expression); - } - return res; - } - - /** - * Clears raw expression from text literals and returns it as an array of chars. - * @param expression Raw expression - * @return Expression as an array of chars. - * @todo #1897:30m Refactor regexp in `RedundantParenthesis`. - * The Java regex engine uses recursive method calls to implement backtracking. - * Therefore when a repetition inside a regular expression contains multiple paths - * (i.e. the body of the repetition contains an alternation (|), an optional - * element or another repetition), trying to match the regular expression can cause a - * stack overflow on large inputs. This does not happen when using a possessive quantifier - * (such as *+ instead of *) or when using a character class inside a repetition - * (e.g. [ab]* instead of (a|b)*). - * Refactor this repetition that can lead to a stack overflow for large inputs. (line 113) - */ - private static char[] expressionChars(final String expression) { - return RedundantParentheses - .PATTERN.matcher(expression).replaceAll("literal").toCharArray(); - } -} diff --git a/eo-parser/src/test/java/org/eolang/parser/RedundantParenthesesTest.java b/eo-parser/src/test/java/org/eolang/parser/RedundantParenthesesTest.java deleted file mode 100644 index 0afebc98f9..0000000000 --- a/eo-parser/src/test/java/org/eolang/parser/RedundantParenthesesTest.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2016-2023 Objectionary.com - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package org.eolang.parser; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.stream.Stream; -import org.cactoos.io.InputOf; -import org.cactoos.io.OutputTo; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -/** - * Test cases for checking of redundant parentheses. - * The {@link org.eolang.parser.Syntax} object is used in order to check all possible expressions - * and situations. - * - * @since 0.28.12 - * @todo #2399:30min Do we need {@link RedundantParentheses} class? After refactoring grammar - * ({@see Program.g4}) parentheses are controlled at the level of grammar and can't be used in the - * many ways it was allowed to use them before. This is the reason the test is disabled. Need to - * check whether we really need the class with new grammar or not. If yes - return - * {@link RedundantParentheses} back to {@link XeListener} and refactor the test. - * If no - move the test cases below to {@link org.eolang.parser.typos} folder and remove - * {@link RedundantParentheses} class from the source code. - */ -class RedundantParenthesesTest { - - @ParameterizedTest - @MethodSource("testCases") - @Disabled - void checksIfBracketsIsNotRedundant( - final String program, - final boolean correct - ) throws IOException { - final Syntax syntax = new Syntax( - "foo", - new InputOf(program), - new OutputTo(new ByteArrayOutputStream()) - ); - if (correct) { - syntax.parse(); - } else { - Assertions.assertThrows(IllegalStateException.class, syntax::parse); - } - } - - static Stream testCases() { - return Stream.of( - Arguments.of("[] > foo\n 1.add (a.add 5) 4 > x", true), - Arguments.of("[] > foo\n add. 1 (a.add 5) > x", true), - Arguments.of("[] > foo\n add. 1 2 3 4 > x", true), - Arguments.of("[] > foo\n add. 1 2 3 4", true), - Arguments.of("[] > foo\n add 1 2 3 4", true), - Arguments.of("[] > foo\n 1.add 4 > x", true), - Arguments.of("[] > foo\n (add 1).add 2", true), - Arguments.of("[] > foo\n 1.add (1.add (1.add (1.add 1))) > x", true), - Arguments.of("[] > foo\n (1.add 1).add (1.add 1) > x", true), - Arguments.of("[] > foo\n add > x\n 1\n 1\n", true), - Arguments.of("[] > foo\n 1.with-text \"(text) with parentheses a(n)...\" > x", true), - Arguments.of("[] > foo\n \"=(\" > x", true), - Arguments.of("[] > foo\n \"=)\" > x", true), - Arguments.of("[] > foo\n \")\" > x", true), - Arguments.of("[] > foo\n \"(-_-)\" > x", true), - Arguments.of("[] > foo\n \"Hello\".<.eq (\"Hello\".<)\n", true), - Arguments.of("[] > foo\n \"\"\"\n(-_-)\n\"\"\" > x", true), - Arguments.of("[] > foo\n add (-4) (-5)", true), - Arguments.of("# Comment().\n[] > obj\n", true), - Arguments.of("[] > foo\n (1.add (a.add 5) (4)) > x", false), - Arguments.of("[] > foo\n (1.add (a.add 5) 4) > x", false), - Arguments.of("[] > foo\n (1.add (a.add 5) 4)", false), - Arguments.of("[] > foo\n 1.add (5) > x", false), - Arguments.of("[] > foo\n (1.add 4) > x", false), - Arguments.of("[] > foo\n (1.add 4)", false), - Arguments.of("[] > foo\n ((1.add 1)) > x", false), - Arguments.of("[] > foo\n 1.add 1 > x\n (1.add 1)", false), - Arguments.of("[] > foo\n 1.add 1 > x\n (1.add 1) > y", false), - Arguments.of("[] > foo\n add > x\n (1)\n (1)\n", false) - ); - } -} diff --git a/eo-parser/src/test/resources/org/eolang/parser/packs/syntax/redundant-parentheses.yaml b/eo-parser/src/test/resources/org/eolang/parser/packs/syntax/redundant-parentheses.yaml new file mode 100644 index 0000000000..b78b3b97d3 --- /dev/null +++ b/eo-parser/src/test/resources/org/eolang/parser/packs/syntax/redundant-parentheses.yaml @@ -0,0 +1,27 @@ +xsls: [] +tests: + - /program/errors[count(*)=0] +eo: | + 1.add (a.add 5) 4 > x + add. 1 (a.add 5) > x + add. 1 2 3 4 > x + add. 1 2 3 4 + add 1 2 3 4 + 1.add 4 > x + (add 1).add 2 + 1.add (1.add (1.add (1.add 1))) > x + (1.add 1).add (1.add 1) > x + add > x + 1 + 1 + 1.with-text "(text) with parentheses a(n)..." > x + "=(" > x + "=)" > x + ")" > x + "(-_-)" > x + "Hello".<.eq ("Hello".<) > a + """ + (-_-) + """ > x + # Comment(). + [] > obj diff --git a/eo-parser/src/test/resources/org/eolang/parser/typos/redundant-parentheses/extra-braces-1.yaml b/eo-parser/src/test/resources/org/eolang/parser/typos/redundant-parentheses/extra-braces-1.yaml new file mode 100644 index 0000000000..97bbfdeee0 --- /dev/null +++ b/eo-parser/src/test/resources/org/eolang/parser/typos/redundant-parentheses/extra-braces-1.yaml @@ -0,0 +1,3 @@ +line: 1 +eo: | + (1.add (a.add 5) (4)) > x \ No newline at end of file diff --git a/eo-parser/src/test/resources/org/eolang/parser/typos/redundant-parentheses/extra-braces-2.yaml b/eo-parser/src/test/resources/org/eolang/parser/typos/redundant-parentheses/extra-braces-2.yaml new file mode 100644 index 0000000000..b367c2eaeb --- /dev/null +++ b/eo-parser/src/test/resources/org/eolang/parser/typos/redundant-parentheses/extra-braces-2.yaml @@ -0,0 +1,3 @@ +line: 1 +eo: | + (1.add (a.add 5) 4) > x \ No newline at end of file diff --git a/eo-parser/src/test/resources/org/eolang/parser/typos/redundant-parentheses/extra-braces-3.yaml b/eo-parser/src/test/resources/org/eolang/parser/typos/redundant-parentheses/extra-braces-3.yaml new file mode 100644 index 0000000000..7b4bb80a60 --- /dev/null +++ b/eo-parser/src/test/resources/org/eolang/parser/typos/redundant-parentheses/extra-braces-3.yaml @@ -0,0 +1,3 @@ +line: 1 +eo: | + (1.add (a.add 5) 4) \ No newline at end of file diff --git a/eo-parser/src/test/resources/org/eolang/parser/typos/redundant-parentheses/extra-braces-4.yaml b/eo-parser/src/test/resources/org/eolang/parser/typos/redundant-parentheses/extra-braces-4.yaml new file mode 100644 index 0000000000..b3a4ba8dcc --- /dev/null +++ b/eo-parser/src/test/resources/org/eolang/parser/typos/redundant-parentheses/extra-braces-4.yaml @@ -0,0 +1,3 @@ +line: 1 +eo: | + (1.add 4) > x \ No newline at end of file diff --git a/eo-parser/src/test/resources/org/eolang/parser/typos/redundant-parentheses/extra-braces-5.yaml b/eo-parser/src/test/resources/org/eolang/parser/typos/redundant-parentheses/extra-braces-5.yaml new file mode 100644 index 0000000000..fa1eee4f82 --- /dev/null +++ b/eo-parser/src/test/resources/org/eolang/parser/typos/redundant-parentheses/extra-braces-5.yaml @@ -0,0 +1,3 @@ +line: 1 +eo: | + (1.add 4) \ No newline at end of file diff --git a/eo-parser/src/test/resources/org/eolang/parser/typos/redundant-parentheses/extra-braces-6.yaml b/eo-parser/src/test/resources/org/eolang/parser/typos/redundant-parentheses/extra-braces-6.yaml new file mode 100644 index 0000000000..37f2faa137 --- /dev/null +++ b/eo-parser/src/test/resources/org/eolang/parser/typos/redundant-parentheses/extra-braces-6.yaml @@ -0,0 +1,3 @@ +line: 1 +eo: | + ((1.add 1)) > x \ No newline at end of file diff --git a/eo-parser/src/test/resources/org/eolang/parser/typos/redundant-parentheses/just-number.yaml b/eo-parser/src/test/resources/org/eolang/parser/typos/redundant-parentheses/just-number.yaml new file mode 100644 index 0000000000..2ab9f917ef --- /dev/null +++ b/eo-parser/src/test/resources/org/eolang/parser/typos/redundant-parentheses/just-number.yaml @@ -0,0 +1,3 @@ +line: 1 +eo: | + 1.add (5) > x \ No newline at end of file diff --git a/eo-parser/src/test/resources/org/eolang/parser/typos/redundant-parentheses/negative-numbers.yaml b/eo-parser/src/test/resources/org/eolang/parser/typos/redundant-parentheses/negative-numbers.yaml new file mode 100644 index 0000000000..3c4afdd4f8 --- /dev/null +++ b/eo-parser/src/test/resources/org/eolang/parser/typos/redundant-parentheses/negative-numbers.yaml @@ -0,0 +1,3 @@ +line: 1 +eo: | + add (-4) (-5) > x \ No newline at end of file diff --git a/eo-parser/src/test/resources/org/eolang/parser/typos/redundant-parentheses/numbers.yaml b/eo-parser/src/test/resources/org/eolang/parser/typos/redundant-parentheses/numbers.yaml new file mode 100644 index 0000000000..4d0a6bbe95 --- /dev/null +++ b/eo-parser/src/test/resources/org/eolang/parser/typos/redundant-parentheses/numbers.yaml @@ -0,0 +1,5 @@ +line: 2 +eo: | + add > x + (1) + (1) diff --git a/eo-parser/src/test/resources/org/eolang/parser/typos/redundant-parentheses/simple-application-named.yaml b/eo-parser/src/test/resources/org/eolang/parser/typos/redundant-parentheses/simple-application-named.yaml new file mode 100644 index 0000000000..6f4fa2cb33 --- /dev/null +++ b/eo-parser/src/test/resources/org/eolang/parser/typos/redundant-parentheses/simple-application-named.yaml @@ -0,0 +1,4 @@ +line: 3 +eo: | + 1.add 1 > x + (1.add 1) > y diff --git a/eo-parser/src/test/resources/org/eolang/parser/typos/redundant-parentheses/simple-application.yaml b/eo-parser/src/test/resources/org/eolang/parser/typos/redundant-parentheses/simple-application.yaml new file mode 100644 index 0000000000..9178b2fe29 --- /dev/null +++ b/eo-parser/src/test/resources/org/eolang/parser/typos/redundant-parentheses/simple-application.yaml @@ -0,0 +1,4 @@ +line: 3 +eo: | + 1.add 1 > x + (1.add 1)