aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser')
-rw-r--r--src/backend/parser/analyze.c91
-rw-r--r--src/backend/parser/gram.y95
-rw-r--r--src/backend/parser/parse_clause.c4
-rw-r--r--src/backend/parser/parse_expr.c56
-rw-r--r--src/backend/parser/parser.c127
5 files changed, 125 insertions, 248 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index ffedca05ed9..ae1f027e47c 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: analyze.c,v 1.160 2000/10/05 19:11:33 tgl Exp $
+ * $Id: analyze.c,v 1.161 2000/10/07 00:58:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -69,49 +69,45 @@ static List *extras_after;
/*
* parse_analyze -
- * analyze a list of parse trees and transform them if necessary.
- *
- * Returns a list of transformed parse trees. Optimizable statements are
- * all transformed to Query while the rest stays the same.
+ * analyze a raw parse tree and transform it to Query form.
*
+ * The result is a List of Query nodes (we need a list since some commands
+ * produce multiple Queries). Optimizable statements require considerable
+ * transformation, while many utility-type statements are simply hung off
+ * a dummy CMD_UTILITY Query node.
*/
List *
-parse_analyze(List *pl, ParseState *parentParseState)
+parse_analyze(Node *parseTree, ParseState *parentParseState)
{
List *result = NIL;
+ ParseState *pstate = make_parsestate(parentParseState);
+ Query *query;
- while (pl != NIL)
- {
- ParseState *pstate = make_parsestate(parentParseState);
- Query *parsetree;
+ extras_before = extras_after = NIL;
- extras_before = extras_after = NIL;
+ query = transformStmt(pstate, parseTree);
+ release_pstate_resources(pstate);
- parsetree = transformStmt(pstate, lfirst(pl));
+ while (extras_before != NIL)
+ {
+ result = lappend(result,
+ transformStmt(pstate, lfirst(extras_before)));
release_pstate_resources(pstate);
+ extras_before = lnext(extras_before);
+ }
- while (extras_before != NIL)
- {
- result = lappend(result,
- transformStmt(pstate, lfirst(extras_before)));
- release_pstate_resources(pstate);
- extras_before = lnext(extras_before);
- }
-
- result = lappend(result, parsetree);
+ result = lappend(result, query);
- while (extras_after != NIL)
- {
- result = lappend(result,
- transformStmt(pstate, lfirst(extras_after)));
- release_pstate_resources(pstate);
- extras_after = lnext(extras_after);
- }
-
- pfree(pstate);
- pl = lnext(pl);
+ while (extras_after != NIL)
+ {
+ result = lappend(result,
+ transformStmt(pstate, lfirst(extras_after)));
+ release_pstate_resources(pstate);
+ extras_after = lnext(extras_after);
}
+ pfree(pstate);
+
return result;
}
@@ -126,8 +122,7 @@ release_pstate_resources(ParseState *pstate)
/*
* transformStmt -
- * transform a Parse tree. If it is an optimizable statement, turn it
- * into a Query tree.
+ * transform a Parse tree into a Query tree.
*/
static Query *
transformStmt(ParseState *pstate, Node *parseTree)
@@ -353,7 +348,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
* from a stand-alone SELECT. (Indeed, Postgres up through 6.5 had
* bugs of just that nature...)
*/
- selectList = parse_analyze(makeList1(stmt->selectStmt), pstate);
+ selectList = parse_analyze(stmt->selectStmt, pstate);
Assert(length(selectList) == 1);
selectQuery = (Query *) lfirst(selectList);
@@ -1933,7 +1928,7 @@ transformSetOperationTree(ParseState *pstate, Node *node)
*/
save_rtable = pstate->p_rtable;
pstate->p_rtable = NIL;
- selectList = parse_analyze(makeList1(stmt), pstate);
+ selectList = parse_analyze((Node *) stmt, pstate);
pstate->p_rtable = save_rtable;
Assert(length(selectList) == 1);
@@ -2752,6 +2747,7 @@ makeFromExpr(List *fromlist, Node *quals)
static void
transformColumnType(ParseState *pstate, ColumnDef *column)
{
+ TypeName *typename = column->typename;
/*
* If the column doesn't have an explicitly specified typmod, check to
@@ -2760,18 +2756,33 @@ transformColumnType(ParseState *pstate, ColumnDef *column)
* Note that we deliberately do NOT look at array or set information
* here; "numeric[]" needs the same default typmod as "numeric".
*/
- if (column->typename->typmod == -1)
+ if (typename->typmod == -1)
{
- switch (typeTypeId(typenameType(column->typename->name)))
+ switch (typeTypeId(typenameType(typename->name)))
{
- case BPCHAROID:
+ case BPCHAROID:
/* "char" -> "char(1)" */
- column->typename->typmod = VARHDRSZ + 1;
+ typename->typmod = VARHDRSZ + 1;
break;
case NUMERICOID:
- column->typename->typmod = VARHDRSZ +
+ typename->typmod = VARHDRSZ +
((NUMERIC_DEFAULT_PRECISION << 16) | NUMERIC_DEFAULT_SCALE);
break;
}
}
+
+ /*
+ * Is this the name of a complex type? If so, implement
+ * it as a set.
+ *
+ * XXX this is a hangover from ancient Berkeley code that probably
+ * doesn't work anymore anyway.
+ */
+ if (typeTypeRelid(typenameType(typename->name)) != InvalidOid)
+ {
+ /* (Eventually add in here that the set can only
+ * contain one element.)
+ */
+ typename->setof = true;
+ }
}
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index f13b942abd8..a596bd6aba1 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.194 2000/10/05 19:11:33 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.195 2000/10/07 00:58:17 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -59,7 +59,6 @@
extern List *parsetree; /* final parse result is delivered here */
-static char saved_relname[NAMEDATALEN]; /* need this for complex attributes */
static bool QueryIsRule = FALSE;
static Oid *param_type_info;
static int pfunc_num_args;
@@ -161,7 +160,7 @@ static void doNegateFloat(Value *v);
%type <str> relation_name, copy_file_name, copy_delimiter, copy_null, def_name,
database_name, access_method_clause, access_method, attr_name,
- class, index_name, name, func_name, file_name, aggr_argtype
+ class, index_name, name, func_name, file_name
%type <str> opt_id,
all_Op, MathOp, opt_name,
@@ -183,7 +182,7 @@ static void doNegateFloat(Value *v);
def_list, opt_indirection, group_clause, TriggerFuncArgs,
opt_select_limit
-%type <typnam> func_arg, func_return
+%type <typnam> func_arg, func_return, aggr_argtype
%type <boolean> opt_arg, TriggerForOpt, TriggerForType, OptTemp
@@ -1541,7 +1540,7 @@ CreateAsStmt: CREATE OptTemp TABLE relation_name OptUnder OptCreateAs AS Select
n->istemp = $2;
n->into = $4;
if ($5 != NIL)
- yyerror("CREATE TABLE/AS SELECT does not support UNDER");
+ elog(ERROR,"CREATE TABLE/AS SELECT does not support UNDER");
if ($6 != NIL)
mapTargetColumns($6, n->targetList);
$$ = $8;
@@ -2009,8 +2008,8 @@ CommentStmt: COMMENT ON comment_type name IS comment_text
CommentStmt *n = makeNode(CommentStmt);
n->objtype = $3;
n->objname = $4;
- n->objproperty = $5;
- n->objlist = NULL;
+ n->objproperty = NULL;
+ n->objlist = makeList1($5);
n->comment = $7;
$$ = (Node *) n;
}
@@ -2309,7 +2308,7 @@ grantee: PUBLIC
opt_with_grant: WITH GRANT OPTION
{
- yyerror("WITH GRANT OPTION is not supported. Only relation owners can set privileges");
+ elog(ERROR,"WITH GRANT OPTION is not supported. Only relation owners can set privileges");
}
| /*EMPTY*/
;
@@ -2471,7 +2470,7 @@ ProcedureStmt: CREATE FUNCTION func_name func_args
{
ProcedureStmt *n = makeNode(ProcedureStmt);
n->funcname = $3;
- n->defArgs = $4;
+ n->argTypes = $4;
n->returnType = (Node *)$6;
n->withClause = $11;
n->as = $8;
@@ -2488,29 +2487,12 @@ func_args: '(' func_args_list ')' { $$ = $2; }
;
func_args_list: func_arg
- { $$ = makeList1(makeString($1->name)); }
+ { $$ = makeList1($1); }
| func_args_list ',' func_arg
- { $$ = lappend($1, makeString($3->name)); }
+ { $$ = lappend($1, $3); }
;
-/* Would be nice to use the full Typename production for these fields,
- * but that one sometimes dives into the catalogs looking for valid types.
- * Arguments like "opaque" are valid when defining functions,
- * so that won't work here. The only thing we give up is array notation,
- * which isn't meaningful in this context anyway.
- * - thomas 2000-03-25
- * The following productions are difficult, since it is difficult to
- * distinguish between TokenId and SimpleTypename:
- opt_arg TokenId SimpleTypename
- {
- $$ = $3;
- }
- | TokenId SimpleTypename
- {
- $$ = $2;
- }
- */
-func_arg: opt_arg SimpleTypename
+func_arg: opt_arg Typename
{
/* We can catch over-specified arguments here if we want to,
* but for now better to silently swallow typmod, etc.
@@ -2518,7 +2500,7 @@ func_arg: opt_arg SimpleTypename
*/
$$ = $2;
}
- | SimpleTypename
+ | Typename
{
$$ = $1;
}
@@ -2546,7 +2528,7 @@ func_as: Sconst
{ $$ = makeList2(makeString($1), makeString($3)); }
;
-func_return: SimpleTypename
+func_return: Typename
{
/* We can catch over-specified arguments here if we want to,
* but for now better to silently swallow typmod, etc.
@@ -2554,11 +2536,6 @@ func_return: SimpleTypename
*/
$$ = $1;
}
- | SETOF SimpleTypename
- {
- $$ = $2;
- $$->setof = TRUE;
- }
;
@@ -2599,12 +2576,12 @@ RemoveAggrStmt: DROP AGGREGATE name aggr_argtype
{
RemoveAggrStmt *n = makeNode(RemoveAggrStmt);
n->aggname = $3;
- n->aggtype = $4;
+ n->aggtype = (Node *) $4;
$$ = (Node *)n;
}
;
-aggr_argtype: name { $$ = $1; }
+aggr_argtype: Typename { $$ = $1; }
| '*' { $$ = NULL; }
;
@@ -2628,16 +2605,16 @@ RemoveOperStmt: DROP OPERATOR all_Op '(' oper_argtypes ')'
}
;
-oper_argtypes: name
+oper_argtypes: Typename
{
elog(ERROR,"parser: argument type missing (use NONE for unary operators)");
}
- | name ',' name
- { $$ = makeList2(makeString($1), makeString($3)); }
- | NONE ',' name /* left unary */
- { $$ = makeList2(NULL, makeString($3)); }
- | name ',' NONE /* right unary */
- { $$ = makeList2(makeString($1), NULL); }
+ | Typename ',' Typename
+ { $$ = makeList2($1, $3); }
+ | NONE ',' Typename /* left unary */
+ { $$ = makeList2(NULL, $3); }
+ | Typename ',' NONE /* right unary */
+ { $$ = makeList2($1, NULL); }
;
@@ -3832,23 +3809,6 @@ Typename: SimpleTypename opt_array_bounds
{
$$ = $1;
$$->arrayBounds = $2;
-
- /* Is this the name of a complex type? If so, implement
- * it as a set.
- */
- if (strcmp(saved_relname, $$->name) == 0)
- /* This attr is the same type as the relation
- * being defined. The classic example: create
- * emp(name=text,mgr=emp)
- */
- $$->setof = TRUE;
- else if (typeTypeRelid(typenameType($$->name)) != InvalidOid)
- /* (Eventually add in here that the set can only
- * contain one element.)
- */
- $$->setof = TRUE;
- else
- $$->setof = FALSE;
}
| SETOF SimpleTypename
{
@@ -3909,7 +3869,7 @@ Numeric: FLOAT opt_float
| DECIMAL opt_decimal
{
$$ = makeNode(TypeName);
- $$->name = xlateSqlType("numeric");
+ $$->name = xlateSqlType("decimal");
$$->typmod = $2;
}
| DEC opt_decimal
@@ -5245,17 +5205,15 @@ update_target_el: ColId opt_indirection '=' a_expr
relation_name: SpecialRuleRelation
{
$$ = $1;
- StrNCpy(saved_relname, $1, NAMEDATALEN);
}
| ColId
{
/* disallow refs to variable system tables */
if (strcmp(LogRelationName, $1) == 0
- || strcmp(VariableRelationName, $1) == 0)
+ || strcmp(VariableRelationName, $1) == 0)
elog(ERROR,"%s cannot be accessed by users",$1);
else
$$ = $1;
- StrNCpy(saved_relname, $1, NAMEDATALEN);
}
;
@@ -5298,7 +5256,7 @@ AexprConst: Iconst
n->val.val.str = $1;
$$ = (Node *)n;
}
- /* The SimpleTypename rule formerly used Typename,
+ /* This rule formerly used Typename,
* but that causes reduce conflicts with subscripted column names.
* Now, separate into ConstTypename and ConstInterval,
* to allow implementing the SQL92 syntax for INTERVAL literals.
@@ -5383,6 +5341,7 @@ ColId: generic { $$ = $1; }
| TokenId { $$ = $1; }
| INTERVAL { $$ = "interval"; }
| NATIONAL { $$ = "national"; }
+ | NONE { $$ = "none"; }
| PATH_P { $$ = "path"; }
| SERIAL { $$ = "serial"; }
| TIME { $$ = "time"; }
@@ -5595,7 +5554,6 @@ ColLabel: ColId { $$ = $1; }
| NATURAL { $$ = "natural"; }
| NCHAR { $$ = "nchar"; }
| NEW { $$ = "new"; }
- | NONE { $$ = "none"; }
| NOT { $$ = "not"; }
| NOTNULL { $$ = "notnull"; }
| NULLIF { $$ = "nullif"; }
@@ -5851,7 +5809,6 @@ xlateSqlType(char *name)
void parser_init(Oid *typev, int nargs)
{
- saved_relname[0] = '\0';
QueryIsRule = FALSE;
/*
* Keep enough information around to fill out the type of param nodes
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index 20233ed1950..38dc3ea0976 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.69 2000/10/05 19:11:33 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.70 2000/10/07 00:58:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -375,7 +375,7 @@ transformRangeSubselect(ParseState *pstate, RangeSubselect *r)
save_joinlist = pstate->p_joinlist;
pstate->p_rtable = NIL;
pstate->p_joinlist = NIL;
- parsetrees = parse_analyze(makeList1(r->subquery), pstate);
+ parsetrees = parse_analyze(r->subquery, pstate);
pstate->p_rtable = save_rtable;
pstate->p_joinlist = save_joinlist;
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 7b647124d1f..94ccaa5f69f 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.85 2000/10/05 19:11:33 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.86 2000/10/07 00:58:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -294,8 +294,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
break;
}
pstate->p_hasSubLinks = true;
- qtrees = parse_analyze(makeList1(sublink->subselect),
- pstate);
+ qtrees = parse_analyze(sublink->subselect, pstate);
if (length(qtrees) != 1)
elog(ERROR, "Bad query in subselect");
qtree = (Query *) lfirst(qtrees);
@@ -821,19 +820,21 @@ exprIsLengthCoercion(Node *expr, int32 *coercedTypmod)
static Node *
parser_typecast_constant(Value *expr, TypeName *typename)
{
- Const *con;
Type tp;
Datum datum;
+ Const *con;
char *const_string = NULL;
bool string_palloced = false;
bool isNull = false;
+ tp = typenameType(TypeNameToInternalName(typename));
+
switch (nodeTag(expr))
{
case T_Integer:
- string_palloced = true;
const_string = DatumGetCString(DirectFunctionCall1(int4out,
Int32GetDatum(expr->val.ival)));
+ string_palloced = true;
break;
case T_Float:
case T_String:
@@ -844,19 +845,9 @@ parser_typecast_constant(Value *expr, TypeName *typename)
break;
default:
elog(ERROR, "Cannot cast this expression to type '%s'",
- typename->name);
+ typeTypeName(tp));
}
- if (typename->arrayBounds != NIL)
- {
- char type_string[NAMEDATALEN + 2];
-
- sprintf(type_string, "_%s", typename->name);
- tp = (Type) typenameType(type_string);
- }
- else
- tp = (Type) typenameType(typename->name);
-
if (isNull)
datum = (Datum) NULL;
else
@@ -892,15 +883,7 @@ parser_typecast_expression(ParseState *pstate,
Type tp;
Oid targetType;
- if (typename->arrayBounds != NIL)
- {
- char type_string[NAMEDATALEN + 2];
-
- sprintf(type_string, "_%s", typename->name);
- tp = (Type) typenameType(type_string);
- }
- else
- tp = (Type) typenameType(typename->name);
+ tp = typenameType(TypeNameToInternalName(typename));
targetType = typeTypeId(tp);
if (inputType == InvalidOid)
@@ -925,3 +908,26 @@ parser_typecast_expression(ParseState *pstate,
return expr;
}
+
+/*
+ * Given a TypeName node as returned by the grammar, generate the internal
+ * name of the corresponding type. Note this does NOT check if the type
+ * exists or not.
+ */
+char *
+TypeNameToInternalName(TypeName *typename)
+{
+ if (typename->arrayBounds != NIL)
+ {
+ /*
+ * By convention, the name of an array type is the name of its
+ * element type with "_" prepended.
+ */
+ char *arrayname = palloc(strlen(typename->name) + 2);
+
+ sprintf(arrayname, "_%s", typename->name);
+ return arrayname;
+ }
+ else
+ return typename->name;
+}
diff --git a/src/backend/parser/parser.c b/src/backend/parser/parser.c
index 4a6c825498a..84b27549d36 100644
--- a/src/backend/parser/parser.c
+++ b/src/backend/parser/parser.c
@@ -1,14 +1,20 @@
/*-------------------------------------------------------------------------
*
* parser.c
- * Main entry point/driver for PostgreSQL parser
+ * Main entry point/driver for PostgreSQL grammar
+ *
+ * Note that the grammar is not allowed to perform any table access
+ * (since we need to be able to do basic parsing even while inside an
+ * aborted transaction). Therefore, the data structures returned by
+ * the grammar are "raw" parsetrees that still need to be analyzed by
+ * parse_analyze.
*
*
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.46 2000/09/12 21:07:02 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.47 2000/10/07 00:58:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -16,8 +22,6 @@
#include "postgres.h"
#include "nodes/parsenodes.h"
-#include "nodes/pg_list.h"
-#include "parser/analyze.h"
#include "parser/gramparse.h"
#include "parser/parse.h"
#include "parser/parser.h"
@@ -35,19 +39,17 @@ List *parsetree; /* result of parsing is left here */
static int lookahead_token; /* one-token lookahead */
static bool have_lookahead; /* lookahead_token set? */
-#ifdef SETS_FIXED
-static void fixupsets();
-static void define_sets();
-
-#endif
/*
- * parser-- returns a list of parse trees
+ * parser
+ * Given a query in string form, and optionally info about
+ * parameter types, do lexical and syntactic analysis.
+ *
+ * Returns a list of raw (un-analyzed) parse trees.
*/
List *
parser(char *str, Oid *typev, int nargs)
{
- List *queryList;
int yyresult;
parseString = str;
@@ -67,28 +69,9 @@ parser(char *str, Oid *typev, int nargs)
clearerr(stdin);
if (yyresult) /* error */
- return (List *) NULL;
-
- queryList = parse_analyze(parsetree, NULL);
+ return NIL;
-#ifdef SETS_FIXED
-
- /*
- * Fixing up sets calls the parser, so it reassigns the global
- * variable parsetree. So save the real parsetree.
- */
- savetree = parsetree;
- foreach(parse, savetree)
- { /* savetree is really a list of parses */
-
- /* find set definitions embedded in query */
- fixupsets((Query *) lfirst(parse));
-
- }
- return savetree;
-#endif
-
- return queryList;
+ return parsetree;
}
@@ -135,83 +118,3 @@ yylex(void)
return cur_token;
}
-
-
-#ifdef SETS_FIXED
-static void
-fixupsets(Query *parse)
-{
- if (parse == NULL)
- return;
- if (parse->commandType == CMD_UTILITY) /* utility */
- return;
- if (parse->commandType != CMD_INSERT)
- return;
- define_sets(parse);
-}
-
-/* Recursively find all of the Consts in the parsetree. Some of
- * these may represent a set. The value of the Const will be the
- * query (a string) which defines the set. Call SetDefine to define
- * the set, and store the OID of the new set in the Const instead.
- */
-static void
-define_sets(Node *clause)
-{
- Oid setoid;
- Type t = typeidType(OIDOID);
- Oid typeoid = typeTypeId(t);
- Size oidsize = typeLen(t);
- bool oidbyval = typeByVal(t);
-
- if (clause == NULL)
- return;
- else if (IsA(clause, LispList))
- {
- define_sets(lfirst(clause));
- define_sets(lnext(clause));
- }
- else if (IsA(clause, Const))
- {
- if (get_constisnull((Const) clause) ||
- !get_constisset((Const) clause))
- return;
- setoid = SetDefine(((Const *) clause)->constvalue,
- typeidTypeName(((Const *) clause)->consttype));
- set_constvalue((Const) clause, setoid);
- set_consttype((Const) clause, typeoid);
- set_constlen((Const) clause, oidsize);
- set_constypeByVal((Const) clause, oidbyval);
- }
- else if (IsA(clause, Iter))
- define_sets(((Iter *) clause)->iterexpr);
- else if (single_node(clause))
- return;
- else if (or_clause(clause) || and_clause(clause))
- {
- List *temp;
-
- /* mapcan */
- foreach(temp, ((Expr *) clause)->args)
- define_sets(lfirst(temp));
- }
- else if (is_funcclause(clause))
- {
- List *temp;
-
- /* mapcan */
- foreach(temp, ((Expr *) clause)->args)
- define_sets(lfirst(temp));
- }
- else if (IsA(clause, ArrayRef))
- define_sets(((ArrayRef *) clause)->refassgnexpr);
- else if (not_clause(clause))
- define_sets(get_notclausearg(clause));
- else if (is_opclause(clause))
- {
- define_sets(get_leftop(clause));
- define_sets(get_rightop(clause));
- }
-}
-
-#endif