2 * Copyright (c) 2017 Pantheon Technologies, s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.yangtools.yang.parser.rfc7950.repo;
10 import com.google.common.annotations.Beta;
11 import com.google.common.base.MoreObjects;
12 import com.google.common.base.Preconditions;
13 import com.google.common.collect.ImmutableList;
14 import java.io.IOException;
15 import java.io.InputStream;
16 import org.antlr.v4.runtime.CharStreams;
17 import org.antlr.v4.runtime.CommonTokenStream;
18 import org.antlr.v4.runtime.ParserRuleContext;
19 import org.antlr.v4.runtime.tree.ErrorNode;
20 import org.antlr.v4.runtime.tree.ParseTreeListener;
21 import org.antlr.v4.runtime.tree.ParseTreeWalker;
22 import org.antlr.v4.runtime.tree.TerminalNode;
23 import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementLexer;
24 import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser;
25 import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser.StatementContext;
26 import org.opendaylight.yangtools.yang.common.YangVersion;
27 import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
28 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
29 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
30 import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule;
31 import org.opendaylight.yangtools.yang.parser.spi.source.QNameToStatementDefinition;
32 import org.opendaylight.yangtools.yang.parser.spi.source.StatementStreamSource;
33 import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter;
36 * This class represents implementation of StatementStreamSource in order to emit YANG statements using supplied
39 * @author Robert Varga
42 public final class YangStatementStreamSource implements StatementStreamSource {
43 private static final ParseTreeListener MAKE_IMMUTABLE_LISTENER = new ParseTreeListener() {
45 public void enterEveryRule(final ParserRuleContext ctx) {
50 public void exitEveryRule(final ParserRuleContext ctx) {
51 ctx.children = ctx.children == null ? ImmutableList.of() : ImmutableList.copyOf(ctx.children);
55 public void visitTerminal(final TerminalNode node) {
60 public void visitErrorNode(final ErrorNode node) {
65 private final YangStatementParserListenerImpl yangStatementModelParser;
66 private final SourceIdentifier identifier;
67 private final StatementContext context;
69 private YangStatementStreamSource(final SourceIdentifier identifier, final YangStatementParserListenerImpl parser,
70 final StatementContext context) {
71 this.identifier = Preconditions.checkNotNull(identifier);
72 this.yangStatementModelParser = Preconditions.checkNotNull(parser);
73 this.context = Preconditions.checkNotNull(context);
76 public static YangStatementStreamSource create(final YangTextSchemaSource source) throws IOException,
77 YangSyntaxErrorException {
78 final StatementContext context;
79 try (InputStream stream = source.openStream()) {
80 context = parseYangSource(source.getIdentifier(), stream);
83 final String sourceName = source.getSymbolicName().orElse(null);
84 final YangStatementParserListenerImpl parser = new YangStatementParserListenerImpl(sourceName);
85 return new YangStatementStreamSource(source.getIdentifier(), parser, context);
88 public static YangStatementStreamSource create(final SourceIdentifier identifier, final StatementContext context,
89 final String symbolicName) {
90 return new YangStatementStreamSource(identifier, new YangStatementParserListenerImpl(symbolicName), context);
94 public void writePreLinkage(final StatementWriter writer, final QNameToStatementDefinition stmtDef) {
95 yangStatementModelParser.setAttributes(writer, stmtDef);
96 ParseTreeWalker.DEFAULT.walk(yangStatementModelParser, context);
100 public void writeLinkage(final StatementWriter writer, final QNameToStatementDefinition stmtDef,
101 final PrefixToModule preLinkagePrefixes) {
102 writeLinkage(writer, stmtDef, preLinkagePrefixes, YangVersion.VERSION_1);
106 public void writeLinkage(final StatementWriter writer, final QNameToStatementDefinition stmtDef,
107 final PrefixToModule preLinkagePrefixes, final YangVersion yangVersion) {
108 yangStatementModelParser.setAttributes(writer, stmtDef, preLinkagePrefixes, yangVersion);
109 ParseTreeWalker.DEFAULT.walk(yangStatementModelParser, context);
113 public void writeLinkageAndStatementDefinitions(final StatementWriter writer,
114 final QNameToStatementDefinition stmtDef, final PrefixToModule prefixes) {
115 writeLinkageAndStatementDefinitions(writer, stmtDef, prefixes, YangVersion.VERSION_1);
119 public void writeLinkageAndStatementDefinitions(final StatementWriter writer,
120 final QNameToStatementDefinition stmtDef, final PrefixToModule prefixes, final YangVersion yangVersion) {
121 yangStatementModelParser.setAttributes(writer, stmtDef, prefixes, yangVersion);
122 ParseTreeWalker.DEFAULT.walk(yangStatementModelParser, context);
126 public void writeFull(final StatementWriter writer, final QNameToStatementDefinition stmtDef,
127 final PrefixToModule prefixes) {
128 writeFull(writer, stmtDef, prefixes, YangVersion.VERSION_1);
132 public void writeFull(final StatementWriter writer, final QNameToStatementDefinition stmtDef,
133 final PrefixToModule prefixes, final YangVersion yangVersion) {
134 yangStatementModelParser.setAttributes(writer, stmtDef, prefixes, yangVersion);
135 ParseTreeWalker.DEFAULT.walk(yangStatementModelParser, context);
139 public SourceIdentifier getIdentifier() {
143 public ParserRuleContext getYangAST() {
147 private static StatementContext parseYangSource(final SourceIdentifier source, final InputStream stream)
148 throws IOException, YangSyntaxErrorException {
149 final YangStatementLexer lexer = new YangStatementLexer(CharStreams.fromStream(stream));
150 final CommonTokenStream tokens = new CommonTokenStream(lexer);
151 final YangStatementParser parser = new YangStatementParser(tokens);
152 //disconnect from console error output
153 parser.removeErrorListeners();
155 final YangErrorListener errorListener = new YangErrorListener(source);
156 parser.addErrorListener(errorListener);
158 final StatementContext result = parser.statement();
159 errorListener.validate();
161 // Walk the resulting tree and replace each children with an immutable list, lowering memory requirements
162 // and making sure the resulting tree will not get accidentally modified. An alternative would be to use
163 // org.antlr.v4.runtime.Parser.TrimToSizeListener, but that does not make the tree immutable.
164 ParseTreeWalker.DEFAULT.walk(MAKE_IMMUTABLE_LISTENER, result);
170 public String toString() {
171 return MoreObjects.toStringHelper(this).add("identifier", getIdentifier()).toString();