import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterators;
-import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
+import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import javax.xml.xpath.XPathExpressionException;
import org.opendaylight.yangtools.yang.common.UnqualifiedQName;
import org.opendaylight.yangtools.yang.common.YangConstants;
import org.opendaylight.yangtools.yang.common.YangNamespaceContext;
+import org.opendaylight.yangtools.yang.common.YangVersion;
+import org.opendaylight.yangtools.yang.xpath.antlr.xpathLexer;
+import org.opendaylight.yangtools.yang.xpath.antlr.xpathParser;
+import org.opendaylight.yangtools.yang.xpath.antlr.xpathParser.AbbreviatedStepContext;
+import org.opendaylight.yangtools.yang.xpath.antlr.xpathParser.AbsoluteLocationPathNorootContext;
+import org.opendaylight.yangtools.yang.xpath.antlr.xpathParser.AdditiveExprContext;
+import org.opendaylight.yangtools.yang.xpath.antlr.xpathParser.AndExprContext;
+import org.opendaylight.yangtools.yang.xpath.antlr.xpathParser.AxisSpecifierContext;
+import org.opendaylight.yangtools.yang.xpath.antlr.xpathParser.EqualityExprContext;
+import org.opendaylight.yangtools.yang.xpath.antlr.xpathParser.ExprContext;
+import org.opendaylight.yangtools.yang.xpath.antlr.xpathParser.FilterExprContext;
+import org.opendaylight.yangtools.yang.xpath.antlr.xpathParser.FunctionCallContext;
+import org.opendaylight.yangtools.yang.xpath.antlr.xpathParser.FunctionNameContext;
+import org.opendaylight.yangtools.yang.xpath.antlr.xpathParser.LocationPathContext;
+import org.opendaylight.yangtools.yang.xpath.antlr.xpathParser.MultiplicativeExprContext;
+import org.opendaylight.yangtools.yang.xpath.antlr.xpathParser.NCNameContext;
+import org.opendaylight.yangtools.yang.xpath.antlr.xpathParser.NameTestContext;
+import org.opendaylight.yangtools.yang.xpath.antlr.xpathParser.NodeTestContext;
+import org.opendaylight.yangtools.yang.xpath.antlr.xpathParser.OrExprContext;
+import org.opendaylight.yangtools.yang.xpath.antlr.xpathParser.PathExprNoRootContext;
+import org.opendaylight.yangtools.yang.xpath.antlr.xpathParser.PredicateContext;
+import org.opendaylight.yangtools.yang.xpath.antlr.xpathParser.PrimaryExprContext;
+import org.opendaylight.yangtools.yang.xpath.antlr.xpathParser.QNameContext;
+import org.opendaylight.yangtools.yang.xpath.antlr.xpathParser.RelationalExprContext;
+import org.opendaylight.yangtools.yang.xpath.antlr.xpathParser.RelativeLocationPathContext;
+import org.opendaylight.yangtools.yang.xpath.antlr.xpathParser.StepContext;
+import org.opendaylight.yangtools.yang.xpath.antlr.xpathParser.UnaryExprNoRootContext;
+import org.opendaylight.yangtools.yang.xpath.antlr.xpathParser.UnionExprNoRootContext;
+import org.opendaylight.yangtools.yang.xpath.antlr.xpathParser.VariableReferenceContext;
import org.opendaylight.yangtools.yang.xpath.api.YangBinaryOperator;
import org.opendaylight.yangtools.yang.xpath.api.YangBooleanConstantExpr;
import org.opendaylight.yangtools.yang.xpath.api.YangExpr;
import org.opendaylight.yangtools.yang.xpath.api.YangXPathMathSupport;
import org.opendaylight.yangtools.yang.xpath.api.YangXPathNodeType;
import org.opendaylight.yangtools.yang.xpath.api.YangXPathParser;
-import org.opendaylight.yangtools.yang.xpath.impl.xpathParser.AbbreviatedStepContext;
-import org.opendaylight.yangtools.yang.xpath.impl.xpathParser.AbsoluteLocationPathNorootContext;
-import org.opendaylight.yangtools.yang.xpath.impl.xpathParser.AdditiveExprContext;
-import org.opendaylight.yangtools.yang.xpath.impl.xpathParser.AndExprContext;
-import org.opendaylight.yangtools.yang.xpath.impl.xpathParser.AxisSpecifierContext;
-import org.opendaylight.yangtools.yang.xpath.impl.xpathParser.EqualityExprContext;
-import org.opendaylight.yangtools.yang.xpath.impl.xpathParser.ExprContext;
-import org.opendaylight.yangtools.yang.xpath.impl.xpathParser.FilterExprContext;
-import org.opendaylight.yangtools.yang.xpath.impl.xpathParser.FunctionCallContext;
-import org.opendaylight.yangtools.yang.xpath.impl.xpathParser.FunctionNameContext;
-import org.opendaylight.yangtools.yang.xpath.impl.xpathParser.LocationPathContext;
-import org.opendaylight.yangtools.yang.xpath.impl.xpathParser.MultiplicativeExprContext;
-import org.opendaylight.yangtools.yang.xpath.impl.xpathParser.NCNameContext;
-import org.opendaylight.yangtools.yang.xpath.impl.xpathParser.NameTestContext;
-import org.opendaylight.yangtools.yang.xpath.impl.xpathParser.NodeTestContext;
-import org.opendaylight.yangtools.yang.xpath.impl.xpathParser.OrExprContext;
-import org.opendaylight.yangtools.yang.xpath.impl.xpathParser.PathExprNoRootContext;
-import org.opendaylight.yangtools.yang.xpath.impl.xpathParser.PredicateContext;
-import org.opendaylight.yangtools.yang.xpath.impl.xpathParser.PrimaryExprContext;
-import org.opendaylight.yangtools.yang.xpath.impl.xpathParser.QNameContext;
-import org.opendaylight.yangtools.yang.xpath.impl.xpathParser.RelationalExprContext;
-import org.opendaylight.yangtools.yang.xpath.impl.xpathParser.RelativeLocationPathContext;
-import org.opendaylight.yangtools.yang.xpath.impl.xpathParser.StepContext;
-import org.opendaylight.yangtools.yang.xpath.impl.xpathParser.UnaryExprNoRootContext;
-import org.opendaylight.yangtools.yang.xpath.impl.xpathParser.UnionExprNoRootContext;
-import org.opendaylight.yangtools.yang.xpath.impl.xpathParser.VariableReferenceContext;
/**
* ANTLR-based XPath parser. Uses {@code xpath.g4} ANTLR grammar.
@Override
public YangXPathExpression parseExpression(final String xpath) throws XPathExpressionException {
- return new AntlrYangXPathExpression.Base(mathMode, parseExpr(xpath), xpath);
+ final Entry<YangVersion, YangExpr> result = parseExpr(xpath);
+ return new AntlrYangXPathExpression.Base(mathMode, result.getKey(), result.getValue(), xpath);
}
@Override
@Override
public YangXPathExpression.QualifiedBound parseExpression(final String xpath) throws XPathExpressionException {
- return new AntlrYangXPathExpression.Qualified(mathMode, parseExpr(xpath), xpath, namespaceContext);
+ final Entry<YangVersion, YangExpr> result = parseExpr(xpath);
+ return new AntlrYangXPathExpression.Qualified(mathMode, result.getKey(), result.getValue(), xpath,
+ namespaceContext);
}
@Override
@Override
public YangXPathExpression.UnqualifiedBound parseExpression(final String xpath)
throws XPathExpressionException {
- return new AntlrYangXPathExpression.Unqualified(mathMode, parseExpr(xpath), xpath, namespaceContext,
- defaultNamespace);
+ final Entry<YangVersion, YangExpr> result = parseExpr(xpath);
+
+ return new AntlrYangXPathExpression.Unqualified(mathMode, result.getKey(), result.getValue(), xpath,
+ namespaceContext, defaultNamespace);
}
@Override
private final YangXPathMathSupport mathSupport;
private final FunctionSupport functionSupport;
+ private YangVersion minimumYangVersion = YangVersion.VERSION_1;
+
AntlrXPathParser(final YangXPathMathMode mathMode) {
this.mathMode = requireNonNull(mathMode);
this.mathSupport = mathMode.getSupport();
}
}
- final YangExpr parseExpr(final String xpath) throws XPathExpressionException {
+ @SuppressWarnings("checkstyle:illegalCatch")
+ final Entry<YangVersion, YangExpr> parseExpr(final String xpath) throws XPathExpressionException {
// Create a parser and disconnect it from console error output
final xpathLexer lexer = new xpathLexer(CharStreams.fromString(xpath));
final xpathParser parser = new xpathParser(new CommonTokenStream(lexer));
lexer.addErrorListener(listener);
parser.removeErrorListeners();
parser.addErrorListener(listener);
-
- final YangExpr expr = parseExpr(parser.main().expr());
+ final ExprContext antlr = parser.main().expr();
listener.reportError();
- return expr;
+
+ // Reset our internal context
+ minimumYangVersion = YangVersion.VERSION_1;
+
+ final YangExpr expr;
+ try {
+ expr = parseExpr(antlr);
+ } catch (RuntimeException e) {
+ throw new XPathExpressionException(e);
+ }
+ return new SimpleImmutableEntry<>(minimumYangVersion, expr);
}
/**
* Parse and simplify an XPath expression in {@link ExprContext} representation.
*
+ * @param ctx Current parsing context
* @param expr ANTLR ExprContext
* @return A {@link YangExpr}
* @throws NullPointerException if {@code expr} is null
throw illegalShape(name);
}
- final List<YangExpr> args = ImmutableList.copyOf(Lists.transform(expr.expr(), this::parseExpr));
+ final List<YangExpr> args = expr.expr().stream().map(this::parseExpr).collect(ImmutableList.toImmutableList());
final YangFunction func = YANG_FUNCTIONS.get(parsed);
if (func != null) {
+ if (minimumYangVersion.compareTo(func.getYangVersion()) < 0) {
+ minimumYangVersion = func.getYangVersion();
+ }
return functionSupport.functionToExpr(func, args);
}
private Deque<Step> parseLocationPathSteps(final RelativeLocationPathContext expr) {
final Deque<Step> steps = new ArrayDeque<>(expr.getChildCount());
final Iterator<ParseTree> it = expr.children.iterator();
- steps.add(parseStep(nextContext(it, StepContext.class)));
+ addNotSelfStep(steps, parseStep(nextContext(it, StepContext.class)));
while (it.hasNext()) {
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));
- if (!SELF_STEP.equals(step)) {
- steps.add(step);
- }
+ addNotSelfStep(steps, parseStep(nextContext(it, StepContext.class)));
}
return steps;
}
+ private static void addNotSelfStep(final Deque<Step> steps, final Step step) {
+ if (!SELF_STEP.equals(step)) {
+ steps.add(step);
+ }
+ }
+
private YangExpr parseTerminal(final TerminalNode term) {
final String text = term.getText();
switch (term.getSymbol().getType()) {
final YangBinaryOperator operator = nextOperator(it);
final YangExpr right = parseAdditive(nextContext(it, AdditiveExprContext.class));
final Optional<YangExpr> simple = simplifyNumbers(operator, ret, right);
- ret = simple.isPresent() ? simple.get() : nextOperator(it).exprWith(ret, right);
+ ret = simple.isPresent() ? simple.get() : operator.exprWith(ret, right);
} while (it.hasNext());
return ret;