/* Zz Dynamic Parser Library Copyright (C) 1989 - I.N.F.N - S.Cabasino, P.S.Paolucci, G.M.Todesco The Zz Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The Zz Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /*============================================================================== rule.C () gestione non-terminali: struct s_nt *start_symbol; struct s_nt *find_nt(); () per creare una regola: open_rule(headname); append_bead(cnt,name); append_t_bead(cnt); append_nt_bead(ntname,name); setaction_exelist(list); setaction_exeproc(proc); setaction_exesproc(proc); setaction_return(value); setaction_pass(proc); setaction_list(proc); setaction_merge_all(proc); setaction_merge(proc); setaction_append(proc); rule=close_rule(); () per distruggere una regola: free_rule(rule); ==============================================================================*/ #include #include #include "avl.h" #include "rule.h" #include "list.h" #include "err.h" #include "mem.h" #include "trace.h" #include "table.h" #include "printz.h" static int nt_mem=0; static int rule_mem=0; struct s_nt *nt_any=0,*nt_param=0,*nt_gparam; /* forwards, now exported in rule.h */ /*void init_rule();*/ /*void free_rule(struct s_rule *);*/ /*----------------------------------------------------------------------------*/ /* extern struct s_dot *create_dot(); */ /* now in table.h extern int link_rule(),unlink_rule(); */ struct s_nt *start_symbol=0; /*----------------------------------------------------------------------------*/ static TREE *nttree=0; static struct s_rule *cur_rule=0,*last_rule=0; #define RULES_SIZE 100 static TREE *rules[RULES_SIZE]; static int rules_sp=1; static int init_rule_done=0; int kernel_flag=1; struct s_rule_class { char *name; TREE *rules; }; TREE *rule_classes=0; /*----------------------------------------------------------------------------*/ void zz_set_kernel_flag(int bool_value) { kernel_flag = bool_value; } /*----------------------------------------------------------------------------*/ struct s_nt *find_nt(char *name) { struct s_nt *nt; zz_assert(name); if(!nttree) { nttree = avl_tree_nodup_str (struct s_nt, name); nt_param=find_nt("param"); nt_gparam=find_nt("gparam"); nt_any=find_nt("any"); } nt = avl_locate(nttree,name); if(!nt) { nt = (struct s_nt*)calloc(1,sizeof(struct s_nt)); nt->name = (char*)malloc(strlen(name)+1); nt_mem+=sizeof(struct s_nt)+strlen(name)+1; strcpy(nt->name,name); nt->prompt=0; avl_insert(nttree,nt); nt->first_dot = 0; } return nt; } /*----------------------------------------------------------------------------*/ int rulecmp(struct s_rule *r1,struct s_rule *r2) { int i; zz_assert(r1 && r2); for(i=0;ibead_n && ibead_n;i++) { if(r1->beads[i].cnt.tag < r2->beads[i].cnt.tag) return -1; else if(r1->beads[i].cnt.tag > r2->beads[i].cnt.tag) return 1; else if(s_content_value(r1->beads[i].cnt) < s_content_value(r2->beads[i].cnt)) return -1; else if(s_content_value(r1->beads[i].cnt) > s_content_value(r2->beads[i].cnt)) return 1; } if(ibead_n) return -1; else if(ibead_n) return 1; else return 0; } /*----------------------------------------------------------------------------*/ void open_rule(char *ntname) { struct s_content tmp1,tmp2; zz_assert(ntname); tmp1.tag = tag_ident; s_content_value(tmp1) = (long)ntname; param_substitute(&tmp1,&tmp2); ntname = (char*)s_content_value(tmp1); if(!init_rule_done) init_rule(); if(cur_rule) free_rule(cur_rule); cur_rule = (struct s_rule *)calloc(1,sizeof(struct s_rule)); rule_mem += sizeof(struct s_rule); cur_rule->bead_n=1; cur_rule->beads = (struct s_bead*) calloc(MAX_RULE_LENGTH,sizeof(struct s_bead)); cur_rule->bead_size = MAX_RULE_LENGTH; rule_mem += sizeof(struct s_bead)*cur_rule->bead_size; cur_rule->beads[0].cnt.tag=tag_sint; s_content_value(cur_rule->beads[0].cnt)=(long)find_nt(ntname); cur_rule->beads[0].name=0; cur_rule->cnt_prec.tag = tag_sint; s_content_value(cur_rule->cnt_prec) = 0; cur_rule->when_exit_scope.tag = 0; cur_rule->when_change_action.tag = 0; cur_rule->kernel=kernel_flag; } /*---------------------------------------------------------------------------*/ void setaction_exelist(struct s_content *list) { zz_assert(list); if(!cur_rule) {zz_error(INTERNAL_ERROR, "setaction: rule not open\n");return;} if(list->tag!=tag_list) { zz_error(INTERNAL_ERROR, "setaction_exelist. argument is not a list\n"); return; } cur_rule->action_type = ACT_T_EXECUTE_LIST; cur_rule->action = *list; cur_rule->sproc_tag = 0; } /*----------------------------------------------------------------------------*/ void setaction_exeproc(int (*proc)(), struct s_tag *tag) { zz_assert(proc); //zz_assert(tag); if(!cur_rule) {zz_error(INTERNAL_ERROR, "setaction: rule not open\n");return;} cur_rule->action_type = ACT_T_EXECUTE_PROC; cur_rule->action.tag = tag_procedure; s_content_value(cur_rule->action) = (long)proc; cur_rule->sproc_tag = tag; } /*----------------------------------------------------------------------------*/ void setaction_exesproc(int (*sproc)(), struct s_tag *tag) { zz_assert(sproc && tag); if(!cur_rule) {zz_error(INTERNAL_ERROR, "setaction: rule not open\n");return;} cur_rule->action_type = ACT_T_EXECUTE_SPROC; cur_rule->action.tag = tag_procedure; s_content_value(cur_rule->action) = (long)sproc; cur_rule->sproc_tag = tag; } /*---------------------------------------------------------------------------*/ void setaction_return(struct s_content *value, char *tag_name) { //struct s_tag *find_tag(); zz_assert(value); // Cannot assert tag_name or else statements // like "/float -> foo float^n : return n" fail. // zz_assert(tag_name); if(!cur_rule) {zz_error(INTERNAL_ERROR, "rule not open\n");return;} cur_rule->action_type = ACT_T_RETURN; cur_rule->action = *value; cur_rule->sproc_tag = (tag_name)?find_tag(tag_name):0; } /*----------------------------------------------------------------------------*/ void setaction_pass() { if(!cur_rule) {zz_error(INTERNAL_ERROR, "setaction: rule not open\n");return;} cur_rule->action_type = ACT_T_PASS; cur_rule->action.tag = 0; s_content_value(cur_rule->action) = 0; cur_rule->sproc_tag = 0; } /*---------------------------------------------------------------------------*/ void setaction_rreturn() { if(!cur_rule) {zz_error(INTERNAL_ERROR, "setaction: rule not open\n");return;} cur_rule->action_type = ACT_T_RRETURN; cur_rule->action.tag = 0; s_content_value(cur_rule->action) = 0; cur_rule->sproc_tag = 0; } /*---------------------------------------------------------------------------*/ void setaction_assign() { if(!cur_rule) {zz_error(INTERNAL_ERROR, "setaction: rule not open\n");return;} cur_rule->action_type = ACT_T_ASSIGN; cur_rule->action.tag = 0; s_content_value(cur_rule->action) = 0; cur_rule->sproc_tag = 0; } /*----------------------------------------------------------------------------*/ void setaction_list() { if(!cur_rule) {zz_error(INTERNAL_ERROR, "setaction: rule not open\n");return;} cur_rule->action_type = ACT_T_LIST; cur_rule->action.tag = 0; s_content_value(cur_rule->action) = 0; cur_rule->sproc_tag = 0; } /*----------------------------------------------------------------------------*/ void setaction_merge_all() { if(!cur_rule) {zz_error(INTERNAL_ERROR, "setaction: rule not open\n");return;} cur_rule->action_type = ACT_T_MERGE_ALL; cur_rule->action.tag = 0; s_content_value(cur_rule->action) = 0; cur_rule->sproc_tag = 0; } /*----------------------------------------------------------------------------*/ void setaction_merge() { if(!cur_rule) {zz_error(INTERNAL_ERROR, "setaction: rule not open\n");return;} cur_rule->action_type = ACT_T_MERGE; cur_rule->action.tag = 0; s_content_value(cur_rule->action) = 0; cur_rule->sproc_tag = 0; } /*----------------------------------------------------------------------------*/ void setaction_append() { if(!cur_rule) {zz_error(INTERNAL_ERROR, "setaction: rule not open\n");return;} cur_rule->action_type = ACT_T_APPEND; cur_rule->action.tag = 0; s_content_value(cur_rule->action) = 0; cur_rule->sproc_tag = 0; } /*----------------------------------------------------------------------------*/ struct s_rule *close_rule() { int i; struct s_rule *rule; struct s_bead *beads; if(!cur_rule) { zz_error(ERROR,"close_rule: rule not open"); return 0; } rule = cur_rule; cur_rule = 0; beads = rule->beads; rule->beads = (struct s_bead*) calloc(rule->bead_n,sizeof(struct s_bead)); rule_mem+=sizeof(struct s_bead)*(rule->bead_n-rule->bead_size); rule->bead_size=rule->bead_n; for(i=0;ibead_n;i++) rule->beads[i]=beads[i]; free(beads); rule->segment_id=0; return rule; } /*----------------------------------------------------------------------------*/ void append_bead(struct s_content *cnt, char *name) { int i; if(!cur_rule) { zz_error(ERROR,"append_bead: rule not open"); return; } if(cur_rule->bead_n>=MAX_RULE_LENGTH) { zz_error(ERROR,"append_bead: rule too long"); return; } i=cur_rule->bead_n++; cur_rule->beads[i].cnt = *cnt; cur_rule->beads[i].name = name; if(cnt->tag==tag_qstring || cnt->tag==tag_ident || cnt->tag==tag_char) cur_rule->cnt_prec = *cnt; } /*----------------------------------------------------------------------------*/ void append_t_bead(struct s_content *cnt) { char *s; struct s_content tmp; if(cnt->tag==tag_qstring) { s = (char*)s_content_value(*cnt); while(*s==' ' || *s=='\t')s++; while(*s) { zlex(&s,&tmp); append_t_bead(&tmp); while(*s==' ' || *s=='\t')s++; } } else append_bead(cnt,0); } /*----------------------------------------------------------------------------*/ void append_nt_bead(char *ntname, char *beadname) { struct s_content tmp; static char *dollar=0; if(!beadname) { if(!dollar) dollar = zlex_strsave("$"); beadname = dollar; } tmp.tag = tag_sint; s_content_value(tmp) = (long)find_nt(ntname); append_bead(&tmp,beadname); } /*============================================================================*/ static int fprint_rule(FILE *chan, void *_rule) { int i; struct s_nt *nt; struct s_rule *rule = (struct s_rule *)_rule; if(!rule) fprintz(chan,"(nil)"); else if(rule->bead_n<0) fprintz(chan,"(nil)-> "); else { nt = (struct s_nt*) s_content_value(rule->beads[0].cnt); fprintz(chan,"%s ->",nt->name); for(i=1;ibead_n;i++) { if(rule->beads[i].cnt.tag==tag_sint) fprintz(chan," %s^%s", ((struct s_nt*)s_content_value(rule->beads[i].cnt))->name, rule->beads[i].name); else fprintz(chan," %z",&rule->beads[i].cnt); } } return 1; } /*----------------------------------------------------------------------------*/ static int sprint_rule(char* buffer, void *_rule) { struct s_nt *nt; int i; char *s; struct s_rule *rule=(struct s_rule *)_rule; if(!rule) strcpy(buffer,"(nil)"); else if(rule->bead_n<0) strcpy(buffer,"(nil)-> "); else { nt = (struct s_nt*) s_content_value(rule->beads[0].cnt); strcpy(buffer,nt->name); strcat(buffer," ->"); s = buffer+strlen(buffer); for(i=1;ibead_n;i++) { if(rule->beads[i].cnt.tag==tag_sint) sprintz(s," %s^%s", ((struct s_nt*)s_content_value(rule->beads[i].cnt))->name, rule->beads[i].name); else sprintz(s," %z",&rule->beads[i].cnt); while(*s)s++; } } return 1; } /*----------------------------------------------------------------------------*/ void print_rule(struct s_rule *rule) { printz(" %r\n",rule); } /*----------------------------------------------------------------------------*/ void init_rule() { if(init_rule_done) return; init_rule_done=1; printz_code('r',fprint_rule,sprint_rule); } /*----------------------------------------------------------------------------*/ static int do_delete_scope_action(rule) struct s_rule *rule; { zz_trace("do_delete_scope_action()\n"); if(rule->when_exit_scope.tag==tag_list) { source_list(&rule->when_exit_scope); parse(find_nt("root")); pop_source(); zz_trace("do_delete_scope_action() exit scope (%r): %z\n",rule,&rule->when_exit_scope); } } void free_rule(void *_rule /*, void *dummy_param*/) { struct s_rule *rule = (struct s_rule *)_rule; do_delete_scope_action(rule); rule_mem-=sizeof(struct s_rule)-sizeof(struct s_bead)*rule->bead_size; free(rule->beads); free(rule); } /*============================================================================*/ void show_rule_memory() { PRINTMEM("rule",rule_mem); PRINTMEM("non-terminal",nt_mem); } /*============================================================================*/ /* azioni: sproc_tag action_type action.tag action : ACT_T_EXECUTE_PROC tag_procedure saction : tag_xxx ACT_T_EXECUTE_SPROC tag_procedure pass : ACT_T_PASS list : ACT_T_LIST append : ACT_T_APPEND ret/proc: ACT_T_RETURN tag_procedure */ static char rcsid[] = "$Id: rule.c,v 1.18 2002/06/03 11:06:13 kibun Exp $ ";