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 java.util.Optional;
13 import org.opendaylight.yangtools.yang.common.QName;
14 import org.opendaylight.yangtools.yang.common.QNameModule;
15 import org.opendaylight.yangtools.yang.common.YangConstants;
16 import org.opendaylight.yangtools.yang.common.YangVersion;
17 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
18 import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRArgument;
19 import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRKeyword;
20 import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRKeyword.Qualified;
21 import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRStatement;
22 import org.opendaylight.yangtools.yang.parser.spi.source.ExplicitStatement;
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.StatementSourceReference;
26 import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter;
27 import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter.ResumedStatement;
29 class StatementContextVisitor {
30 private final QNameToStatementDefinition stmtDef;
31 private final ArgumentContextUtils utils;
32 private final StatementWriter writer;
33 private final PrefixToModule prefixes;
34 private final String sourceName;
36 StatementContextVisitor(final String sourceName, final StatementWriter writer,
37 final QNameToStatementDefinition stmtDef, final PrefixToModule prefixes, final YangVersion yangVersion) {
38 this.writer = requireNonNull(writer);
39 this.stmtDef = requireNonNull(stmtDef);
40 this.utils = ArgumentContextUtils.forVersion(yangVersion);
41 this.sourceName = sourceName;
42 this.prefixes = prefixes;
45 void visit(final IRStatement stmt) {
46 processStatement(0, stmt);
50 * Based on identifier read from source and collections of relevant prefixes and statement definitions mappings
51 * provided for actual phase, method resolves and returns valid QName for declared statement to be written.
52 * This applies to any declared statement, including unknown statements.
54 * @param prefixes collection of all relevant prefix mappings supplied for actual parsing phase
55 * @param stmtDef collection of all relevant statement definition mappings provided for actual parsing phase
56 * @param keyword statement keyword text to parse from source
57 * @param ref Source reference
58 * @return valid QName for declared statement to be written, or null
60 QName getValidStatementDefinition(final IRKeyword keyword, final StatementSourceReference ref) {
61 if (keyword instanceof Qualified) {
62 return getValidStatementDefinition((Qualified) keyword, ref);
64 final StatementDefinition def = stmtDef.get(QName.unsafeOf(YangConstants.RFC6020_YIN_MODULE,
65 keyword.identifier()));
66 return def != null ? def.getStatementName() : null;
69 private QName getValidStatementDefinition(final Qualified keyword, final StatementSourceReference ref) {
70 if (prefixes == null) {
71 // No prefixes to look up from
75 final QNameModule qNameModule = prefixes.get(keyword.prefix());
76 if (qNameModule == null) {
77 // Failed to look the namespace
81 final StatementDefinition foundStmtDef = resolveStatement(qNameModule, keyword.identifier());
82 return foundStmtDef != null ? foundStmtDef.getStatementName() : null;
85 StatementDefinition resolveStatement(final QNameModule module, final String localName) {
86 return stmtDef.get(QName.unsafeOf(module, localName));
89 // Normal entry point, checks for potential resume
90 private boolean processStatement(final int myOffset, final IRStatement stmt) {
91 final Optional<? extends ResumedStatement> optResumed = writer.resumeStatement(myOffset);
92 if (optResumed.isPresent()) {
93 final ResumedStatement resumed = optResumed.get();
94 return resumed.isFullyDefined() || doProcessStatement(stmt, resumed.getSourceReference());
96 return processNewStatement(myOffset, stmt);
99 // Slow-path allocation of a new statement
100 private boolean processNewStatement(final int myOffset, final IRStatement stmt) {
101 final StatementSourceReference ref = ExplicitStatement.atPosition(sourceName, stmt.startLine(),
102 stmt.startColumn() + 1);
103 final QName def = getValidStatementDefinition(stmt.keyword(), ref);
108 final IRArgument argumentCtx = stmt.argument();
109 final String argument = argumentCtx == null ? null : utils.stringFromStringContext(argumentCtx, ref);
110 writer.startStatement(myOffset, def, argument, ref);
111 return doProcessStatement(stmt, ref);
115 private boolean doProcessStatement(final IRStatement stmt, final StatementSourceReference ref) {
117 boolean fullyDefined = true;
118 for (IRStatement substatement : stmt.statements()) {
119 if (!processStatement(childOffset++, substatement)) {
120 fullyDefined = false;
124 writer.storeStatement(childOffset, fullyDefined);
125 writer.endStatement(ref);