Add an explicit intermediate YANG representation
[yangtools.git] / yang / yang-parser-rfc7950 / src / main / java / org / opendaylight / yangtools / yang / parser / rfc7950 / repo / YangStatementStreamSource.java
index 98d3aac98d6112264f990566e15c613671e36bfd..77e46b8e451ee0ed818601b39715ce537f643c51 100644 (file)
@@ -7,21 +7,13 @@
  */
 package org.opendaylight.yangtools.yang.parser.rfc7950.repo;
 
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Verify.verifyNotNull;
 import static java.util.Objects.requireNonNull;
 
 import com.google.common.annotations.Beta;
-import com.google.common.collect.ImmutableList;
 import java.io.IOException;
 import java.io.InputStream;
 import org.antlr.v4.runtime.CharStreams;
 import org.antlr.v4.runtime.CommonTokenStream;
-import org.antlr.v4.runtime.ParserRuleContext;
-import org.antlr.v4.runtime.tree.ErrorNode;
-import org.antlr.v4.runtime.tree.ParseTreeListener;
-import org.antlr.v4.runtime.tree.ParseTreeWalker;
-import org.antlr.v4.runtime.tree.TerminalNode;
 import org.opendaylight.yangtools.concepts.AbstractIdentifiable;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
@@ -33,9 +25,9 @@ import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
 import org.opendaylight.yangtools.yang.parser.antlr.YangStatementLexer;
 import org.opendaylight.yangtools.yang.parser.antlr.YangStatementParser;
 import org.opendaylight.yangtools.yang.parser.antlr.YangStatementParser.FileContext;
-import org.opendaylight.yangtools.yang.parser.antlr.YangStatementParser.KeywordContext;
-import org.opendaylight.yangtools.yang.parser.antlr.YangStatementParser.StatementContext;
 import org.opendaylight.yangtools.yang.parser.rfc7950.antlr.CompactYangStatementLexer;
+import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRKeyword;
+import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRStatement;
 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;
@@ -52,35 +44,13 @@ import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter;
 @Beta
 public final class YangStatementStreamSource extends AbstractIdentifiable<SourceIdentifier>
         implements StatementStreamSource {
-    private static final ParseTreeListener MAKE_IMMUTABLE_LISTENER = new ParseTreeListener() {
-        @Override
-        public void enterEveryRule(final ParserRuleContext ctx) {
-            // No-op
-        }
-
-        @Override
-        public void exitEveryRule(final ParserRuleContext ctx) {
-            ctx.children = ctx.children == null ? ImmutableList.of() : ImmutableList.copyOf(ctx.children);
-        }
-
-        @Override
-        public void visitTerminal(final TerminalNode node) {
-            // No-op
-        }
-
-        @Override
-        public void visitErrorNode(final ErrorNode node) {
-            // No-op
-        }
-    };
-
-    private final StatementContext context;
+    private final IRStatement rootStatement;
     private final String sourceName;
 
-    private YangStatementStreamSource(final SourceIdentifier identifier,  final StatementContext context,
+    private YangStatementStreamSource(final SourceIdentifier identifier,  final IRStatement rootStatement,
             final String sourceName) {
         super(identifier);
-        this.context = requireNonNull(context);
+        this.rootStatement = requireNonNull(rootStatement);
         this.sourceName = sourceName;
     }
 
@@ -94,12 +64,13 @@ public final class YangStatementStreamSource extends AbstractIdentifiable<Source
      */
     public static YangStatementStreamSource create(final YangTextSchemaSource source) throws IOException,
             YangSyntaxErrorException {
-        final StatementContext context;
+        final IRStatement rootStatement;
         try (InputStream stream = source.openStream()) {
-            context = parseYangSource(source.getIdentifier(), stream);
+            rootStatement = parseYangSource(source.getIdentifier(), stream);
         }
 
-        return new YangStatementStreamSource(source.getIdentifier(), context, source.getSymbolicName().orElse(null));
+        return new YangStatementStreamSource(source.getIdentifier(), rootStatement,
+            source.getSymbolicName().orElse(null));
     }
 
     /**
@@ -109,20 +80,17 @@ public final class YangStatementStreamSource extends AbstractIdentifiable<Source
      * @return A new {@link YangStatementStreamSource}
      */
     public static YangStatementStreamSource create(final ASTSchemaSource source) {
-        final ParserRuleContext ast = source.getAST();
-        checkArgument(ast instanceof StatementContext,
-                "Unsupported context class %s for source %s", ast.getClass(), source.getIdentifier());
-        return create(source.getIdentifier(), (StatementContext) ast, source.getSymbolicName().orElse(null));
+        return create(source.getIdentifier(), source.getRootStatement(), source.getSymbolicName().orElse(null));
     }
 
-    public static YangStatementStreamSource create(final SourceIdentifier identifier, final StatementContext context,
-        final String symbolicName) {
-        return new YangStatementStreamSource(identifier, context, symbolicName);
+    public static YangStatementStreamSource create(final SourceIdentifier identifier, final IRStatement rootStatement,
+            final String symbolicName) {
+        return new YangStatementStreamSource(identifier, rootStatement, symbolicName);
     }
 
     @Override
     public void writePreLinkage(final StatementWriter writer, final QNameToStatementDefinition stmtDef) {
-        new StatementContextVisitor(sourceName, writer, stmtDef, null, YangVersion.VERSION_1).visit(context);
+        new StatementContextVisitor(sourceName, writer, stmtDef, null, YangVersion.VERSION_1).visit(rootStatement);
     }
 
     @Override
@@ -133,13 +101,13 @@ public final class YangStatementStreamSource extends AbstractIdentifiable<Source
             StatementDefinition resolveStatement(final QNameModule module, final String localName) {
                 return stmtDef.getByNamespaceAndLocalName(module.getNamespace(), localName);
             }
-        }.visit(context);
+        }.visit(rootStatement);
     }
 
     @Override
     public void writeLinkageAndStatementDefinitions(final StatementWriter writer,
             final QNameToStatementDefinition stmtDef, final PrefixToModule prefixes, final YangVersion yangVersion) {
-        new StatementContextVisitor(sourceName, writer, stmtDef, prefixes, yangVersion).visit(context);
+        new StatementContextVisitor(sourceName, writer, stmtDef, prefixes, yangVersion).visit(rootStatement);
     }
 
     @Override
@@ -147,22 +115,22 @@ public final class YangStatementStreamSource extends AbstractIdentifiable<Source
             final PrefixToModule prefixes, final YangVersion yangVersion) {
         new StatementContextVisitor(sourceName, writer, stmtDef, prefixes, yangVersion) {
             @Override
-            QName getValidStatementDefinition(final KeywordContext keyword, final StatementSourceReference ref) {
+            QName getValidStatementDefinition(final IRKeyword keyword, final StatementSourceReference ref) {
                 final QName ret = super.getValidStatementDefinition(keyword, ref);
                 if (ret == null) {
                     throw new SourceException(ref, "%s is not a YANG statement or use of extension.",
-                        keyword.getText());
+                        keyword.asStringDeclaration());
                 }
                 return ret;
             }
-        }.visit(context);
+        }.visit(rootStatement);
     }
 
-    StatementContext statementContext() {
-        return context;
+    IRStatement rootStatement() {
+        return rootStatement;
     }
 
-    private static StatementContext parseYangSource(final SourceIdentifier source, final InputStream stream)
+    private static IRStatement parseYangSource(final SourceIdentifier source, final InputStream stream)
             throws IOException, YangSyntaxErrorException {
         final YangStatementLexer lexer = new CompactYangStatementLexer(CharStreams.fromStream(stream));
         final YangStatementParser parser = new YangStatementParser(new CommonTokenStream(lexer));
@@ -176,12 +144,6 @@ public final class YangStatementStreamSource extends AbstractIdentifiable<Source
 
         final FileContext result = parser.file();
         errorListener.validate();
-
-        // Walk the resulting tree and replace each children with an immutable list, lowering memory requirements
-        // and making sure the resulting tree will not get accidentally modified. An alternative would be to use
-        // org.antlr.v4.runtime.Parser.TrimToSizeListener, but that does not make the tree immutable.
-        ParseTreeWalker.DEFAULT.walk(MAKE_IMMUTABLE_LISTENER, result);
-
-        return verifyNotNull(result.statement());
+        return IRStatement.forContext(result.statement());
     }
 }