Пример #1
0
 expression_arg<SM>& apply (SM& sm, expression_arg<SM>& out) const
 {
     return apply_append( sm
                        , base_type::left_expr()
                        , base_type::right_expr()
                        , out);
 } 
Пример #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
int apply_follow_next_arc(struct apply_handle *h) {
    char *fname, *fvalue;
    int eatupi, eatupo, symin, symout, fneg;
    int vcount, marksource, marktarget;
    
    /* Here we follow three possible search strategies:        */
    /* (1) if the state in question has an index, we use that  */
    /* (2) if the state is binary searchable, we use that      */
    /* (3) otherwise we traverse arc-by-arc                    */
    /*     Condition (2) needs arcs to be sorted in the proper */
    /*     direction, and requires that the state be flag-free */
    /*     For those states that aren't flag-free, (3) is used */

    if (h->state_has_index) {
	for ( ; h->iptr != NULL && h->iptr->fsmptr != -1; ) {

	    h->ptr = h->curr_ptr = h->iptr->fsmptr;
	    if (((h->mode) & DOWN) == DOWN) {
		symin = (h->gstates+h->curr_ptr)->in;
		symout = (h->gstates+h->curr_ptr)->out;
	    } else {
		symin = (h->gstates+h->curr_ptr)->out;
		symout = (h->gstates+h->curr_ptr)->in;
	    }
	    
	    marksource = *(h->marks+(h->gstates+h->ptr)->state_no);
	    marktarget = *(h->marks+(h->gstates+(*(h->statemap+(h->gstates+h->curr_ptr)->target)))->state_no);
	    eatupi = apply_match_length(h, symin);
	    if (!(eatupi == -1 || -1-(h->ipos)-eatupi == marktarget)) {     /* input 2x EPSILON loop check */
		if ((eatupi = apply_match_str(h, symin, h->ipos)) != -1) {
		    eatupo = apply_append(h, h->curr_ptr, symout);
		    if (h->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;
		    }
		    /* Push old position */
		    apply_stack_push(h, marksource, fname, fvalue, fneg);
		    h->ptr = *(h->statemap+(h->gstates+h->curr_ptr)->target);
		    h->ipos += eatupi;
		    h->opos += eatupo;
		    apply_set_iptr(h);
		    return 1;
		}
	    }
	    h->iptr = h->iptr->next;
	}
	return 0;
    } else if ((h->binsearch && !(h->has_flags)) || (h->binsearch && !(BITTEST(h->flagstates, (h->gstates+h->ptr)->state_no)))) {
	for (;;) {
	    if (apply_binarysearch(h)) {
		if (((h->mode) & DOWN) == DOWN) {
		    symin = (h->gstates+h->curr_ptr)->in;
		    symout = (h->gstates+h->curr_ptr)->out;
		} else {
		    symin = (h->gstates+h->curr_ptr)->out;
		    symout = (h->gstates+h->curr_ptr)->in;
		}
		
		marksource = *(h->marks+(h->gstates+h->ptr)->state_no);
		marktarget = *(h->marks+(h->gstates+(*(h->statemap+(h->gstates+h->curr_ptr)->target)))->state_no);
		
		eatupi = apply_match_length(h, symin);
		if (eatupi != -1 && -1-(h->ipos)-eatupi != marktarget) {
		    if ((eatupi = apply_match_str(h, symin, h->ipos)) != -1) {
			eatupo = apply_append(h, h->curr_ptr, symout);
			
			/* Push old position */
			apply_stack_push(h, marksource, NULL, NULL, 0);
			
			/* Follow arc */
			h->ptr = *(h->statemap+(h->gstates+h->curr_ptr)->target);
			h->ipos += eatupi;
			h->opos += eatupo;
			apply_set_iptr(h);
			return 1;
		    }
		}
		if ((h->gstates+h->curr_ptr)->state_no == (h->gstates+h->curr_ptr+1)->state_no) {
		    h->curr_ptr++; 
		    h->ptr = h->curr_ptr;
		    if ((h->gstates+h->curr_ptr)-> target == -1) { 
			return 0; 
		    }
		    continue;
		}
	    }
	    return 0;
	}
    } else {
	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)++) {
	    
	    /* 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;
		}
	    }
	    
	    if (((h->mode) & DOWN) == DOWN) {
		symin = (h->gstates+h->curr_ptr)->in;
		symout = (h->gstates+h->curr_ptr)->out;
	    } else {
		symin = (h->gstates+h->curr_ptr)->out;
		symout = (h->gstates+h->curr_ptr)->in;
	    }
	    
	    marksource = *(h->marks+(h->gstates+h->ptr)->state_no);
	    marktarget = *(h->marks+(h->gstates+(*(h->statemap+(h->gstates+h->curr_ptr)->target)))->state_no);

	    eatupi = apply_match_length(h, symin);

	    if (eatupi == -1 || -1-(h->ipos)-eatupi == marktarget) { continue; } /* loop check */
	    if ((eatupi = apply_match_str(h, symin, h->ipos)) != -1) {
		eatupo = apply_append(h, h->curr_ptr, symout);
		if (h->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;
		}
		
		/* Push old position */
		apply_stack_push(h, marksource, fname, fvalue, fneg);
		
		/* Follow arc */
		h->ptr = *(h->statemap+(h->gstates+h->curr_ptr)->target);
		h->ipos += eatupi;
		h->opos += eatupo;
		apply_set_iptr(h);
		return(1);
	    }
	}
	return(0);
    }
}