Fix XPathExpr parsing
[yangtools.git] / yang / yang-xpath-impl / src / main / java / org / opendaylight / yangtools / yang / xpath / impl / AntlrXPathParser.java
index f3e9a0998ee428412200120093a9ffb84e2173c4..2c7f506cc1aff934c256a727104cb917e0e45cc8 100644 (file)
@@ -34,15 +34,11 @@ import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 import javax.xml.xpath.XPathExpressionException;
-import org.antlr.v4.runtime.BaseErrorListener;
 import org.antlr.v4.runtime.CharStreams;
 import org.antlr.v4.runtime.CommonTokenStream;
 import org.antlr.v4.runtime.ParserRuleContext;
-import org.antlr.v4.runtime.RecognitionException;
-import org.antlr.v4.runtime.Recognizer;
 import org.antlr.v4.runtime.tree.ParseTree;
 import org.antlr.v4.runtime.tree.TerminalNode;
-import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.YangConstants;
 import org.opendaylight.yangtools.yang.common.YangNamespaceContext;
@@ -60,6 +56,7 @@ import org.opendaylight.yangtools.yang.xpath.api.YangNaryExpr;
 import org.opendaylight.yangtools.yang.xpath.api.YangNaryOperator;
 import org.opendaylight.yangtools.yang.xpath.api.YangNegateExpr;
 import org.opendaylight.yangtools.yang.xpath.api.YangNumberExpr;
+import org.opendaylight.yangtools.yang.xpath.api.YangPathExpr;
 import org.opendaylight.yangtools.yang.xpath.api.YangVariableReferenceExpr;
 import org.opendaylight.yangtools.yang.xpath.api.YangXPathAxis;
 import org.opendaylight.yangtools.yang.xpath.api.YangXPathExpression;
@@ -116,7 +113,7 @@ final class AntlrXPathParser implements YangXPathParser {
     private static final AxisStep SELF_STEP = YangXPathAxis.SELF.asStep();
 
     private final YangXPathMathMode mathMode;
-    private final YangXPathMathSupport<?> mathSupport;
+    private final YangXPathMathSupport mathSupport;
     private final YangNamespaceContext namespaceContext;
     private final FunctionSupport functionSupport;
 
@@ -133,32 +130,14 @@ final class AntlrXPathParser implements YangXPathParser {
         final xpathLexer lexer = new xpathLexer(CharStreams.fromString(xpath));
         final xpathParser parser = new xpathParser(new CommonTokenStream(lexer));
 
-        final List<XPathExpressionException> errors = new ArrayList<>();
-        final BaseErrorListener listener = new BaseErrorListener() {
-            @Override
-            public void syntaxError(final @Nullable Recognizer<?, ?> recognizer, final @Nullable Object offendingSymbol,
-                    final int line, final int charPositionInLine, final @Nullable String msg,
-                    final @Nullable RecognitionException cause) {
-                final XPathExpressionException ex = new XPathExpressionException(msg);
-                ex.initCause(cause);
-                if (errors.isEmpty()) {
-                    errors.add(ex);
-                } else {
-                    errors.get(0).addSuppressed(ex);
-                }
-            }
-        };
-
+        final CapturingErrorListener listener = new CapturingErrorListener();
         lexer.removeErrorListeners();
         lexer.addErrorListener(listener);
         parser.removeErrorListeners();
         parser.addErrorListener(listener);
 
         final YangExpr expr = parseExpr(parser.main().expr());
-        if (!errors.isEmpty()) {
-            throw errors.get(0);
-        }
-
+        listener.reportError();
         return new AntlrYangXPathExpression(namespaceContext, mathMode, expr, xpath);
     }
 
@@ -253,15 +232,7 @@ final class AntlrXPathParser implements YangXPathParser {
         verifyChildCount(abs, 2);
 
         final Deque<Step> steps = parseLocationPathSteps(getChild(abs, RelativeLocationPathContext.class, 1));
-        switch (getTerminalType(abs, 0)) {
-            case xpathParser.PATHSEP:
-                break;
-            case xpathParser.ABRPATH:
-                steps.addFirst(YangXPathAxis.DESCENDANT_OR_SELF.asStep());
-                break;
-            default:
-                throw illegalShape(abs);
-        }
+        parseStepShorthand(abs.getChild(0)).ifPresent(steps::addFirst);
 
         return YangLocationPath.of(true, steps);
     }
@@ -297,8 +268,9 @@ final class AntlrXPathParser implements YangXPathParser {
         }
 
         verifyChildCount(expr, 3);
-        return parseOperator(expr.getChild(1)).exprWith(filter,
-            parseRelativeLocationPath(getChild(expr, RelativeLocationPathContext.class, 2)));
+        final Deque<Step> steps = parseLocationPathSteps(getChild(expr, RelativeLocationPathContext.class, 2));
+        parseStepShorthand(expr.getChild(1)).ifPresent(steps::addFirst);
+        return YangPathExpr.of(filter, YangLocationPath.of(false, steps));
     }
 
     private YangExpr parsePredicate(final PredicateContext expr) {
@@ -337,16 +309,7 @@ final class AntlrXPathParser implements YangXPathParser {
         steps.add(parseStep(nextContext(it, StepContext.class)));
 
         while (it.hasNext()) {
-            final ParseTree tree = it.next();
-            switch (verifyTerminal(tree).getSymbol().getType()) {
-                case xpathParser.PATHSEP:
-                    break;
-                case xpathParser.ABRPATH:
-                    steps.add(YangXPathAxis.DESCENDANT_OR_SELF.asStep());
-                    break;
-                default:
-                    throw illegalShape(tree);
-            }
+            parseStepShorthand(it.next()).ifPresent(steps::add);
 
             // Parse step and add it if it's not SELF_STEP
             final Step step = parseStep(nextContext(it, StepContext.class));
@@ -383,9 +346,7 @@ final class AntlrXPathParser implements YangXPathParser {
             // Even number of '-' tokens cancel out
             return ret;
         }
-
-        return ret instanceof YangNumberExpr ? mathSupport.negateNumber((YangNumberExpr<?, ?>) ret)
-                : YangNegateExpr.of(ret);
+        return ret instanceof YangNumberExpr ? mathSupport.negateNumber((YangNumberExpr) ret) : YangNegateExpr.of(ret);
     }
 
     private YangExpr parseUnion(final UnionExprNoRootContext expr) {
@@ -437,7 +398,7 @@ final class AntlrXPathParser implements YangXPathParser {
             final YangExpr right) {
         if (left instanceof YangNumberExpr && right instanceof YangNumberExpr) {
             // Constant folding on numbers -- precision plays a role here
-            return mathSupport.tryEvaluate(operator, (YangNumberExpr<?, ?>)left, (YangNumberExpr<?, ?>)right);
+            return mathSupport.tryEvaluate(operator, (YangNumberExpr)left, (YangNumberExpr)right);
         }
         return Optional.empty();
     }
@@ -568,4 +529,15 @@ final class AntlrXPathParser implements YangXPathParser {
         final String str = verifyTerminal(tree).getText();
         return verifyNotNull(BINARY_OPERATORS.get(str), "Unhandled operator %s", str);
     }
+
+    private static Optional<Step> parseStepShorthand(final ParseTree tree) {
+        switch (verifyTerminal(tree).getSymbol().getType()) {
+            case xpathParser.PATHSEP:
+                return Optional.empty();
+            case xpathParser.ABRPATH:
+                return Optional.of(YangXPathAxis.DESCENDANT_OR_SELF.asStep());
+            default:
+                throw illegalShape(tree);
+        }
+    }
 }