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 java.util.Objects.requireNonNull;
12 import org.opendaylight.yangtools.yang.common.QName;
13 import org.opendaylight.yangtools.yang.common.QNameModule;
14 import org.opendaylight.yangtools.yang.common.YangConstants;
15 import org.opendaylight.yangtools.yang.common.YangVersion;
16 import org.opendaylight.yangtools.yang.ir.IRArgument;
17 import org.opendaylight.yangtools.yang.ir.IRKeyword;
18 import org.opendaylight.yangtools.yang.ir.IRKeyword.Qualified;
19 import org.opendaylight.yangtools.yang.ir.IRStatement;
20 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
21 import org.opendaylight.yangtools.yang.model.api.meta.StatementSourceReference;
22 import org.opendaylight.yangtools.yang.model.spi.meta.StatementDeclarations;
23 import org.opendaylight.yangtools.yang.parser.spi.source.PrefixResolver;
24 import org.opendaylight.yangtools.yang.parser.spi.source.QNameToStatementDefinition;
25 import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter;
27 class StatementContextVisitor {
28 private final QNameToStatementDefinition stmtDef;
29 private final ArgumentContextUtils utils;
30 private final PrefixResolver prefixes;
31 private final StatementWriter writer;
32 private final String sourceName;
34 StatementContextVisitor(final String sourceName, final StatementWriter writer,
35 final QNameToStatementDefinition stmtDef, final PrefixResolver prefixes, final YangVersion yangVersion) {
36 this.writer = requireNonNull(writer);
37 this.stmtDef = requireNonNull(stmtDef);
38 utils = ArgumentContextUtils.forVersion(yangVersion);
39 this.sourceName = sourceName;
40 this.prefixes = prefixes;
43 void visit(final IRStatement stmt) {
44 processStatement(0, stmt);
48 * Based on identifier read from source and collections of relevant prefixes and statement definitions mappings
49 * provided for actual phase, method resolves and returns valid QName for declared statement to be written.
50 * This applies to any declared statement, including unknown statements.
52 * @param prefixes collection of all relevant prefix mappings supplied for actual parsing phase
53 * @param stmtDef collection of all relevant statement definition mappings provided for actual parsing phase
54 * @param keyword statement keyword text to parse from source
55 * @param ref Source reference
56 * @return valid QName for declared statement to be written, or null
58 QName getValidStatementDefinition(final IRKeyword keyword, final StatementSourceReference ref) {
59 if (keyword instanceof Qualified) {
60 return getValidStatementDefinition((Qualified) keyword, ref);
62 final StatementDefinition def = stmtDef.get(QName.unsafeOf(YangConstants.RFC6020_YIN_MODULE,
63 keyword.identifier()));
64 return def != null ? def.getStatementName() : null;
67 private QName getValidStatementDefinition(final Qualified keyword, final StatementSourceReference ref) {
68 if (prefixes == null) {
69 // No prefixes to look up from
73 final QNameModule qNameModule = prefixes.resolvePrefix(keyword.prefix());
74 if (qNameModule == null) {
75 // Failed to look the namespace
79 final StatementDefinition foundStmtDef = resolveStatement(qNameModule, keyword.identifier());
80 return foundStmtDef != null ? foundStmtDef.getStatementName() : null;
83 StatementDefinition resolveStatement(final QNameModule module, final String localName) {
84 return stmtDef.get(QName.unsafeOf(module, localName));
87 // Normal entry point, checks for potential resume
88 private boolean processStatement(final int myOffset, final IRStatement stmt) {
89 final var optResumed = writer.resumeStatement(myOffset);
90 if (optResumed.isPresent()) {
91 final var resumed = optResumed.orElseThrow();
92 return resumed.isFullyDefined() || doProcessStatement(stmt, resumed.getSourceReference());
94 return processNewStatement(myOffset, stmt);
97 // Slow-path allocation of a new statement
98 private boolean processNewStatement(final int myOffset, final IRStatement stmt) {
99 final var ref = StatementDeclarations.inText(sourceName, stmt.startLine(), stmt.startColumn() + 1);
100 final QName def = getValidStatementDefinition(stmt.keyword(), ref);
105 final IRArgument argumentCtx = stmt.argument();
106 final String argument = argumentCtx == null ? null : utils.stringFromStringContext(argumentCtx, ref);
107 writer.startStatement(myOffset, def, argument, ref);
108 return doProcessStatement(stmt, ref);
112 private boolean doProcessStatement(final IRStatement stmt, final StatementSourceReference ref) {
114 boolean fullyDefined = true;
115 for (IRStatement substatement : stmt.statements()) {
116 if (!processStatement(childOffset++, substatement)) {
117 fullyDefined = false;
121 writer.storeStatement(childOffset, fullyDefined);
122 writer.endStatement(ref);