X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=xpath%2Fyang-xpath-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fyang%2Fxpath%2Fimpl%2FInstanceIdentifierParser.java;h=31fac3e9b0f09b85bf41ffa0442bde170b0c375d;hb=45e8951a576c6bf2cb2bd0290167619b8be2fc5a;hp=4fdf780847e2bce8187ae764f763dba374d3de16;hpb=a8b25dbe1b83518844ba8a1c3d5fe970400b7f16;p=yangtools.git diff --git a/xpath/yang-xpath-impl/src/main/java/org/opendaylight/yangtools/yang/xpath/impl/InstanceIdentifierParser.java b/xpath/yang-xpath-impl/src/main/java/org/opendaylight/yangtools/yang/xpath/impl/InstanceIdentifierParser.java index 4fdf780847..31fac3e9b0 100644 --- a/xpath/yang-xpath-impl/src/main/java/org/opendaylight/yangtools/yang/xpath/impl/InstanceIdentifierParser.java +++ b/xpath/yang-xpath-impl/src/main/java/org/opendaylight/yangtools/yang/xpath/impl/InstanceIdentifierParser.java @@ -10,8 +10,10 @@ package org.opendaylight.yangtools.yang.xpath.impl; import static java.util.Objects.requireNonNull; import static org.opendaylight.yangtools.yang.xpath.impl.ParseTreeUtils.getChild; import static org.opendaylight.yangtools.yang.xpath.impl.ParseTreeUtils.illegalShape; +import static org.opendaylight.yangtools.yang.xpath.impl.ParseTreeUtils.verifyTerminal; import static org.opendaylight.yangtools.yang.xpath.impl.ParseTreeUtils.verifyToken; +import com.google.common.base.VerifyException; import com.google.common.collect.ImmutableSet; import java.util.ArrayList; import java.util.Collection; @@ -20,9 +22,9 @@ import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; import org.opendaylight.yangtools.yang.common.UnresolvedQName; import org.opendaylight.yangtools.yang.common.YangNamespaceContext; +import org.opendaylight.yangtools.yang.xpath.antlr.instanceIdentifierLexer; import org.opendaylight.yangtools.yang.xpath.antlr.instanceIdentifierParser; import org.opendaylight.yangtools.yang.xpath.antlr.instanceIdentifierParser.EqQuotedStringContext; -import org.opendaylight.yangtools.yang.xpath.antlr.instanceIdentifierParser.InstanceIdentifierContext; import org.opendaylight.yangtools.yang.xpath.antlr.instanceIdentifierParser.KeyPredicateContext; import org.opendaylight.yangtools.yang.xpath.antlr.instanceIdentifierParser.KeyPredicateExprContext; import org.opendaylight.yangtools.yang.xpath.antlr.instanceIdentifierParser.LeafListPredicateContext; @@ -32,7 +34,6 @@ import org.opendaylight.yangtools.yang.xpath.antlr.instanceIdentifierParser.Path import org.opendaylight.yangtools.yang.xpath.antlr.instanceIdentifierParser.PosContext; import org.opendaylight.yangtools.yang.xpath.antlr.instanceIdentifierParser.PredicateContext; import org.opendaylight.yangtools.yang.xpath.antlr.instanceIdentifierParser.QuotedStringContext; -import org.opendaylight.yangtools.yang.xpath.antlr.xpathLexer; import org.opendaylight.yangtools.yang.xpath.api.YangBinaryOperator; import org.opendaylight.yangtools.yang.xpath.api.YangExpr; import org.opendaylight.yangtools.yang.xpath.api.YangLiteralExpr; @@ -90,15 +91,15 @@ abstract class InstanceIdentifierParser { } final Absolute interpretAsInstanceIdentifier(final YangLiteralExpr expr) throws XPathExpressionException { - final xpathLexer lexer = new xpathLexer(CharStreams.fromString(expr.getLiteral())); - final instanceIdentifierParser parser = new instanceIdentifierParser(new CommonTokenStream(lexer)); - final CapturingErrorListener listener = new CapturingErrorListener(); + final var lexer = new instanceIdentifierLexer(CharStreams.fromString(expr.getLiteral())); + final var parser = new instanceIdentifierParser(new CommonTokenStream(lexer)); + final var listener = new CapturingErrorListener(); lexer.removeErrorListeners(); lexer.addErrorListener(listener); parser.removeErrorListeners(); parser.addErrorListener(listener); - final InstanceIdentifierContext id = parser.instanceIdentifier(); + final var id = parser.instanceIdentifier(); listener.reportError(); final int length = id.getChildCount(); @@ -158,7 +159,52 @@ abstract class InstanceIdentifierParser { } private static YangLiteralExpr parseEqStringValue(final EqQuotedStringContext expr) { - return YangLiteralExpr.of(verifyToken(getChild(expr, QuotedStringContext.class, expr.getChildCount() - 1), 1, - instanceIdentifierParser.STRING).getText()); + final var quotedString = getChild(expr, QuotedStringContext.class, expr.getChildCount() - 1); + return switch (quotedString.getChildCount()) { + case 1 -> YangLiteralExpr.empty(); + case 2 -> { + final var terminal = verifyTerminal(quotedString.getChild(0)); + final var token = terminal.getSymbol(); + final var literal = switch (token.getType()) { + case instanceIdentifierParser.DQUOT_STRING -> unescape(token.getText()); + case instanceIdentifierParser.SQUOT_STRING -> token.getText(); + default -> throw illegalShape(terminal); + }; + yield YangLiteralExpr.of(literal); + } + default -> throw illegalShape(quotedString); + }; + } + + private static String unescape(final String escaped) { + final int firstEscape = escaped.indexOf('\\'); + return firstEscape == -1 ? escaped : unescape(escaped, firstEscape); + } + + private static String unescape(final String escaped, final int firstEscape) { + // Sizing: optimize allocation for only a single escape + final int length = escaped.length(); + final var sb = new StringBuilder(length - 1).append(escaped, 0, firstEscape); + + int esc = firstEscape; + while (true) { + final var ch = escaped.charAt(esc + 1); + sb.append( + switch (ch) { + case 'n' -> '\n'; + case 't' -> '\t'; + case '"' -> '"'; + case '\\' -> '\\'; + default -> throw new VerifyException("Unexpected escaped char '" + ch + "'"); + }); + + final int start = esc + 2; + esc = escaped.indexOf('\\', start); + if (esc == -1) { + return sb.append(escaped, start, length).toString(); + } + + sb.append(escaped, start, esc); + } } }