--- /dev/null
+/*
+ * Copyright (c) 2018 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.repo;
+
+import static com.google.common.base.Verify.verifyNotNull;
+import static java.util.Objects.requireNonNull;
+
+import org.antlr.v4.runtime.tree.ParseTree;
+import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser.ArgumentContext;
+import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser.KeywordContext;
+import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser.StatementContext;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.common.YangConstants;
+import org.opendaylight.yangtools.yang.common.YangVersion;
+import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
+import org.opendaylight.yangtools.yang.parser.spi.source.DeclarationInTextSource;
+import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule;
+import org.opendaylight.yangtools.yang.parser.spi.source.QNameToStatementDefinition;
+import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
+import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
+import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter;
+
+abstract class StatementContextVisitor {
+ static final class Loose extends StatementContextVisitor {
+ Loose(final String sourceName, final StatementWriter writer,
+ final QNameToStatementDefinition stmtDef, final PrefixToModule prefixes, final YangVersion yangVersion) {
+ super(sourceName, writer, stmtDef, prefixes, yangVersion);
+ }
+
+ Loose(final String sourceName, final StatementWriter writer, final QNameToStatementDefinition stmtDef) {
+ this(sourceName, writer, stmtDef, null, YangVersion.VERSION_1);
+ }
+ }
+
+ static final class Strict extends StatementContextVisitor {
+ Strict(final String sourceName, final StatementWriter writer,
+ final QNameToStatementDefinition stmtDef, final PrefixToModule prefixes, final YangVersion yangVersion) {
+ super(sourceName, writer, stmtDef, prefixes, yangVersion);
+ }
+
+ @Override
+ QName getValidStatementDefinition(final String keywordText, final StatementSourceReference ref) {
+ return SourceException.throwIfNull(super.getValidStatementDefinition(keywordText, ref), ref,
+ "%s is not a YANG statement or use of extension.", keywordText);
+ }
+ }
+
+ private final QNameToStatementDefinition stmtDef;
+ private final StatementWriter writer;
+ private final YangVersion yangVersion;
+ private final PrefixToModule prefixes;
+ private final String sourceName;
+
+ private StatementContextVisitor(final String sourceName, final StatementWriter writer,
+ final QNameToStatementDefinition stmtDef, final PrefixToModule prefixes, final YangVersion yangVersion) {
+ this.writer = requireNonNull(writer);
+ this.stmtDef = requireNonNull(stmtDef);
+ this.yangVersion = requireNonNull(yangVersion);
+ this.sourceName = sourceName;
+ this.prefixes = prefixes;
+ }
+
+ void visit(final StatementContext context) {
+ processStatement(0, context);
+ }
+
+ /**
+ * Based on identifier read from source and collections of relevant prefixes and statement definitions mappings
+ * provided for actual phase, method resolves and returns valid QName for declared statement to be written.
+ * This applies to any declared statement, including unknown statements.
+ *
+ * @param prefixes collection of all relevant prefix mappings supplied for actual parsing phase
+ * @param stmtDef collection of all relevant statement definition mappings provided for actual parsing phase
+ * @param keywordText statement keyword text to parse from source
+ * @param ref Source reference
+ * @return valid QName for declared statement to be written, or null
+ */
+ QName getValidStatementDefinition(final String keywordText, final StatementSourceReference ref) {
+ final int firstColon = keywordText.indexOf(':');
+ if (firstColon == -1) {
+ final StatementDefinition def = stmtDef.get(QName.create(YangConstants.RFC6020_YIN_NAMESPACE, keywordText));
+ return def != null ? def.getStatementName() : null;
+ }
+
+ SourceException.throwIf(firstColon == keywordText.length() - 1
+ || keywordText.indexOf(':', firstColon + 1) != -1, ref, "Malformed statement '%s'", keywordText);
+
+ if (prefixes == null) {
+ // No prefixes to look up from
+ return null;
+ }
+
+ final String prefix = keywordText.substring(0, firstColon);
+ final QNameModule qNameModule = prefixes.get(prefix);
+ if (qNameModule == null) {
+ // Failed to look the namespace
+ return null;
+ }
+
+ final String localName = keywordText.substring(firstColon + 1);
+ final StatementDefinition foundStmtDef;
+ if (prefixes.isPreLinkageMap()) {
+ foundStmtDef = stmtDef.getByNamespaceAndLocalName(qNameModule.getNamespace(), localName);
+ } else {
+ foundStmtDef = stmtDef.get(QName.create(qNameModule, localName));
+ }
+
+ return foundStmtDef != null ? foundStmtDef.getStatementName() : null;
+ }
+
+ private void processStatement(final int myOffset, final StatementContext ctx) {
+ final String keywordTxt = verifyNotNull(ctx.getChild(KeywordContext.class, 0)).getText();
+ final StatementSourceReference ref = DeclarationInTextSource.atPosition(sourceName, ctx.getStart().getLine(),
+ ctx.getStart().getCharPositionInLine());
+ final QName def = getValidStatementDefinition(keywordTxt, ref);
+ if (def == null) {
+ return;
+ }
+
+ final ArgumentContext argumentCtx = ctx.getChild(ArgumentContext.class, 0);
+ final String argument = argumentCtx == null ? null
+ : ArgumentContextUtils.stringFromStringContext(argumentCtx, yangVersion, ref);
+ writer.startStatement(myOffset, def, argument, ref);
+
+ if (ctx.children != null) {
+ int childOffset = 0;
+ for (ParseTree s : ctx.children) {
+ if (s instanceof StatementContext) {
+ processStatement(childOffset++, (StatementContext) s);
+ }
+ }
+ }
+
+ writer.endStatement(ref);
+ }
+}
+++ /dev/null
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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.repo;
-
-import static com.google.common.base.Verify.verify;
-import static com.google.common.base.Verify.verifyNotNull;
-import static java.util.Objects.requireNonNull;
-
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.Deque;
-import java.util.List;
-import org.antlr.v4.runtime.tree.ParseTreeWalker;
-import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser.ArgumentContext;
-import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser.KeywordContext;
-import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser.StatementContext;
-import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParserBaseListener;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.QNameModule;
-import org.opendaylight.yangtools.yang.common.YangConstants;
-import org.opendaylight.yangtools.yang.common.YangVersion;
-import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
-import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
-import org.opendaylight.yangtools.yang.parser.spi.source.DeclarationInTextSource;
-import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule;
-import org.opendaylight.yangtools.yang.parser.spi.source.QNameToStatementDefinition;
-import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
-import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
-import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter;
-
-final class YangStatementParserListenerImpl extends YangStatementParserBaseListener {
- private static final class Counter {
- private int value = 0;
-
- int getAndIncrement() {
- return value++;
- }
- }
-
- private final List<String> toBeSkipped = new ArrayList<>();
- private final Deque<Counter> counters = new ArrayDeque<>();
- private final String sourceName;
-
- private QNameToStatementDefinition stmtDef;
- private PrefixToModule prefixes;
- private StatementWriter writer;
- private YangVersion yangVersion;
-
- YangStatementParserListenerImpl(final String sourceName) {
- this.sourceName = sourceName;
- }
-
- @SuppressWarnings("checkstyle:hiddenField")
- void walk(final StatementWriter writer, final QNameToStatementDefinition stmtDef, final StatementContext context) {
- walk(writer, stmtDef, null, YangVersion.VERSION_1, context);
- }
-
- @SuppressWarnings("checkstyle:hiddenField")
- void walk(final StatementWriter writer, final QNameToStatementDefinition stmtDef,
- final PrefixToModule prefixes, final YangVersion yangVersion, final StatementContext context) {
- // Verify & initialize state
- verify(toBeSkipped.isEmpty());
- verify(counters.isEmpty());
- this.writer = requireNonNull(writer);
- this.stmtDef = requireNonNull(stmtDef);
- this.prefixes = prefixes;
- this.yangVersion = requireNonNull(yangVersion);
- counters.push(new Counter());
-
- try {
- ParseTreeWalker.DEFAULT.walk(this, context);
- } finally {
- // Reset out state
- this.writer = null;
- this.stmtDef = null;
- this.prefixes = null;
- this.yangVersion = null;
- toBeSkipped.clear();
- counters.clear();
- }
- }
-
- @Override
- public void enterStatement(final StatementContext ctx) {
- final StatementSourceReference ref = DeclarationInTextSource.atPosition(sourceName, ctx.getStart().getLine(),
- ctx.getStart().getCharPositionInLine());
- final String keywordTxt = verifyNotNull(ctx.getChild(KeywordContext.class, 0)).getText();
- final QName validStatementDefinition = getValidStatementDefinition(prefixes, stmtDef, keywordTxt, ref);
-
- final int childId = counters.peek().getAndIncrement();
- counters.push(new Counter());
- if (stmtDef == null || validStatementDefinition == null || !toBeSkipped.isEmpty()) {
- SourceException.throwIf(writer.getPhase() == ModelProcessingPhase.FULL_DECLARATION, ref,
- "%s is not a YANG statement or use of extension.", keywordTxt);
- toBeSkipped.add(keywordTxt);
- return;
- }
-
- final ArgumentContext argumentCtx = ctx.getChild(ArgumentContext.class, 0);
- final String argument = argumentCtx != null
- ? ArgumentContextUtils.stringFromStringContext(argumentCtx, yangVersion, ref) : null;
- writer.startStatement(childId, validStatementDefinition, argument, ref);
- }
-
- @Override
- public void exitStatement(final StatementContext ctx) {
- final StatementSourceReference ref = DeclarationInTextSource.atPosition(
- sourceName, ctx.getStart().getLine(), ctx.getStart().getCharPositionInLine());
-
- final KeywordContext keyword = ctx.getChild(KeywordContext.class, 0);
- final String statementName = keyword.getText();
- if (stmtDef != null && getValidStatementDefinition(prefixes, stmtDef, statementName, ref) != null
- && toBeSkipped.isEmpty()) {
- writer.endStatement(ref);
- }
-
- // No-op if the statement is not on the list
- toBeSkipped.remove(statementName);
- counters.pop();
- }
-
- /**
- * Based on identifier read from source and collections of relevant prefixes and statement definitions mappings
- * provided for actual phase, method resolves and returns valid QName for declared statement to be written.
- * This applies to any declared statement, including unknown statements.
- *
- * @param prefixes collection of all relevant prefix mappings supplied for actual parsing phase
- * @param stmtDef collection of all relevant statement definition mappings provided for actual parsing phase
- * @param keywordText statement keyword text to parse from source
- * @param ref Source reference
- * @return valid QName for declared statement to be written, or null
- */
- private static QName getValidStatementDefinition(final PrefixToModule prefixes,
- final QNameToStatementDefinition stmtDef, final String keywordText, final StatementSourceReference ref) {
- final int firstColon = keywordText.indexOf(':');
- if (firstColon == -1) {
- final StatementDefinition statementDefinition = stmtDef.get(
- QName.create(YangConstants.RFC6020_YIN_NAMESPACE, keywordText));
- return statementDefinition != null ? statementDefinition.getStatementName() : null;
- }
-
- SourceException.throwIf(firstColon == keywordText.length() - 1
- || keywordText.indexOf(':', firstColon + 1) != -1, ref, "Malformed statement '%s'", keywordText);
-
- if (prefixes == null) {
- // No prefixes to look up from
- return null;
- }
-
- final String prefix = keywordText.substring(0, firstColon);
- final QNameModule qNameModule = prefixes.get(prefix);
- if (qNameModule == null) {
- // Failed to look the namespace
- return null;
- }
-
- final String localName = keywordText.substring(firstColon + 1);
- final StatementDefinition foundStmtDef;
- if (prefixes.isPreLinkageMap()) {
- foundStmtDef = stmtDef.getByNamespaceAndLocalName(qNameModule.getNamespace(), localName);
- } else {
- foundStmtDef = stmtDef.get(QName.create(qNameModule, localName));
- }
-
- return foundStmtDef != null ? foundStmtDef.getStatementName() : null;
- }
-}
}
};
- private final YangStatementParserListenerImpl yangStatementModelParser;
private final SourceIdentifier identifier;
private final StatementContext context;
+ private final String sourceName;
- private YangStatementStreamSource(final SourceIdentifier identifier, final YangStatementParserListenerImpl parser,
- final StatementContext context) {
+ private YangStatementStreamSource(final SourceIdentifier identifier, final StatementContext context,
+ final String sourceName) {
this.identifier = Preconditions.checkNotNull(identifier);
- this.yangStatementModelParser = Preconditions.checkNotNull(parser);
this.context = Preconditions.checkNotNull(context);
+ this.sourceName = sourceName;
}
/**
context = parseYangSource(source.getIdentifier(), stream);
}
- final String sourceName = source.getSymbolicName().orElse(null);
- final YangStatementParserListenerImpl parser = new YangStatementParserListenerImpl(sourceName);
- return new YangStatementStreamSource(source.getIdentifier(), parser, context);
+ return new YangStatementStreamSource(source.getIdentifier(), context, source.getSymbolicName().orElse(null));
}
/**
public static YangStatementStreamSource create(final SourceIdentifier identifier, final StatementContext context,
final String symbolicName) {
- return new YangStatementStreamSource(identifier, new YangStatementParserListenerImpl(symbolicName), context);
+ return new YangStatementStreamSource(identifier, context, symbolicName);
}
@Override
public void writePreLinkage(final StatementWriter writer, final QNameToStatementDefinition stmtDef) {
- yangStatementModelParser.walk(writer, stmtDef, context);
+ new StatementContextVisitor.Loose(sourceName, writer, stmtDef).visit(context);
}
@Override
@Override
public void writeLinkage(final StatementWriter writer, final QNameToStatementDefinition stmtDef,
final PrefixToModule preLinkagePrefixes, final YangVersion yangVersion) {
- yangStatementModelParser.walk(writer, stmtDef, preLinkagePrefixes, yangVersion, context);
+ new StatementContextVisitor.Loose(sourceName, writer, stmtDef, preLinkagePrefixes, yangVersion).visit(context);
}
@Override
@Override
public void writeLinkageAndStatementDefinitions(final StatementWriter writer,
final QNameToStatementDefinition stmtDef, final PrefixToModule prefixes, final YangVersion yangVersion) {
- yangStatementModelParser.walk(writer, stmtDef, prefixes, yangVersion, context);
+ new StatementContextVisitor.Loose(sourceName, writer, stmtDef, prefixes, yangVersion).visit(context);
}
@Override
@Override
public void writeFull(final StatementWriter writer, final QNameToStatementDefinition stmtDef,
final PrefixToModule prefixes, final YangVersion yangVersion) {
- yangStatementModelParser.walk(writer, stmtDef, prefixes, yangVersion, context);
+ new StatementContextVisitor.Strict(sourceName, writer, stmtDef, prefixes, yangVersion).visit(context);
}
@Override