C:/Users/Dennis/src/lang/bertrand/BERTRAND/bertrand/rules.c

Go to the documentation of this file.
00001 /************************************************************
00002  *
00003  * Routines to manage rules
00004  *
00005  ************************************************************/
00006 
00007 #include "def.h"
00008 int label_count;                /* number of label names in a rule */
00009 
00010 /*****************************************************************
00011  *
00012  * Compare two pattern expressions to determine which is "more specific".
00013  * In general, a pattern is more specific if it matches a subset of
00014  * the expressions matched by another pattern.  We require, however,
00015  * that two expressions are equally specific ONLY if they are the same
00016  * expression, so we need to set up a total ordering out of this partial
00017  * ordering.
00018  *
00019  * returns:
00020  *      1 if A is more specific than B
00021  *      -1 if B is more specific than A
00022  *      0 if they are equally specific
00023  *
00024  *
00025  *  An untyped parameter (which matches anything) is less specific
00026  *  than anything else.
00027  *  An operator or type is more specific than a supertype.
00028  *  A term is more specific than a parameter.
00029  *  compare the precedence of operator A to the precedence of operator B
00030  *  compare the address of operator A to the address of operator B
00031  *
00032  * If the two operators the same, then compare their arguments.
00033  *
00034  *****************************************************************/
00035 static int
00036 more_specific(A, B)
00037 NODE *A, *B;
00038 {
00039 extern OP *untyped_prim;        /* from primitive.c */
00040 extern OP *undeclared_prim;     /* from primitive.c */
00041 extern OP *positive_type, *nonzero_type;        /* from primitive.c */
00042 register OP *opa = A->op;
00043 register OP *opb = B->op;
00044 register OP *sop;
00045 
00046 if (opa != opb) {
00047     if (opb == untyped_prim) return 1;
00048     if (opa == untyped_prim) return -1;
00049     for (sop = opa->super; sop; sop = sop->super) if (sop == opb) return 1;
00050     for (sop = opb->super; sop; sop = sop->super) if (sop == opa) return -1;
00051     if (opb->arity == OP_NAME && opa->arity != OP_NAME) return 1;
00052     if (opa->arity == OP_NAME && opb->arity != OP_NAME) return -1;
00053     if (opa->precedence > opb->precedence) return 1;
00054     if (opa->precedence < opb->precedence) return -1;
00055     if (opa > opb) return 1;
00056     if (opa < opb) return -1;
00057     }
00058 /* same operator */
00059 if (opa->arity == NULLARY) return 0;
00060 if ((opa->arity & BINARY) || (opa->arity & UNARY)) {
00061     if ((opa->arity & BINARY) || (opa->arity == POSTFIX))
00062         return more_specific(((TERM_NODE *)A)->left, ((TERM_NODE *)B)->left);
00063     if (opa->arity != POSTFIX)
00064         return more_specific(((TERM_NODE *)A)->right, ((TERM_NODE *)B)->right);
00065     }
00066 return 0;
00067 }
00068 
00069 /************************************************************
00070  *
00071  * Build a rule, and insert it as the hash value of the
00072  * root operator of the head expression.
00073  * Return a pointer to the rule, in case someone wants to
00074  * print it, or something.
00075  *
00076  * TO DO: shouldn't use malloc direcly.
00077  *
00078  ************************************************************/
00079 RULE *
00080 rule_build(head, body, tag, names)
00081 NODE *head, *body;
00082 OP *tag;
00083 NAME_NODE *names;               /* local name space */
00084 {
00085 char *malloc();
00086 void rule_print();              /* forward reference */
00087 register RULE *rr;
00088 RULE *cr, *pr = NULL;           /* used to insert rule into list */
00089 int cmp;
00090 static int rule_verbose = -1;
00091 
00092 if (!(head->op->arity & OP_TERM)) {
00093     error("head of rule must be an expression");
00094     }
00095 rr = (RULE *) malloc(sizeof(RULE));
00096 rr->head = head;
00097 rr->body = body;
00098 rr->tag = tag;
00099 rr->space = names;
00100 rr->size = label_count;         /* number of label names */
00101 
00102 if (rule_verbose == -1) rule_verbose = verbose;
00103 if (rule_verbose) {
00104     rr->verbose = 1;
00105     rule_print(rr);
00106     }
00107 else rr->verbose = 0;
00108 rule_verbose = verbose;
00109 
00110 cr = head->op->hash;
00111 if (cr == NULL) {       /* no rules for this op */
00112     rr->next = NULL;
00113     head->op->hash = rr;
00114     return rr;
00115     }
00116 while (cr) {
00117     if (1 == more_specific(rr->head, cr->head)) {       /* insert here */
00118         rr->next = cr;
00119         if (pr) pr->next = rr;
00120         else head->op->hash = rr;
00121         return rr;
00122         }
00123     pr = cr;
00124     cr = cr->next;
00125     }
00126 pr->next = rr;
00127 rr->next = NULL;
00128 return rr;
00129 }
00130 
00131 /************************************************************
00132  *
00133  * Free a rule.
00134  *
00135  ************************************************************/
00136 void rule_free(rr)
00137 RULE *rr;
00138 {
00139 void expr_free();       /* from expr.c */
00140 
00141 expr_free(rr->head);
00142 expr_free(rr->body);
00143 name_free(rr->space);
00144 free((char *)rr);
00145 }
00146 
00147 /************************************************************
00148  *
00149  * Print out a rule.
00150  *
00151  ************************************************************/
00152 void rule_print(rp)
00153 RULE *rp;
00154 {
00155 void expr_print();              /* from expr.c */
00156 void name_space_print();        /* from names.c */
00157 
00158 expr_print(rp->head);
00159 fprintf(stderr, " { ");
00160 expr_print(rp->body);
00161 fprintf(stderr, " }");
00162 if (rp->tag) fprintf(stderr, " '%s", rp->tag->pname);
00163 fprintf(stderr, "\t");
00164 name_space_print(rp->space);
00165 fprintf(stderr, "\n");
00166 }

Generated on Fri Jan 25 09:58:43 2008 for Bertrand by  doxygen 1.5.4