#include "expr/kind.h"
#include "expr/metakind.h"
#include "expr/node.h"
+#include "expr/node_algorithm.h"
#include "expr/node_manager.h"
#include "expr/sequence.h"
#include "expr/type_node.h"
"predeclaration";
CVC4_API_CHECK(ntSymbol.d_node->getType() == rule.d_node->getType())
<< "Expected ntSymbol and rule to have the same sort";
+ CVC4_API_ARG_CHECK_EXPECTED(!containsFreeVariables(rule), rule)
+ << "a term whose free variables are limited to synthFun/synthInv "
+ "parameters and non-terminal symbols of the grammar";
//////// all checks before this line
d_ntsToTerms[ntSymbol].push_back(rule);
////////
d_ntsToTerms.find(ntSymbol) != d_ntsToTerms.cend(), ntSymbol)
<< "ntSymbol to be one of the non-terminal symbols given in the "
"predeclaration";
+ for (size_t i = 0, n = rules.size(); i < n; ++i)
+ {
+ CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+ !containsFreeVariables(rules[i]), rules[i], rules, i)
+ << "a term whose free variables are limited to synthFun/synthInv "
+ "parameters and non-terminal symbols of the grammar";
+ }
//////// all checks before this line
d_ntsToTerms[ntSymbol].insert(
d_ntsToTerms[ntSymbol].cend(), rules.cbegin(), rules.cend());
CVC4_API_TRY_CATCH_END;
}
+bool Grammar::containsFreeVariables(const Term& rule) const
+{
+ std::unordered_set<TNode, TNodeHashFunction> scope;
+
+ for (const Term& sygusVar : d_sygusVars)
+ {
+ scope.emplace(*sygusVar.d_node);
+ }
+
+ for (const Term& ntsymbol : d_ntSyms)
+ {
+ scope.emplace(*ntsymbol.d_node);
+ }
+
+ std::unordered_set<Node, NodeHashFunction> fvs;
+ return expr::getFreeVariablesScope(*rule.d_node, fvs, scope, false);
+}
+
std::ostream& operator<<(std::ostream& out, const Grammar& grammar)
{
return out << grammar.toString();
*/
void addSygusConstructorVariables(DatatypeDecl& dt, const Sort& sort) const;
+ /**
+ * Check if <rule> contains variables that are neither parameters of
+ * the corresponding synthFun/synthInv nor non-terminals.
+ * @param rule the non-terminal allowed to be any constant
+ * @return <true> if <rule> contains free variables and <false> otherwise
+ */
+ bool containsFreeVariables(const Term& rule) const;
+
/** The solver that created this grammar. */
const Solver* d_solver;
/** Input variables to the corresponding function/invariant to synthesize.*/
ASSERT_THROW(g.addRule(start, nullTerm), CVC4ApiException);
ASSERT_THROW(g.addRule(nts, d_solver.mkBoolean(false)), CVC4ApiException);
ASSERT_THROW(g.addRule(start, d_solver.mkInteger(0)), CVC4ApiException);
+ ASSERT_THROW(g.addRule(start, nts), CVC4ApiException);
d_solver.synthFun("f", {}, boolean, g);
ASSERT_THROW(g.addRules(start, {nullTerm}), CVC4ApiException);
ASSERT_THROW(g.addRules(nts, {d_solver.mkBoolean(false)}), CVC4ApiException);
ASSERT_THROW(g.addRules(start, {d_solver.mkInteger(0)}), CVC4ApiException);
+ ASSERT_THROW(g.addRules(start, {nts}), CVC4ApiException);
d_solver.synthFun("f", {}, boolean, g);