--- /dev/null
+/*
+ * Copyright (c) 2018 Pantheon Technologies, s.r.o. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.parser.rfc7950.antlr;
+
+import static com.google.common.base.Verify.verifyNotNull;
+
+import com.google.common.annotations.Beta;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import javax.annotation.concurrent.NotThreadSafe;
+import org.antlr.v4.runtime.BaseErrorListener;
+import org.antlr.v4.runtime.RecognitionException;
+import org.antlr.v4.runtime.Recognizer;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.yangtools.concepts.Mutable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Abstract base type for converting ANTLRErrorListener errors to Exceptions.
+ *
+ * @param <E> Reported exception type
+ * @author Robert Varga
+ */
+@Beta
+@NonNullByDefault
+@NotThreadSafe
+public abstract class AbstractParserErrorListener<E extends Exception> extends BaseErrorListener implements Mutable {
+ private static final Logger LOG = LoggerFactory.getLogger(AbstractParserErrorListener.class);
+
+ private final Collection<E> exceptions = new ArrayList<>();
+
+ @Override
+ @SuppressWarnings("checkstyle:parameterName")
+ public final void syntaxError(final @Nullable Recognizer<?, ?> recognizer, final @Nullable Object offendingSymbol,
+ final int line, final int charPositionInLine, final @Nullable String msg,
+ final @Nullable RecognitionException e) {
+ LOG.debug("Syntax error at {}:{}: {}", line, charPositionInLine, msg, e);
+ exceptions.add(verifyNotNull(createException(verifyNotNull(recognizer), offendingSymbol, line,
+ charPositionInLine, verifyNotNull(msg), e)));
+ }
+
+ public final void validate() throws E {
+ if (!exceptions.isEmpty()) {
+ final Iterator<E> it = exceptions.iterator();
+ final E exception = it.next();
+ it.forEachRemaining(exception::addSuppressed);
+ throw exception;
+ }
+ }
+
+ protected abstract E createException(Recognizer<?, ?> recognizer, @Nullable Object offendingSymbol, int line,
+ int charPositionInLine, String msg, @Nullable RecognitionException cause);
+}
--- /dev/null
+/*
+ * Copyright (c) 2018 Pantheon Technologies, s.r.o. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.parser.rfc7950.antlr;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.annotations.Beta;
+import java.util.function.Supplier;
+import javax.annotation.concurrent.NotThreadSafe;
+import org.antlr.v4.runtime.RecognitionException;
+import org.antlr.v4.runtime.Recognizer;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
+import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
+
+/**
+ * Utility class for converting ANTLRErrorListener errors to SourceExceptions.
+ *
+ * @author Robert Varga
+ */
+@Beta
+@NonNullByDefault
+@NotThreadSafe
+public final class SourceExceptionParser {
+ private static final class Listener extends AbstractParserErrorListener<SourceException> {
+ private final StatementSourceReference ref;
+
+ private Listener(final StatementSourceReference ref) {
+ this.ref = requireNonNull(ref);
+ }
+
+ @Override
+ protected SourceException createException(final Recognizer<?, ?> recognizer,
+ final @Nullable Object offendingSymbol, final int line, final int charPositionInLine,
+ final String msg, final @Nullable RecognitionException cause) {
+ return new SourceException(ref, cause, "%s at %s:%s", msg, line, charPositionInLine);
+ }
+ }
+
+ private SourceExceptionParser() {
+
+ }
+
+ /**
+ * Parse a Recognizer extracting its root item.
+ *
+ * @param recognizer Recognizer to use
+ * @param parseMethod Root item extractor method
+ * @param ref Source reference
+ * @return Parsed item
+ * @throws NullPointerException if any argument is null
+ * @throws SourceException if a parser error occurs
+ */
+ public static <T> T parse(final Recognizer<?, ?> recognizer, final Supplier<T> parseMethod,
+ final StatementSourceReference ref) {
+ final Listener listener = new Listener(ref);
+ recognizer.removeErrorListeners();
+ recognizer.addErrorListener(listener);
+
+ final T ret = parseMethod.get();
+ listener.validate();
+ return ret;
+ }
+}
\ No newline at end of file
import java.util.function.Predicate;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.yangtools.antlrv4.code.gen.IfFeatureExpressionLexer;
import org.opendaylight.yangtools.antlrv4.code.gen.IfFeatureExpressionParser;
import org.opendaylight.yangtools.antlrv4.code.gen.IfFeatureExpressionParser.Identifier_ref_argContext;
import org.opendaylight.yangtools.antlrv4.code.gen.IfFeatureExpressionParser.If_feature_termContext;
import org.opendaylight.yangtools.antlrv4.code.gen.IfFeatureExpressionParserBaseVisitor;
import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.parser.rfc7950.antlr.SourceExceptionParser;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
+@NonNullByDefault
final class IfFeaturePredicateVisitor extends IfFeatureExpressionParserBaseVisitor<Predicate<Set<QName>>> {
private final StmtContext<?, ?, ?> stmtCtx;
}
static Predicate<Set<QName>> parseIfFeatureExpression(final StmtContext<?, ?, ?> ctx, final String value) {
- final IfFeatureExpressionLexer lexer = new IfFeatureExpressionLexer(CharStreams.fromString(value));
- final CommonTokenStream tokens = new CommonTokenStream(lexer);
- final IfFeatureExpressionParser parser = new IfFeatureExpressionParser(tokens);
-
- return new IfFeaturePredicateVisitor(ctx).visit(parser.if_feature_expr());
+ final IfFeatureExpressionParser parser = new IfFeatureExpressionParser(new CommonTokenStream(
+ new IfFeatureExpressionLexer(CharStreams.fromString(value))));
+ return new IfFeaturePredicateVisitor(ctx).visit(SourceExceptionParser.parse(parser, parser::if_feature_expr,
+ ctx.getStatementSourceReference()));
}
@Override
- public Predicate<Set<QName>> visitIf_feature_expr(final If_feature_exprContext ctx) {
- if (ctx.if_feature_expr() == null) {
- return visitIf_feature_term(ctx.if_feature_term());
- }
-
- return visitIf_feature_term(ctx.if_feature_term()).or(visitIf_feature_expr(ctx.if_feature_expr()));
+ public Predicate<Set<QName>> visitIf_feature_expr(final @Nullable If_feature_exprContext ctx) {
+ final Predicate<Set<QName>> term = visitIf_feature_term(ctx.if_feature_term());
+ final If_feature_exprContext expr = ctx.if_feature_expr();
+ return expr == null ? term : term.or(visitIf_feature_expr(expr));
}
@Override
- public Predicate<Set<QName>> visitIf_feature_term(final If_feature_termContext ctx) {
- if (ctx.if_feature_term() == null) {
- return visitIf_feature_factor(ctx.if_feature_factor());
- }
-
- return visitIf_feature_factor(ctx.if_feature_factor()).and(visitIf_feature_term(ctx.if_feature_term()));
+ public Predicate<Set<QName>> visitIf_feature_term(final @Nullable If_feature_termContext ctx) {
+ final Predicate<Set<QName>> factor = visitIf_feature_factor(ctx.if_feature_factor());
+ final If_feature_termContext term = ctx.if_feature_term();
+ return term == null ? factor : factor.and(visitIf_feature_term(term));
}
@Override
- public Predicate<Set<QName>> visitIf_feature_factor(final If_feature_factorContext ctx) {
+ public Predicate<Set<QName>> visitIf_feature_factor(final @Nullable If_feature_factorContext ctx) {
if (ctx.if_feature_expr() != null) {
return visitIf_feature_expr(ctx.if_feature_expr());
} else if (ctx.if_feature_factor() != null) {
}
@Override
- public Predicate<Set<QName>> visitIdentifier_ref_arg(final Identifier_ref_argContext ctx) {
+ public Predicate<Set<QName>> visitIdentifier_ref_arg(final @Nullable Identifier_ref_argContext ctx) {
final QName featureQName = StmtContextUtils.parseNodeIdentifier(stmtCtx, ctx.getText());
return setQNames -> setQNames.contains(featureQName);
}