示例#1
0
char *apply_random_upper(struct apply_handle *h) {
    apply_clear_flags(h);
    h->mode = DOWN + ENUMERATE + UPPER + RANDOM;
    return(apply_enumerate(h));
}
示例#2
0
char *apply_net(struct apply_handle *h) {

    char *fname, *fvalue;
    int eatupi, eatupo, symin, symout, f, fneg; 
    int vcount, msource, mtarget;
    
/*     We perform a basic DFS on the graph, with two minor complications:       */

/*     1. We keep a mark for each state which indicates whether it is seen      */
/*        on the current "run."  If we reach a marked state, we terminate.      */
/*        As we pop a position, we also unmark the state we came from.          */
/*        If we're matching against a string, we terminate if the mark          */
/*        is set and ipos is the same as last time we saw the flag, i.e.        */
/*        we've traversed a loop without consuming an input symbol              */
 
/*     2. If the graph has flags, we push the previous flag value when          */
/*        traversing a flag-modifying arc.  This is because a flag may          */
/*        may have been set during the previous "run" and may not apply.        */
/*        Since we're doing a DFS, we can be sure to return to the previous     */
/*        global flag state by just remembering that last flag change.          */
    
    /* If called with NULL as the input word, this will be set */
    if (h->iterate_old == 1) {
        goto resume;
    }

    h->ptr = 0; h->ipos = 0; h->opos = 0;
    apply_stack_clear(h);

    if (h->has_flags) {
	apply_clear_flags(h);
    }
    
    /* "The use of four-letter words like goto can occasionally be justified */
    /*  even in the best of company." Knuth (1974). */

    goto L2;

    while(!apply_stack_isempty(h)) {
	
	apply_stack_pop(h);

	/* Last line */
	if ((h->gstates+h->ptr)->state_no != (h->gstates+h->ptr+1)->state_no) {
	    /* Restore mark */
	    *(h->marks+(h->gstates+h->ptr)->state_no) = 0;
	    continue;
	}
	(h->ptr)++;

	/* Follow arc & push old position */

    L1:
	for (f=0,h->curr_ptr = h->ptr; (h->gstates+h->curr_ptr)->state_no == (h->gstates+h->ptr)->state_no && (h->gstates+h->curr_ptr)-> in != -1; (h->curr_ptr)++) {
	    f = 0;

	    /* Select one random arc to follow out of all outgoing arcs */

	    if ((h->mode & RANDOM) == RANDOM) {
		vcount = 0;
		for (h->curr_ptr = h->ptr;  (h->gstates+h->curr_ptr)->state_no == (h->gstates+h->ptr)->state_no && (h->gstates+h->curr_ptr)-> in != -1; (h->curr_ptr)++) {
		    vcount++;
		}
		if (vcount > 0) {
		  h->curr_ptr = h->ptr + (rand() % vcount) ;
		} else {
		  h->curr_ptr = h->ptr;
		}
	    }

	    symin  = (((h->mode)&DOWN) == DOWN) ? (h->gstates+h->curr_ptr)->in  : (h->gstates+h->curr_ptr)->out;
	    symout = (((h->mode)&DOWN) == DOWN) ? (h->gstates+h->curr_ptr)->out : (h->gstates+h->curr_ptr)->in;
	    
	    msource = *(h->marks+(h->gstates+h->ptr)->state_no);
	    mtarget = *(h->marks+(h->gstates+(*(h->statemap+(h->gstates+h->curr_ptr)->target)))->state_no);
	    
	    if (((eatupi = apply_match_str(h, symin, h->ipos)) != -1) && -1-(h->ipos)-eatupi != mtarget) {
		eatupo = apply_append(h, h->curr_ptr, symout);
		if (g_obey_flags && h->has_flags && ((h->flag_lookup+symin)->type & (FLAG_UNIFY|FLAG_CLEAR|FLAG_POSITIVE|FLAG_NEGATIVE))) {
                    fname = (h->flag_lookup+symin)->name;
		    fvalue = h->oldflagvalue;
		    fneg = h->oldflagneg;

		} else {
		    fname = fvalue = NULL;
		    fneg = 0;
		}
		
                apply_stack_push(h, h->curr_ptr, h->ipos, h->opos, msource, fname, fvalue, fneg);

		f = 1;
                h->ptr = *(h->statemap+(h->gstates+h->curr_ptr)->target);
		h->ipos = (h->ipos)+eatupi;
		h->opos = (h->opos)+eatupo;
		break;
	    } 
	}

	/* There were no more edges on this vertex? */
	if (!f) {
	    /* Unmark? */
	    *(h->marks+(h->gstates+h->ptr)->state_no) = 0;
	    continue;
	}
	
	/* Print accumulated string */

    L2:
	if ((h->gstates+h->ptr)->final_state == 1 && ((((h->mode) & ENUMERATE) == ENUMERATE) || (h->ipos == h->current_instring_length))) {
            /* Stick a 0 to endpos to avoid getting old accumulated gunk strings printed */
            *(h->outstring+h->opos) = '\0';
	    if (((h->mode) & RANDOM) == RANDOM) {
		/* To end or not to end */
		if (!(rand() % 2)) {
		    apply_stack_clear(h);
		    h->iterator = 0;
		    h->iterate_old = 0;
                    return(h->outstring);
		}
            } else {
		return(h->outstring);
            }
        }

    resume:
	
	/* Mark */
	/* 0 = unseen, +ipos = seen at ipos, -ipos = seen second time at ipos */
	if ((h->mode & RANDOM) != RANDOM) {
	    if (*(h->marks+(h->gstates+h->ptr)->state_no) == h->ipos+1) {
		*(h->marks+(h->gstates+h->ptr)->state_no) = -(h->ipos+1);
	    } else {
		*(h->marks+(h->gstates+h->ptr)->state_no) = h->ipos+1;
	    }
	}
	goto L1;
    }
    /* Catch unprinted random which didn't stop at a final state */
    if ((h->mode & RANDOM) == RANDOM) {
	  apply_stack_clear(h);
	  h->iterator = 0;
	  h->iterate_old = 0;
          return(h->outstring);    
    }
    apply_stack_clear(h);
    return NULL;
}
示例#3
0
文件: apply.c 项目: JSefara/foma
char *apply_net(struct apply_handle *h) {

/*     We perform a basic DFS on the graph, with two minor complications:       */

/*     1. We keep a mark for each state which indicates how many input symbols  */
/*        we had consumed the last time we entered that state on the current    */
/*        "run."  If we reach a state seen twice without consuming input, we    */
/*        terminate that branch of the search.                                  */
/*        As we pop a position, we also unmark the state we came from.          */
 
/*     2. If the graph has flags, we push the previous flag value when          */
/*        traversing a flag-modifying arc (P,U,N, or C).  This is because a     */
/*        flag may have been set during the previous "run" and may not apply.   */
/*        Since we're doing a DFS, we can be sure to return to the previous     */
/*        global flag state by just remembering that last flag change.          */

/*     3. The whole system needs to work as an iterator, meaning we need to     */
/*        store the global state of the search so we can resume it later to     */
/*        to yield more possible output words with the same input string.       */

    char *returnstring;

    if (h->iterate_old == 1) {     /* If called with NULL as the input word, this will be set */
        goto resume;
    }

    h->iptr = NULL; h->ptr = 0; h->ipos = 0; h->opos = 0;
    apply_set_iptr(h);

    apply_stack_clear(h);

    if (h->has_flags) {
	apply_clear_flags(h);
    }
    
    /* "The use of four-letter words like goto can occasionally be justified */
    /*  even in the best of company." Knuth (1974).                          */

    goto L2;

    while(!apply_stack_isempty(h)) {
	apply_stack_pop(h);
	/* If last line was popped */
	if (apply_at_last_arc(h)) {
	    *(h->marks+(h->gstates+h->ptr)->state_no) = 0; /* Unmark   */
	    continue;                                      /* pop next */
	}
	apply_skip_this_arc(h);                            /* skip old pushed arc */
    L1:
	if (!apply_follow_next_arc(h)) {
	    *(h->marks+(h->gstates+h->ptr)->state_no) = 0; /* Unmark   */
	    continue;                                      /* pop next */
	}
    L2:
	/* Print accumulated string upon entry to state */
	if ((h->gstates+h->ptr)->final_state == 1 && (h->ipos == h->current_instring_length || ((h->mode) & ENUMERATE) == ENUMERATE)) {
	    if ((returnstring = (apply_return_string(h))) != NULL) {
		return(returnstring);
	    }
	}

    resume:
       	apply_mark_state(h);  /* Mark upon arrival to new state */
	goto L1;
    }
    if ((h->mode & RANDOM) == RANDOM) {
          apply_stack_clear(h);
          h->iterator = 0;
          h->iterate_old = 0;
          return(h->outstring);
    }
    apply_stack_clear(h);
    return NULL;
}