2 * Copyright (c) 2018 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 static com.google.common.base.Verify.verifyNotNull;
11 import static java.util.Objects.requireNonNull;
13 import org.antlr.v4.runtime.tree.ParseTree;
14 import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser.ArgumentContext;
15 import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser.KeywordContext;
16 import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser.StatementContext;
17 import org.opendaylight.yangtools.yang.common.QName;
18 import org.opendaylight.yangtools.yang.common.QNameModule;
19 import org.opendaylight.yangtools.yang.common.YangConstants;
20 import org.opendaylight.yangtools.yang.common.YangVersion;
21 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
22 import org.opendaylight.yangtools.yang.parser.spi.source.DeclarationInTextSource;
23 import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule;
24 import org.opendaylight.yangtools.yang.parser.spi.source.QNameToStatementDefinition;
25 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
26 import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
27 import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter;
29 abstract class StatementContextVisitor {
30 static final class Loose extends StatementContextVisitor {
31 Loose(final String sourceName, final StatementWriter writer,
32 final QNameToStatementDefinition stmtDef, final PrefixToModule prefixes, final YangVersion yangVersion) {
33 super(sourceName, writer, stmtDef, prefixes, yangVersion);
36 Loose(final String sourceName, final StatementWriter writer, final QNameToStatementDefinition stmtDef) {
37 this(sourceName, writer, stmtDef, null, YangVersion.VERSION_1);
41 static final class Strict extends StatementContextVisitor {
42 Strict(final String sourceName, final StatementWriter writer,
43 final QNameToStatementDefinition stmtDef, final PrefixToModule prefixes, final YangVersion yangVersion) {
44 super(sourceName, writer, stmtDef, prefixes, yangVersion);
48 QName getValidStatementDefinition(final String keywordText, final StatementSourceReference ref) {
49 return SourceException.throwIfNull(super.getValidStatementDefinition(keywordText, ref), ref,
50 "%s is not a YANG statement or use of extension.", keywordText);
54 private final QNameToStatementDefinition stmtDef;
55 private final StatementWriter writer;
56 private final YangVersion yangVersion;
57 private final PrefixToModule prefixes;
58 private final String sourceName;
60 private StatementContextVisitor(final String sourceName, final StatementWriter writer,
61 final QNameToStatementDefinition stmtDef, final PrefixToModule prefixes, final YangVersion yangVersion) {
62 this.writer = requireNonNull(writer);
63 this.stmtDef = requireNonNull(stmtDef);
64 this.yangVersion = requireNonNull(yangVersion);
65 this.sourceName = sourceName;
66 this.prefixes = prefixes;
69 void visit(final StatementContext context) {
70 processStatement(0, context);
74 * Based on identifier read from source and collections of relevant prefixes and statement definitions mappings
75 * provided for actual phase, method resolves and returns valid QName for declared statement to be written.
76 * This applies to any declared statement, including unknown statements.
78 * @param prefixes collection of all relevant prefix mappings supplied for actual parsing phase
79 * @param stmtDef collection of all relevant statement definition mappings provided for actual parsing phase
80 * @param keywordText statement keyword text to parse from source
81 * @param ref Source reference
82 * @return valid QName for declared statement to be written, or null
84 QName getValidStatementDefinition(final String keywordText, final StatementSourceReference ref) {
85 final int firstColon = keywordText.indexOf(':');
86 if (firstColon == -1) {
87 final StatementDefinition def = stmtDef.get(QName.create(YangConstants.RFC6020_YIN_NAMESPACE, keywordText));
88 return def != null ? def.getStatementName() : null;
91 SourceException.throwIf(firstColon == keywordText.length() - 1
92 || keywordText.indexOf(':', firstColon + 1) != -1, ref, "Malformed statement '%s'", keywordText);
94 if (prefixes == null) {
95 // No prefixes to look up from
99 final String prefix = keywordText.substring(0, firstColon);
100 final QNameModule qNameModule = prefixes.get(prefix);
101 if (qNameModule == null) {
102 // Failed to look the namespace
106 final String localName = keywordText.substring(firstColon + 1);
107 final StatementDefinition foundStmtDef;
108 if (prefixes.isPreLinkageMap()) {
109 foundStmtDef = stmtDef.getByNamespaceAndLocalName(qNameModule.getNamespace(), localName);
111 foundStmtDef = stmtDef.get(QName.create(qNameModule, localName));
114 return foundStmtDef != null ? foundStmtDef.getStatementName() : null;
117 private void processStatement(final int myOffset, final StatementContext ctx) {
118 final String keywordTxt = verifyNotNull(ctx.getChild(KeywordContext.class, 0)).getText();
119 final StatementSourceReference ref = DeclarationInTextSource.atPosition(sourceName, ctx.getStart().getLine(),
120 ctx.getStart().getCharPositionInLine());
121 final QName def = getValidStatementDefinition(keywordTxt, ref);
126 final ArgumentContext argumentCtx = ctx.getChild(ArgumentContext.class, 0);
127 final String argument = argumentCtx == null ? null
128 : ArgumentContextUtils.stringFromStringContext(argumentCtx, yangVersion, ref);
129 writer.startStatement(myOffset, def, argument, ref);
131 if (ctx.children != null) {
133 for (ParseTree s : ctx.children) {
134 if (s instanceof StatementContext) {
135 processStatement(childOffset++, (StatementContext) s);
140 writer.endStatement(ref);