/* Pattern matching routines */ #include "evalint.h" pattern *make_pattern(expr) char *expr; { register pattern *pat; if (pat = ALLOC(pattern)) { if (pat->val = compile(expr)) { init_var_list(&pat->vl); if (make_var_list(pat->val, &pat->vl)) return(pat); free_expr(pat->val); } } return(NULL); } void free_pattern(pat) pattern *pat; { free_expr(pat->val); free_var_list(&pat->vl); FREE(pattern, pat); } /* The actual recursive pattern matcher */ static int _match_pattern(pat, expr) register value pat; register value expr; { if (pat->type == var) /* Variable in pattern */ { value val; val = get_var(&pat->vr); if (val == NULL) /* uninstantiated ==> can be anything */ { set_var(&pat->vr, expr); return(TRUE); } else /* instantiated ==> must be the same as last time */ return(same(val, expr)); } /* For everything else, an exact match */ else if (pat->type != expr->type) return(FALSE); else switch (pat->type) { case cste: return(pat->cte == expr->cte); case fonc: return(pat->fn.func == expr->fn.func && _match_pattern(pat->fn.arg, expr->fn.arg)); case op: return(pat->opr.op == expr->opr.op && _match_pattern(pat->opr.arg1, expr->opr.arg1) && _match_pattern(pat->opr.arg2, expr->opr.arg2)); } } /* Matches a pattern to a value */ /* returns TRUE if matches, FALSE otherwise */ /* If TRUE, the variables used in the var_list will contain what they matched */ /* Don't forget to free them ! */ int match_pattern(pat, expr) pattern *pat; value expr; { /* This makes sure the pattern variables don't interfere with the variables used in the expression */ if (create_vars(&pat->vl)) { if (_match_pattern(pat->val, expr)) return(TRUE); free_vars(&pat->vl); /* Not matched, free vars */ } return(FALSE); }