2 * Copyright (c) 2015 Cisco Systems, Inc. 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.base.Verify;
11 import java.util.ArrayDeque;
12 import java.util.ArrayList;
13 import java.util.Deque;
14 import java.util.List;
15 import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser.ArgumentContext;
16 import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser.KeywordContext;
17 import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser.StatementContext;
18 import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParserBaseListener;
19 import org.opendaylight.yangtools.yang.common.QName;
20 import org.opendaylight.yangtools.yang.common.QNameModule;
21 import org.opendaylight.yangtools.yang.common.YangConstants;
22 import org.opendaylight.yangtools.yang.common.YangVersion;
23 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
24 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
25 import org.opendaylight.yangtools.yang.parser.spi.source.DeclarationInTextSource;
26 import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule;
27 import org.opendaylight.yangtools.yang.parser.spi.source.QNameToStatementDefinition;
28 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
29 import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
30 import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter;
32 final class YangStatementParserListenerImpl extends YangStatementParserBaseListener {
33 private static final class Counter {
34 private int value = 0;
36 int getAndIncrement() {
41 private final List<String> toBeSkipped = new ArrayList<>();
42 private final Deque<Counter> counters = new ArrayDeque<>();
43 private final String sourceName;
44 private QNameToStatementDefinition stmtDef;
45 private PrefixToModule prefixes;
46 private StatementWriter writer;
47 private YangVersion yangVersion;
49 YangStatementParserListenerImpl(final String sourceName) {
50 this.sourceName = sourceName;
53 public void setAttributes(final StatementWriter writer, final QNameToStatementDefinition stmtDef) {
55 this.stmtDef = stmtDef;
59 public void setAttributes(final StatementWriter writer, final QNameToStatementDefinition stmtDef,
60 final PrefixToModule prefixes) {
62 this.stmtDef = stmtDef;
63 this.prefixes = prefixes;
67 public void setAttributes(final StatementWriter writer, final QNameToStatementDefinition stmtDef,
68 final PrefixToModule prefixes, final YangVersion yangVersion) {
69 this.yangVersion = yangVersion;
70 setAttributes(writer, stmtDef, prefixes);
73 private void initCounters() {
75 counters.push(new Counter());
79 public void enterStatement(final StatementContext ctx) {
80 final StatementSourceReference ref = DeclarationInTextSource.atPosition(sourceName, ctx.getStart().getLine(),
81 ctx.getStart().getCharPositionInLine());
82 final String keywordTxt = Verify.verifyNotNull(ctx.getChild(KeywordContext.class, 0)).getText();
83 final QName validStatementDefinition = getValidStatementDefinition(prefixes, stmtDef, keywordTxt, ref);
85 final int childId = counters.peek().getAndIncrement();
86 counters.push(new Counter());
87 if (stmtDef == null || validStatementDefinition == null || !toBeSkipped.isEmpty()) {
88 SourceException.throwIf(writer.getPhase() == ModelProcessingPhase.FULL_DECLARATION, ref,
89 "%s is not a YANG statement or use of extension.", keywordTxt);
90 toBeSkipped.add(keywordTxt);
94 final ArgumentContext argumentCtx = ctx.getChild(ArgumentContext.class, 0);
95 final String argument = argumentCtx != null
96 ? ArgumentContextUtils.stringFromStringContext(argumentCtx, yangVersion, ref) : null;
97 writer.startStatement(childId, validStatementDefinition, argument, ref);
101 public void exitStatement(final StatementContext ctx) {
102 final StatementSourceReference ref = DeclarationInTextSource.atPosition(
103 sourceName, ctx.getStart().getLine(), ctx.getStart().getCharPositionInLine());
105 final KeywordContext keyword = ctx.getChild(KeywordContext.class, 0);
106 final String statementName = keyword.getText();
107 if (stmtDef != null && getValidStatementDefinition(prefixes, stmtDef, statementName, ref) != null
108 && toBeSkipped.isEmpty()) {
109 writer.endStatement(ref);
112 // No-op if the statement is not on the list
113 toBeSkipped.remove(statementName);
118 * Based on identifier read from source and collections of relevant prefixes and statement definitions mappings
119 * provided for actual phase, method resolves and returns valid QName for declared statement to be written.
120 * This applies to any declared statement, including unknown statements.
122 * @param prefixes collection of all relevant prefix mappings supplied for actual parsing phase
123 * @param stmtDef collection of all relevant statement definition mappings provided for actual parsing phase
124 * @param keywordText statement keyword text to parse from source
125 * @param ref Source reference
126 * @return valid QName for declared statement to be written, or null
128 private static QName getValidStatementDefinition(final PrefixToModule prefixes,
129 final QNameToStatementDefinition stmtDef, final String keywordText, final StatementSourceReference ref) {
130 final int firstColon = keywordText.indexOf(':');
131 if (firstColon == -1) {
132 final StatementDefinition statementDefinition = stmtDef.get(
133 QName.create(YangConstants.RFC6020_YIN_NAMESPACE, keywordText));
134 return statementDefinition != null ? statementDefinition.getStatementName() : null;
137 SourceException.throwIf(firstColon == keywordText.length() - 1
138 || keywordText.indexOf(':', firstColon + 1) != -1, ref, "Malformed statement '%s'", keywordText);
140 if (prefixes == null) {
141 // No prefixes to look up from
145 final String prefix = keywordText.substring(0, firstColon);
146 final QNameModule qNameModule = prefixes.get(prefix);
147 if (qNameModule == null) {
148 // Failed to look the namespace
152 final String localName = keywordText.substring(firstColon + 1);
153 final StatementDefinition foundStmtDef;
154 if (prefixes.isPreLinkageMap()) {
155 foundStmtDef = stmtDef.getByNamespaceAndLocalName(qNameModule.getNamespace(), localName);
157 foundStmtDef = stmtDef.get(QName.create(qNameModule, localName));
160 return foundStmtDef != null ? foundStmtDef.getStatementName() : null;