This PR refactors how a term is constructed based on information regarding an operator (ParseOp) and its arguments. It also makes a few miscellaneous fixes. This includes:
Indexed ops are carried in ParseOp via api::Op not Expr,
getKindForFunction is limited to "APPLY" kinds from the new API,
The TPTP/SMT2 parsers rely on mkTermInternal for handling associativity.
TPTP should use DIVISION not DIVISION_TOTAL.
This is in preparation for parser migration. These are the essential behavioral changes required for using the new API for the majority of the parser.
| LPAREN { args.push_back(f); }
formula[f] { args.push_back(f); }
( COMMA formula[f] { args.push_back(f); } )* RPAREN
- // TODO: check arity
- { Kind k = PARSER_STATE->getKindForFunction(args.front());
+ {
+ PARSER_STATE->checkFunctionLike(args.front());
+ Kind k = PARSER_STATE->getKindForFunction(args.front());
Debug("parser") << "expr is " << args.front() << std::endl;
Debug("parser") << "kind is " << k << std::endl;
f = MK_EXPR(k, args);
}
Kind Parser::getKindForFunction(Expr fun) {
- Kind k = getExprManager()->operatorToKind(fun);
- if (k != UNDEFINED_KIND)
- {
- return k;
- }
Type t = fun.getType();
if (t.isFunction())
{
}
| sym=SIMPLE_SYMBOL nonemptyNumeralList[numerals]
{
- p.d_expr = PARSER_STATE->mkIndexedOp(AntlrInput::tokenText($sym), numerals)
- .getExpr();
+ p.d_op = PARSER_STATE->mkIndexedOp(AntlrInput::tokenText($sym), numerals);
}
)
RPAREN_TOK
// First phase: process the operator
if (Debug.isOn("parser"))
{
- Debug("parser") << "Apply parse op to:" << std::endl;
- Debug("parser") << "args has size " << args.size() << std::endl;
+ Debug("parser") << "applyParseOp: " << p << " to:" << std::endl;
for (std::vector<Expr>::iterator i = args.begin(); i != args.end(); ++i)
{
Debug("parser") << "++ " << *i << std::endl;
}
}
+ api::Op op;
if (p.d_kind != kind::NULL_EXPR)
{
// It is a special case, e.g. tupSel or array constant specification.
kind = fkind;
}
}
+ else if (!p.d_op.isNull())
+ {
+ // it was given an operator
+ op = p.d_op;
+ }
else
{
isBuiltinOperator = isOperatorEnabled(p.d_name);
}
}
}
- if (args.size() > 2)
- {
- if (kind == kind::INTS_DIVISION || kind == kind::XOR
- || kind == kind::MINUS || kind == kind::DIVISION
- || (kind == kind::BITVECTOR_XNOR && v2_6()))
- {
- // Builtin operators that are not tokenized, are left associative,
- // but not internally variadic must set this.
- return em->mkLeftAssociative(kind, args);
- }
- else if (kind == kind::IMPLIES)
- {
- /* right-associative, but CVC4 internally only supports 2 args */
- return em->mkRightAssociative(kind, args);
- }
- else if (kind == kind::EQUAL || kind == kind::LT || kind == kind::GT
- || kind == kind::LEQ || kind == kind::GEQ)
- {
- /* "chainable", but CVC4 internally only supports 2 args */
- return em->mkChain(kind, args);
- }
- }
-
- if (kind::isAssociative(kind) && args.size() > em->maxArity(kind))
- {
- /* Special treatment for associative operators with lots of children
- */
- return em->mkAssociative(kind, args);
- }
- else if (!strictModeEnabled() && (kind == kind::AND || kind == kind::OR)
- && args.size() == 1)
+ if (!strictModeEnabled() && (kind == kind::AND || kind == kind::OR)
+ && args.size() == 1)
{
// Unary AND/OR can be replaced with the argument.
return args[0];
{
return em->mkExpr(kind::UMINUS, args[0]);
}
- else
- {
- checkOperator(kind, args.size());
- return em->mkExpr(kind, args);
- }
+ api::Term ret =
+ d_solver->mkTerm(intToExtKind(kind), api::exprVectorToTerms(args));
+ Debug("parser") << "applyParseOp: return default builtin " << ret
+ << std::endl;
+ return ret.getExpr();
}
if (args.size() >= 2)
}
}
}
+ if (!op.isNull())
+ {
+ api::Term ret = d_solver->mkTerm(op, api::exprVectorToTerms(args));
+ Debug("parser") << "applyParseOp: return op : " << ret << std::endl;
+ return ret.getExpr();
+ }
if (kind == kind::NULL_EXPR)
{
std::vector<Expr> eargs(args.begin() + 1, args.end());
}
| '$quotient'
{
- p.d_kind = kind::DIVISION_TOTAL;
+ p.d_kind = kind::DIVISION;
}
| ( '$quotient_e' { remainder = false; }
| '$remainder_e' { remainder = true; }
Expr Tptp::applyParseOp(ParseOp& p, std::vector<Expr>& args)
{
+ if (Debug.isOn("parser"))
+ {
+ Debug("parser") << "applyParseOp: " << p << " to:" << std::endl;
+ for (std::vector<Expr>::iterator i = args.begin(); i != args.end(); ++i)
+ {
+ Debug("parser") << "++ " << *i << std::endl;
+ }
+ }
assert(!args.empty());
ExprManager* em = getExprManager();
// If operator already defined, just build application
}
}
}
-
- if (args.size() > 2)
- {
- if (kind == kind::INTS_DIVISION || kind == kind::XOR
- || kind == kind::MINUS || kind == kind::DIVISION)
- {
- // Builtin operators that are not tokenized, are left associative,
- // but not internally variadic must set this.
- return em->mkLeftAssociative(kind, args);
- }
- if (kind == kind::IMPLIES)
- {
- /* right-associative, but CVC4 internally only supports 2 args */
- return em->mkRightAssociative(kind, args);
- }
- if (kind == kind::EQUAL || kind == kind::LT || kind == kind::GT
- || kind == kind::LEQ || kind == kind::GEQ)
- {
- /* "chainable", but CVC4 internally only supports 2 args */
- return em->mkChain(kind, args);
- }
- }
-
- if (kind::isAssociative(kind) && args.size() > em->maxArity(kind))
- {
- /* Special treatment for associative operators with lots of children
- */
- return em->mkAssociative(kind, args);
- }
if (!strictModeEnabled() && (kind == kind::AND || kind == kind::OR)
&& args.size() == 1)
{
{
return em->mkExpr(kind::UMINUS, args[0]);
}
- checkOperator(kind, args.size());
- return em->mkExpr(kind, args);
+ return d_solver->mkTerm(intToExtKind(kind), api::exprVectorToTerms(args))
+ .getExpr();
}
// check if partially applied function, in this case we use HO_APPLY
Debug("parser") << " : #argTypes = " << arity;
Debug("parser") << ", #args = " << args.size() - 1 << std::endl;
// must curry the partial application
- return em->mkLeftAssociative(kind::HO_APPLY, args);
+ return d_solver->mkTerm(api::HO_APPLY, api::exprVectorToTerms(args))
+ .getExpr();
}
}
}