From dd9516f60597882aea5d987aaad9760425796263 Mon Sep 17 00:00:00 2001 From: Samuel Schneider Date: Fri, 6 May 2022 11:58:29 +0200 Subject: [PATCH] Refactor IfFeaturePredicateVisitor Refactor IfFeaturePredicateVisitor to work purely on IfFeatureExpressionParser without use of ANTLR's visitors. JIRA: YANGTOOLS-1396 Change-Id: I4ff988caa34a50da843fd35b8918e7b502bdf770 Signed-off-by: Samuel Schneider Signed-off-by: Robert Varga --- parser/yang-parser-rfc7950/pom.xml | 3 +- .../if_feature/IfFeaturePredicateParser.java | 103 ++++++++++++++++++ .../if_feature/IfFeaturePredicateVisitor.java | 90 --------------- .../IfFeatureStatementRFC7950Support.java | 2 +- 4 files changed, 105 insertions(+), 93 deletions(-) create mode 100644 parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/if_feature/IfFeaturePredicateParser.java delete mode 100644 parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/if_feature/IfFeaturePredicateVisitor.java diff --git a/parser/yang-parser-rfc7950/pom.xml b/parser/yang-parser-rfc7950/pom.xml index 7daa3fde36..7653f4bd48 100644 --- a/parser/yang-parser-rfc7950/pom.xml +++ b/parser/yang-parser-rfc7950/pom.xml @@ -104,8 +104,7 @@ - - true + false false diff --git a/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/if_feature/IfFeaturePredicateParser.java b/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/if_feature/IfFeaturePredicateParser.java new file mode 100644 index 0000000000..f9d0392458 --- /dev/null +++ b/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/if_feature/IfFeaturePredicateParser.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2017, 2022 PANTHEON.tech, s.r.o. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.if_feature; + +import static java.util.Objects.requireNonNull; + +import com.google.common.collect.ImmutableSet; +import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.TerminalNode; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.opendaylight.yangtools.yang.model.api.stmt.IfFeatureExpr; +import org.opendaylight.yangtools.yang.parser.antlr.IfFeatureExpressionLexer; +import org.opendaylight.yangtools.yang.parser.antlr.IfFeatureExpressionParser; +import org.opendaylight.yangtools.yang.parser.antlr.IfFeatureExpressionParser.Identifier_ref_argContext; +import org.opendaylight.yangtools.yang.parser.antlr.IfFeatureExpressionParser.If_feature_exprContext; +import org.opendaylight.yangtools.yang.parser.antlr.IfFeatureExpressionParser.If_feature_factorContext; +import org.opendaylight.yangtools.yang.parser.antlr.IfFeatureExpressionParser.If_feature_termContext; +import org.opendaylight.yangtools.yang.parser.rfc7950.antlr.SourceExceptionParser; +import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext; +import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils; +import org.opendaylight.yangtools.yang.parser.spi.source.SourceException; + +@NonNullByDefault +final class IfFeaturePredicateParser { + private final StmtContext stmt; + + private IfFeaturePredicateParser(final StmtContext stmt) { + this.stmt = requireNonNull(stmt); + } + + static IfFeatureExpr parseIfFeatureExpression(final StmtContext stmt, final String value) { + final var lexer = new IfFeatureExpressionLexer(CharStreams.fromString(value)); + final var parser = new IfFeatureExpressionParser(new CommonTokenStream(lexer)); + final var ifFeatureExprContext = + SourceExceptionParser.parse(lexer, parser, parser::if_feature_expr, stmt.sourceReference()); + return new IfFeaturePredicateParser(stmt).parseIfFeatureExpr(ifFeatureExprContext); + } + + private IfFeatureExpr parseIfFeatureExpr(final If_feature_exprContext expr) { + final int count = verifyExprOrTermChildren(expr); + final var expressions = ImmutableSet.builderWithExpectedSize(count / 4 + 1); + for (int i = 0; i < count; i += 4) { + expressions.add(parseIfFeatureTerm(getChild(expr, i, If_feature_termContext.class))); + } + return IfFeatureExpr.or(expressions.build()); + } + + private IfFeatureExpr parseIfFeatureTerm(final If_feature_termContext term) { + final int count = verifyExprOrTermChildren(term); + final var expressions = ImmutableSet.builderWithExpectedSize(count / 4 + 1); + expressions.add(parseIfFeatureFactor(getChild(term, 0, If_feature_factorContext.class))); + + for (int i = 4; i < count; i += 4) { + expressions.add(parseIfFeatureTerm(getChild(term, i, If_feature_termContext.class))); + } + return IfFeatureExpr.and(expressions.build()); + } + + private IfFeatureExpr parseIfFeatureFactor(final If_feature_factorContext factor) { + final var first = factor.getChild(0); + if (first instanceof Identifier_ref_argContext refArg) { + return IfFeatureExpr.isPresent(StmtContextUtils.parseNodeIdentifier(stmt, refArg.getText())); + } else if (first instanceof TerminalNode terminal) { + return switch (terminal.getSymbol().getType()) { + case IfFeatureExpressionParser.LP -> + parseIfFeatureExpr(factor.getChild(If_feature_exprContext.class, 0)); + case IfFeatureExpressionParser.NOT -> + parseIfFeatureFactor(getChild(factor, 2, If_feature_factorContext.class)).negate(); + default -> throw new SourceException(stmt, "Unexpected terminal %s in sub-expression at %s", + terminal.getText(), factor.getSourceInterval()); + }; + } else { + throw new SourceException(stmt, "Unexpected error: sub-expression at %s has context %s. Please file a bug " + + "report with the corresponding model attached.", factor.getSourceInterval(), first); + } + } + + private int verifyExprOrTermChildren(ParserRuleContext context) { + final int count = context.getChildCount(); + if (count % 4 != 1) { + throw new SourceException(stmt, "Unexpected error: sub-expression at %s has %s children. Please file a bug " + + "report with the corresponding model attached.", context.getSourceInterval(), count); + } + return count; + } + + private T getChild(final ParserRuleContext parent, final int offset, final Class clazz) { + final var child = parent.getChild(offset); + if (!clazz.isInstance(child)) { + throw new SourceException(stmt, "Unexpected error: sub-expression at %s has child %s at offset %s when " + + "expecting %s. Please file a bug report with the corresponding model attached.", + parent.getSourceInterval(), child, offset, clazz); + } + return clazz.cast(child); + } +} diff --git a/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/if_feature/IfFeaturePredicateVisitor.java b/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/if_feature/IfFeaturePredicateVisitor.java deleted file mode 100644 index 53c6631a6c..0000000000 --- a/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/if_feature/IfFeaturePredicateVisitor.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2017 Pantheon Technologies, s.r.o. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.if_feature; - -import static java.util.Objects.requireNonNull; - -import com.google.common.collect.ImmutableSet; -import java.util.ArrayList; -import java.util.List; -import org.antlr.v4.runtime.CharStreams; -import org.antlr.v4.runtime.CommonTokenStream; -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; -import org.opendaylight.yangtools.yang.model.api.stmt.IfFeatureExpr; -import org.opendaylight.yangtools.yang.parser.antlr.IfFeatureExpressionLexer; -import org.opendaylight.yangtools.yang.parser.antlr.IfFeatureExpressionParser; -import org.opendaylight.yangtools.yang.parser.antlr.IfFeatureExpressionParser.Identifier_ref_argContext; -import org.opendaylight.yangtools.yang.parser.antlr.IfFeatureExpressionParser.If_feature_exprContext; -import org.opendaylight.yangtools.yang.parser.antlr.IfFeatureExpressionParser.If_feature_factorContext; -import org.opendaylight.yangtools.yang.parser.antlr.IfFeatureExpressionParser.If_feature_termContext; -import org.opendaylight.yangtools.yang.parser.antlr.IfFeatureExpressionParserBaseVisitor; -import org.opendaylight.yangtools.yang.parser.rfc7950.antlr.SourceExceptionParser; -import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext; -import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils; -import org.opendaylight.yangtools.yang.parser.spi.source.SourceException; - -// FIXME: YANGTOOLS-1396: refactor on top of vanilla IfFeatureExpressionParser -@NonNullByDefault -final class IfFeaturePredicateVisitor extends IfFeatureExpressionParserBaseVisitor { - private final StmtContext stmtCtx; - - private IfFeaturePredicateVisitor(final StmtContext ctx) { - this.stmtCtx = requireNonNull(ctx); - } - - static IfFeatureExpr parseIfFeatureExpression(final StmtContext ctx, final String value) { - final IfFeatureExpressionLexer lexer = new IfFeatureExpressionLexer(CharStreams.fromString(value)); - final IfFeatureExpressionParser parser = new IfFeatureExpressionParser(new CommonTokenStream(lexer)); - final IfFeatureExpr ret = new IfFeaturePredicateVisitor(ctx).visit(SourceExceptionParser.parse(lexer, parser, - parser::if_feature_expr, ctx.sourceReference())); - - return ret; - } - - @Override - public IfFeatureExpr visitIf_feature_expr(final @Nullable If_feature_exprContext ctx) { - return IfFeatureExpr.or(ctx.if_feature_term().stream() - .map(this::visitIf_feature_term) - .collect(ImmutableSet.toImmutableSet())); - } - - @Override - public IfFeatureExpr visitIf_feature_term(final @Nullable If_feature_termContext ctx) { - final IfFeatureExpr factor = visitIf_feature_factor(ctx.if_feature_factor()); - final List terms = ctx.if_feature_term(); - if (terms == null || terms.isEmpty()) { - return factor; - } - final List factors = new ArrayList<>(terms.size() + 1); - factors.add(factor); - for (If_feature_termContext term : terms) { - factors.add(visitIf_feature_term(term)); - } - return IfFeatureExpr.and(ImmutableSet.copyOf(factors)); - } - - @Override - public IfFeatureExpr visitIf_feature_factor(final @Nullable If_feature_factorContext ctx) { - if (ctx.if_feature_expr() != null) { - return visitIf_feature_expr(ctx.if_feature_expr()); - } else if (ctx.if_feature_factor() != null) { - return visitIf_feature_factor(ctx.if_feature_factor()).negate(); - } else if (ctx.identifier_ref_arg() != null) { - return visitIdentifier_ref_arg(ctx.identifier_ref_arg()); - } - - throw new SourceException("Unexpected grammar context during parsing of IfFeature expression. " - + "Most probably IfFeature grammar has been changed.", stmtCtx); - } - - @Override - public IfFeatureExpr visitIdentifier_ref_arg(final @Nullable Identifier_ref_argContext ctx) { - return IfFeatureExpr.isPresent(StmtContextUtils.parseNodeIdentifier(stmtCtx, ctx.getText())); - } -} diff --git a/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/if_feature/IfFeatureStatementRFC7950Support.java b/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/if_feature/IfFeatureStatementRFC7950Support.java index ee94c7300f..1f1460a2f7 100644 --- a/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/if_feature/IfFeatureStatementRFC7950Support.java +++ b/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/if_feature/IfFeatureStatementRFC7950Support.java @@ -18,6 +18,6 @@ public final class IfFeatureStatementRFC7950Support extends AbstractIfFeatureSta @Override public IfFeatureExpr parseArgumentValue(final StmtContext ctx, final String value) { - return IfFeaturePredicateVisitor.parseIfFeatureExpression(ctx, value); + return IfFeaturePredicateParser.parseIfFeatureExpression(ctx, value); } } -- 2.36.6