import static com.google.common.base.Verify.verifyNotNull;
import static java.util.Objects.requireNonNull;
+import com.google.common.base.VerifyException;
+import java.util.Optional;
+import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.tree.ParseTree;
-import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser.ArgumentContext;
-import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser.KeywordContext;
-import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser.StatementContext;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.common.YangConstants;
import org.opendaylight.yangtools.yang.common.YangVersion;
import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
+import org.opendaylight.yangtools.yang.parser.antlr.YangStatementParser.ArgumentContext;
+import org.opendaylight.yangtools.yang.parser.antlr.YangStatementParser.KeywordContext;
+import org.opendaylight.yangtools.yang.parser.antlr.YangStatementParser.StatementContext;
import org.opendaylight.yangtools.yang.parser.spi.source.DeclarationInTextSource;
import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule;
import org.opendaylight.yangtools.yang.parser.spi.source.QNameToStatementDefinition;
-import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter;
+import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter.ResumedStatement;
class StatementContextVisitor {
private final QNameToStatementDefinition stmtDef;
+ private final ArgumentContextUtils utils;
private final StatementWriter writer;
- private final YangVersion yangVersion;
private final PrefixToModule prefixes;
private final String sourceName;
final QNameToStatementDefinition stmtDef, final PrefixToModule prefixes, final YangVersion yangVersion) {
this.writer = requireNonNull(writer);
this.stmtDef = requireNonNull(stmtDef);
- this.yangVersion = requireNonNull(yangVersion);
+ this.utils = ArgumentContextUtils.forVersion(yangVersion);
this.sourceName = sourceName;
this.prefixes = prefixes;
}
*
* @param prefixes collection of all relevant prefix mappings supplied for actual parsing phase
* @param stmtDef collection of all relevant statement definition mappings provided for actual parsing phase
- * @param keywordText statement keyword text to parse from source
+ * @param keyword statement keyword text to parse from source
* @param ref Source reference
* @return valid QName for declared statement to be written, or null
*/
- QName getValidStatementDefinition(final String keywordText, final StatementSourceReference ref) {
- final int firstColon = keywordText.indexOf(':');
- if (firstColon == -1) {
- final StatementDefinition def = stmtDef.get(QName.create(YangConstants.RFC6020_YIN_NAMESPACE, keywordText));
- return def != null ? def.getStatementName() : null;
- }
-
- SourceException.throwIf(firstColon == keywordText.length() - 1
- || keywordText.indexOf(':', firstColon + 1) != -1, ref, "Malformed statement '%s'", keywordText);
+ QName getValidStatementDefinition(final KeywordContext keyword, final StatementSourceReference ref) {
+ switch (keyword.getChildCount()) {
+ case 1:
+ final StatementDefinition def = stmtDef.get(QName.create(YangConstants.RFC6020_YIN_MODULE,
+ keyword.getChild(0).getText()));
+ return def != null ? def.getStatementName() : null;
+ case 3:
+ if (prefixes == null) {
+ // No prefixes to look up from
+ return null;
+ }
- if (prefixes == null) {
- // No prefixes to look up from
- return null;
- }
+ final String prefix = keyword.getChild(0).getText();
+ final QNameModule qNameModule = prefixes.get(prefix);
+ if (qNameModule == null) {
+ // Failed to look the namespace
+ return null;
+ }
- final String prefix = keywordText.substring(0, firstColon);
- final QNameModule qNameModule = prefixes.get(prefix);
- if (qNameModule == null) {
- // Failed to look the namespace
- return null;
+ final String localName = keyword.getChild(2).getText();
+ final StatementDefinition foundStmtDef = resolveStatement(qNameModule, localName);
+ return foundStmtDef != null ? foundStmtDef.getStatementName() : null;
+ default:
+ throw new VerifyException("Unexpected shape of " + keyword);
}
-
- final String localName = keywordText.substring(firstColon + 1);
- final StatementDefinition foundStmtDef = resolveStatement(qNameModule, localName);
- return foundStmtDef != null ? foundStmtDef.getStatementName() : null;
}
StatementDefinition resolveStatement(final QNameModule module, final String localName) {
return stmtDef.get(QName.create(module, localName));
}
- private void processStatement(final int myOffset, final StatementContext ctx) {
- final String keywordTxt = verifyNotNull(ctx.getChild(KeywordContext.class, 0)).getText();
- final StatementSourceReference ref = DeclarationInTextSource.atPosition(sourceName, ctx.getStart().getLine(),
- ctx.getStart().getCharPositionInLine());
- final QName def = getValidStatementDefinition(keywordTxt, ref);
+ // Normal entry point, checks for potential resume
+ private boolean processStatement(final int myOffset, final StatementContext ctx) {
+ final Optional<? extends ResumedStatement> optResumed = writer.resumeStatement(myOffset);
+ if (optResumed.isPresent()) {
+ final ResumedStatement resumed = optResumed.get();
+ return resumed.isFullyDefined() || doProcessStatement(ctx, resumed.getSourceReference());
+ }
+ return processNewStatement(myOffset, ctx);
+ }
+
+ // Slow-path allocation of a new statement
+ private boolean processNewStatement(final int myOffset, final StatementContext ctx) {
+ final Token start = ctx.getStart();
+ final StatementSourceReference ref = DeclarationInTextSource.atPosition(sourceName, start.getLine(),
+ start.getCharPositionInLine());
+ final QName def = getValidStatementDefinition(verifyNotNull(ctx.getChild(KeywordContext.class, 0)), ref);
if (def == null) {
- return;
+ return false;
}
final ArgumentContext argumentCtx = ctx.getChild(ArgumentContext.class, 0);
- final String argument = argumentCtx == null ? null
- : ArgumentContextUtils.stringFromStringContext(argumentCtx, yangVersion, ref);
+ final String argument = argumentCtx == null ? null : utils.stringFromStringContext(argumentCtx, ref);
writer.startStatement(myOffset, def, argument, ref);
+ return doProcessStatement(ctx, ref);
+ }
+ // Actual processing
+ private boolean doProcessStatement(final StatementContext ctx, final StatementSourceReference ref) {
+ int childOffset = 0;
+ boolean fullyDefined = true;
if (ctx.children != null) {
- int childOffset = 0;
for (ParseTree s : ctx.children) {
- if (s instanceof StatementContext) {
- processStatement(childOffset++, (StatementContext) s);
+ if (s instanceof StatementContext && !processStatement(childOffset++, (StatementContext) s)) {
+ fullyDefined = false;
}
}
}
+ writer.storeStatement(childOffset, fullyDefined);
writer.endStatement(ref);
+ return fullyDefined;
}
}