package org.batfish.grammar.assertion; import java.util.List; import java.util.stream.Collectors; import org.antlr.v4.runtime.ParserRuleContext; import org.batfish.common.BatfishException; import org.batfish.datamodel.assertion.And; import org.batfish.datamodel.assertion.AssertionAst; import org.batfish.datamodel.assertion.BooleanExpr; import org.batfish.datamodel.assertion.BooleanExprs; import org.batfish.datamodel.assertion.Eq; import org.batfish.datamodel.assertion.FloatLiteral; import org.batfish.datamodel.assertion.Ge; import org.batfish.datamodel.assertion.Gt; import org.batfish.datamodel.assertion.BooleanIf; import org.batfish.datamodel.assertion.IntLiteral; import org.batfish.datamodel.assertion.Le; import org.batfish.datamodel.assertion.LongLiteral; import org.batfish.datamodel.assertion.Lt; import org.batfish.datamodel.assertion.Not; import org.batfish.datamodel.assertion.ComparableExpr; import org.batfish.datamodel.assertion.ComparableIf; import org.batfish.datamodel.assertion.DoubleLiteral; import org.batfish.datamodel.assertion.Or; import org.batfish.datamodel.assertion.PathSize; import org.batfish.datamodel.assertion.StringExpr; import org.batfish.datamodel.assertion.StringIf; import org.batfish.datamodel.assertion.StringLiteral; import org.batfish.grammar.assertion.AssertionParser.*; public class AssertionExtractor extends AssertionParserBaseListener { private AssertionAst _ast; private String _text; public AssertionExtractor(String fileText, AssertionParser assertionParser) { _text = fileText; } private BatfishException convError(Class<?> type, ParserRuleContext ctx) { String typeName = type.getSimpleName(); String txt = getFullText(ctx); return new BatfishException( "Could not convert to " + typeName + ": " + txt); } @Override public void exitAssertion(AssertionContext ctx) { _ast = toAst(ctx); } public AssertionAst getAst() { return _ast; } private String getFullText(ParserRuleContext ctx) { int start = ctx.getStart().getStartIndex(); int end = ctx.getStop().getStopIndex(); String text = _text.substring(start, end + 1); return text; } private String getText(Quoted_stringContext ctx) { if (ctx.text != null) { return ctx.text.getText(); } else { return ""; } } private AssertionAst toAst(AssertionContext ctx) { BooleanExpr expr = toBooleanExpr(ctx.boolean_expr()); return new AssertionAst(expr); } private BooleanExpr toBooleanExpr(AndContext ctx) { List<BooleanExpr> conjuncts = ctx.conjuncts.stream() .map(cctx -> toBooleanExpr(cctx)).collect(Collectors.toList()); return new And(conjuncts); } private BooleanExpr toBooleanExpr(Boolean_exprContext ctx) { if (ctx.boolean_application() != null) { return toBooleanExpr(ctx.boolean_application().boolean_function()); } else if (ctx.FALSE() != null) { return BooleanExprs.FALSE; } else { throw convError(BooleanExpr.class, ctx); } } private BooleanExpr toBooleanExpr(Boolean_functionContext ctx) { if (ctx.and() != null) { return toBooleanExpr(ctx.and()); } else if (ctx.boolean_if() != null) { return toBooleanExpr(ctx.boolean_if()); } else if (ctx.eq() != null) { return toBooleanExpr(ctx.eq()); } else if (ctx.ge() != null) { return toBooleanExpr(ctx.ge()); } else if (ctx.gt() != null) { return toBooleanExpr(ctx.gt()); } else if (ctx.le() != null) { return toBooleanExpr(ctx.le()); } else if (ctx.lt() != null) { return toBooleanExpr(ctx.lt()); } else if (ctx.not() != null) { return toBooleanExpr(ctx.not()); } else if (ctx.or() != null) { return toBooleanExpr(ctx.or()); } else { throw convError(BooleanExpr.class, ctx); } } private BooleanExpr toBooleanExpr(Boolean_ifContext ctx) { BooleanExpr guard = toBooleanExpr(ctx.guard); BooleanExpr trueExpr = toBooleanExpr(ctx.trueval); BooleanExpr falseExpr = toBooleanExpr(ctx.falseval); return new BooleanIf(guard, trueExpr, falseExpr); } private BooleanExpr toBooleanExpr(EqContext ctx) { if (ctx.lhs_boolean != null) { BooleanExpr lhs = toBooleanExpr(ctx.lhs_boolean); BooleanExpr rhs = toBooleanExpr(ctx.rhs_boolean); return new Eq(lhs, rhs); } else if (ctx.lhs_num != null) { ComparableExpr lhs = toComparableExpr(ctx.lhs_num); ComparableExpr rhs = toComparableExpr(ctx.rhs_num); return new Eq(lhs, rhs); } else if (ctx.lhs_string != null) { StringExpr lhs = toStringExpr(ctx.lhs_string); StringExpr rhs = toStringExpr(ctx.rhs_string); return new Eq(lhs, rhs); } else { throw convError(BooleanExpr.class, ctx); } } private BooleanExpr toBooleanExpr(GeContext ctx) { ComparableExpr lhs = toComparableExpr(ctx.lhs); ComparableExpr rhs = toComparableExpr(ctx.lhs); return new Ge(lhs, rhs); } private BooleanExpr toBooleanExpr(GtContext ctx) { ComparableExpr lhs = toComparableExpr(ctx.lhs); ComparableExpr rhs = toComparableExpr(ctx.rhs); return new Gt(lhs, rhs); } private BooleanExpr toBooleanExpr(LeContext ctx) { ComparableExpr lhs = toComparableExpr(ctx.lhs); ComparableExpr rhs = toComparableExpr(ctx.rhs); return new Le(lhs, rhs); } private BooleanExpr toBooleanExpr(LtContext ctx) { ComparableExpr lhs = toComparableExpr(ctx.lhs); ComparableExpr rhs = toComparableExpr(ctx.rhs); return new Lt(lhs, rhs); } private BooleanExpr toBooleanExpr(NotContext ctx) { BooleanExpr expr = toBooleanExpr(ctx.boolean_expr()); return new Not(expr); } private BooleanExpr toBooleanExpr(OrContext ctx) { List<BooleanExpr> disjuncts = ctx.disjuncts.stream() .map(cctx -> toBooleanExpr(cctx)).collect(Collectors.toList()); return new Or(disjuncts); } private ComparableExpr toComparableExpr(Num_exprContext ctx) { if (ctx.num_application() != null) { return toComparableExpr(ctx.num_application().num_function()); } else if (ctx.num_double() != null) { String raw = ctx.num_double().DOUBLE().getText(); String num = raw.substring(0, raw.length() - 1); double d = Double.parseDouble(num); return new DoubleLiteral(d); } else if (ctx.num_float() != null) { String raw = ctx.num_float().FLOAT().getText(); String num = raw.substring(0, raw.length() - 1); float f = Float.parseFloat(num); return new FloatLiteral(f); } else if (ctx.num_int() != null) { String num = ctx.num_int().INT().getText(); int i = Integer.parseInt(num); return new IntLiteral(i); } else if (ctx.num_long() != null) { String raw = ctx.num_long().LONG().getText(); String num = raw.substring(0, raw.length() - 1); long l = Long.parseLong(num); return new LongLiteral(l); } else { throw convError(ComparableExpr.class, ctx); } } private ComparableExpr toComparableExpr(Num_functionContext ctx) { if (ctx.num_if() != null) { return toComparableExpr(ctx.num_if()); } else if (ctx.pathsize() != null) { return toComparableExpr(ctx.pathsize()); } else { throw convError(ComparableExpr.class, ctx); } } private ComparableExpr toComparableExpr(Num_ifContext ctx) { BooleanExpr guard = toBooleanExpr(ctx.guard); ComparableExpr trueExpr = toComparableExpr(ctx.trueval); ComparableExpr falseExpr = toComparableExpr(ctx.falseval); return new ComparableIf(guard, trueExpr, falseExpr); } private ComparableExpr toComparableExpr(PathsizeContext ctx) { StringExpr pathExpr = toStringExpr(ctx.string_expr()); return new PathSize(pathExpr); } private StringExpr toStringExpr(Quoted_stringContext ctx) { String text = getText(ctx); return new StringLiteral(text); } private StringExpr toStringExpr(String_exprContext ctx) { if (ctx.string_application() != null) { return toStringExpr(ctx.string_application().string_function()); } else if (ctx.quoted_string() != null) { return toStringExpr(ctx.quoted_string()); } else { throw convError(StringExpr.class, ctx); } } private StringExpr toStringExpr(String_functionContext ctx) { if (ctx.string_if() != null) { return toStringExpr(ctx.string_if()); } else { throw convError(StringExpr.class, ctx); } } private StringExpr toStringExpr(String_ifContext ctx) { BooleanExpr guard = toBooleanExpr(ctx.guard); StringExpr trueExpr = toStringExpr(ctx.trueval); StringExpr falseExpr = toStringExpr(ctx.falseval); return new StringIf(guard, trueExpr, falseExpr); } }