/** * Returns 1 if there is something more to do after this call or 0 if: * - no new information was found * - the main graph matches E */ static int resolve_all_conditions(GrfCheckInfo* chk,struct list_int* *list,int *unknown) { *unknown=0; struct list_int* new_list=NULL; for (int i=1;i<chk->fst2->number_of_graphs+1;i++) { if (chk->graphs_matching_E[i]==CHK_DONT_KNOW) { /* We only need to look at the graphs we are not sure about yet */ resolve_conditions(chk,i,*list); chk->graphs_matching_E[i]=get_status(chk->condition_graphs[i]); if (chk->graphs_matching_E[i]!=CHK_DONT_KNOW) { /* If we have found an answer, we note that graph #i must be * looked at on the next loop */ new_list=new_list_int(i,new_list); } else { /* The graph is still unknown */ (*unknown)++; } } } /* Now we can use the new list */ free_list_int(*list); *list=new_list; if (chk->graphs_matching_E[1]==CHK_MATCHES_E) { error("Main graph matches epsilon!\n"); return 0; } return ((*list)!=NULL && (*unknown)!=0); }
/** * Returns 1 if the given .fst2 is OK to be used by the Locate program; 0 otherwise. * Conditions are: * * 1) no left recursion * 2) no loop that can recognize the empty word (<E> with an output or subgraph * that can match the empty word). */ int OK_for_Locate_write_error(const char* name,char no_empty_graph_warning,U_FILE* ferr) { ConditionList* conditions; ConditionList* conditions_for_state; int i,j; int ERROR=0; struct FST2_free_info fst2_free; Fst2* fst2=load_abstract_fst2(name,1,&fst2_free); if (fst2==NULL) { fatal_error("Cannot load graph %s\n",name); } u_printf("Recursion detection started\n"); int* graphs_matching_E=(int*)malloc(sizeof(int)*(fst2->number_of_graphs+1)); conditions=(ConditionList*)malloc(sizeof(ConditionList)*(fst2->number_of_graphs+1)); if (graphs_matching_E==NULL || conditions==NULL) { fatal_alloc_error("OK_for_Locate"); } for (i=0;i<fst2->number_of_graphs+1;i++) { graphs_matching_E[i]=0; conditions[i]=NULL; } /* First, we look for tags that match the empty word <E> */ for (i=0;i<fst2->number_of_tags;i++) { check_epsilon_tag(fst2->tags[i]); } /* Then, we look for graphs that match <E> with or without conditions */ for (i=1;i<=fst2->number_of_graphs;i++) { conditions_for_state=(ConditionList*)malloc(sizeof(ConditionList)*fst2->number_of_states_per_graphs[i]); if (conditions_for_state==NULL) { fatal_alloc_error("OK_for_Locate"); } for (j=0;j<fst2->number_of_states_per_graphs[i];j++) { conditions_for_state[j]=NULL; } graphs_matching_E[i]=graph_matches_E(fst2->initial_states[i],fst2->initial_states[i], fst2->states,fst2->tags,i,fst2->graph_names, conditions_for_state,&conditions[i]); /* If any, we remove the temp conditions */ if (conditions[i]!=NULL) free_ConditionList(conditions[i]); /* And we way that the conditions for the current graph are its initial * state's ones. */ conditions[i]=conditions_for_state[0]; /* Then we perform cleaning */ conditions_for_state[0]=NULL; for (j=1;j<fst2->number_of_states_per_graphs[i];j++) { free_ConditionList(conditions_for_state[j]); } free(conditions_for_state); } /* Then, we use all our condition lists to determine which graphs match <E>. * We iterate until we find a fixed point. If some conditions remain non null * after this loop, it means that there are <E> dependencies between graphs * and this case will be dealt with later. */ u_printf("Resolving <E> conditions\n"); while (resolve_conditions(conditions,fst2->number_of_graphs, fst2->states,fst2->initial_states,ferr)) {} if (is_bit_mask_set(fst2->states[fst2->initial_states[1]]->control,UNCONDITIONAL_E_MATCH)) { /* If the main graph matches <E> */ if (!no_empty_graph_warning) { error("ERROR: the main graph %S recognizes <E>\n",fst2->graph_names[1]); if (ferr != NULL) u_fprintf(ferr,"ERROR: the main graph %S recognizes <E>\n",fst2->graph_names[1]); } ERROR=1; } if (!ERROR) { for (i=1;i<fst2->number_of_graphs+1;i++) { if (is_bit_mask_set(fst2->states[fst2->initial_states[i]]->control,UNCONDITIONAL_E_MATCH)) { /* If the graph matches <E> */ if (!no_empty_graph_warning) { error("WARNING: the graph %S recognizes <E>\n",fst2->graph_names[i]); if (ferr != NULL) u_fprintf(ferr,"WARNING: the graph %S recognizes <E>\n",fst2->graph_names[i]); } } } } clean_controls(fst2,graphs_matching_E); if (!ERROR) { u_printf("Looking for <E> loops\n"); for (i=1;!ERROR && i<fst2->number_of_graphs+1;i++) { ERROR=look_for_E_loops(i,fst2,graphs_matching_E,ferr); } } clean_controls(fst2,NULL); if (!ERROR) { u_printf("Looking for infinite recursions\n"); for (i=1;!ERROR && i<fst2->number_of_graphs+1;i++) { ERROR=look_for_recursion(i,NULL,fst2,graphs_matching_E,ferr); } } for (i=1;i<fst2->number_of_graphs+1;i++) { free_ConditionList(conditions[i]); } free_abstract_Fst2(fst2,&fst2_free); u_printf("Recursion detection completed\n"); free(conditions); free(graphs_matching_E); if (ERROR) return LEFT_RECURSION; return NO_LEFT_RECURSION; }