⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 regc_nfa.c

📁 从一个开源软件中摘取的正则表达式模块
💻 C
📖 第 1 页 / 共 3 页
字号:
	struct arc *a;	assert(old != new);	for (a = old->outs; a != NULL; a = a->outchain)		cparc(nfa, a, new, a->to);}/* * cloneouts - copy out arcs of a state to another state pair, modifying type */static voidcloneouts(struct nfa * nfa,		  struct state * old,		  struct state * from,		  struct state * to,		  int type){	struct arc *a;	assert(old != from);	for (a = old->outs; a != NULL; a = a->outchain)		newarc(nfa, type, a->co, from, to);}/* * delsub - delete a sub-NFA, updating subre pointers if necessary * * This uses a recursive traversal of the sub-NFA, marking already-seen * states using their tmp pointer. */static voiddelsub(struct nfa * nfa,	   struct state * lp,		/* the sub-NFA goes from here... */	   struct state * rp)		/* ...to here, *not* inclusive */{	assert(lp != rp);	rp->tmp = rp;				/* mark end */	deltraverse(nfa, lp, lp);	assert(lp->nouts == 0 && rp->nins == 0);	/* did the job */	assert(lp->no != FREESTATE && rp->no != FREESTATE); /* no more */	rp->tmp = NULL;				/* unmark end */	lp->tmp = NULL;				/* and begin, marked by deltraverse */}/* * deltraverse - the recursive heart of delsub * This routine's basic job is to destroy all out-arcs of the state. */static voiddeltraverse(struct nfa * nfa,			struct state * leftend,			struct state * s){	struct arc *a;	struct state *to;	if (s->nouts == 0)		return;					/* nothing to do */	if (s->tmp != NULL)		return;					/* already in progress */	s->tmp = s;					/* mark as in progress */	while ((a = s->outs) != NULL)	{		to = a->to;		deltraverse(nfa, leftend, to);		assert(to->nouts == 0 || to->tmp != NULL);		freearc(nfa, a);		if (to->nins == 0 && to->tmp == NULL)		{			assert(to->nouts == 0);			freestate(nfa, to);		}	}	assert(s->no != FREESTATE); /* we're still here */	assert(s == leftend || s->nins != 0);		/* and still reachable */	assert(s->nouts == 0);		/* but have no outarcs */	s->tmp = NULL;				/* we're done here */}/* * dupnfa - duplicate sub-NFA * * Another recursive traversal, this time using tmp to point to duplicates * as well as mark already-seen states.  (You knew there was a reason why * it's a state pointer, didn't you? :-)) */static voiddupnfa(struct nfa * nfa,	   struct state * start,	/* duplicate of subNFA starting here */	   struct state * stop,		/* and stopping here */	   struct state * from,		/* stringing duplicate from here */	   struct state * to)		/* to here */{	if (start == stop)	{		newarc(nfa, EMPTY, 0, from, to);		return;	}	stop->tmp = to;	duptraverse(nfa, start, from);	/* done, except for clearing out the tmp pointers */	stop->tmp = NULL;	cleartraverse(nfa, start);}/* * duptraverse - recursive heart of dupnfa */static voidduptraverse(struct nfa * nfa,			struct state * s,			struct state * stmp)	/* s's duplicate, or NULL */{	struct arc *a;	if (s->tmp != NULL)		return;					/* already done */	s->tmp = (stmp == NULL) ? newstate(nfa) : stmp;	if (s->tmp == NULL)	{		assert(NISERR());		return;	}	for (a = s->outs; a != NULL && !NISERR(); a = a->outchain)	{		duptraverse(nfa, a->to, (struct state *) NULL);		if (NISERR())			break;		assert(a->to->tmp != NULL);		cparc(nfa, a, s->tmp, a->to->tmp);	}}/* * cleartraverse - recursive cleanup for algorithms that leave tmp ptrs set */static voidcleartraverse(struct nfa * nfa,			  struct state * s){	struct arc *a;	if (s->tmp == NULL)		return;	s->tmp = NULL;	for (a = s->outs; a != NULL; a = a->outchain)		cleartraverse(nfa, a->to);}/* * specialcolors - fill in special colors for an NFA */static voidspecialcolors(struct nfa * nfa){	/* false colors for BOS, BOL, EOS, EOL */	if (nfa->parent == NULL)	{		nfa->bos[0] = pseudocolor(nfa->cm);		nfa->bos[1] = pseudocolor(nfa->cm);		nfa->eos[0] = pseudocolor(nfa->cm);		nfa->eos[1] = pseudocolor(nfa->cm);	}	else	{		assert(nfa->parent->bos[0] != COLORLESS);		nfa->bos[0] = nfa->parent->bos[0];		assert(nfa->parent->bos[1] != COLORLESS);		nfa->bos[1] = nfa->parent->bos[1];		assert(nfa->parent->eos[0] != COLORLESS);		nfa->eos[0] = nfa->parent->eos[0];		assert(nfa->parent->eos[1] != COLORLESS);		nfa->eos[1] = nfa->parent->eos[1];	}}/* * optimize - optimize an NFA */static long						/* re_info bits */optimize(struct nfa * nfa,		 FILE *f)				/* for debug output; NULL none */{#ifdef REG_DEBUG	int			verbose = (f != NULL) ? 1 : 0;	if (verbose)		fprintf(f, "\ninitial cleanup:\n");#endif	cleanup(nfa);				/* may simplify situation */#ifdef REG_DEBUG	if (verbose)		dumpnfa(nfa, f);	if (verbose)		fprintf(f, "\nempties:\n");#endif	fixempties(nfa, f);			/* get rid of EMPTY arcs */#ifdef REG_DEBUG	if (verbose)		fprintf(f, "\nconstraints:\n");#endif	pullback(nfa, f);			/* pull back constraints backward */	pushfwd(nfa, f);			/* push fwd constraints forward */#ifdef REG_DEBUG	if (verbose)		fprintf(f, "\nfinal cleanup:\n");#endif	cleanup(nfa);				/* final tidying */	return analyze(nfa);		/* and analysis */}/* * pullback - pull back constraints backward to (with luck) eliminate them */static voidpullback(struct nfa * nfa,		 FILE *f)				/* for debug output; NULL none */{	struct state *s;	struct state *nexts;	struct arc *a;	struct arc *nexta;	int			progress;	/* find and pull until there are no more */	do	{		progress = 0;		for (s = nfa->states; s != NULL && !NISERR(); s = nexts)		{			nexts = s->next;			for (a = s->outs; a != NULL && !NISERR(); a = nexta)			{				nexta = a->outchain;				if (a->type == '^' || a->type == BEHIND)					if (pull(nfa, a))						progress = 1;				assert(nexta == NULL || s->no != FREESTATE);			}		}		if (progress && f != NULL)			dumpnfa(nfa, f);	} while (progress && !NISERR());	if (NISERR())		return;	for (a = nfa->pre->outs; a != NULL; a = nexta)	{		nexta = a->outchain;		if (a->type == '^')		{			assert(a->co == 0 || a->co == 1);			newarc(nfa, PLAIN, nfa->bos[a->co], a->from, a->to);			freearc(nfa, a);		}	}}/* * pull - pull a back constraint backward past its source state * A significant property of this function is that it deletes at most * one state -- the constraint's from state -- and only if the constraint * was that state's last outarc. */static int						/* 0 couldn't, 1 could */pull(struct nfa * nfa,	 struct arc * con){	struct state *from = con->from;	struct state *to = con->to;	struct arc *a;	struct arc *nexta;	struct state *s;	if (from == to)	{							/* circular constraint is pointless */		freearc(nfa, con);		return 1;	}	if (from->flag)				/* can't pull back beyond start */		return 0;	if (from->nins == 0)	{							/* unreachable */		freearc(nfa, con);		return 1;	}	/*	 * DGP 2007-11-15: Cloning a state with a circular constraint on its list	 * of outs can lead to trouble [Tcl Bug 1810038], so get rid of them first.	 */	for (a = from->outs; a != NULL; a = nexta)	{		nexta = a->outchain;		switch (a->type)		{			case '^':			case '$':			case BEHIND:			case AHEAD:				if (from == a->to)					freearc(nfa, a);				break;		}	}	/* first, clone from state if necessary to avoid other outarcs */	if (from->nouts > 1)	{		s = newstate(nfa);		if (NISERR())			return 0;		assert(to != from);		/* con is not an inarc */		copyins(nfa, from, s);	/* duplicate inarcs */		cparc(nfa, con, s, to); /* move constraint arc */		freearc(nfa, con);		from = s;		con = from->outs;	}	assert(from->nouts == 1);	/* propagate the constraint into the from state's inarcs */	for (a = from->ins; a != NULL; a = nexta)	{		nexta = a->inchain;		switch (combine(con, a))		{			case INCOMPATIBLE:	/* destroy the arc */				freearc(nfa, a);				break;			case SATISFIED:		/* no action needed */				break;			case COMPATIBLE:	/* swap the two arcs, more or less */				s = newstate(nfa);				if (NISERR())					return 0;				cparc(nfa, a, s, to);	/* anticipate move */				cparc(nfa, con, a->from, s);				if (NISERR())					return 0;				freearc(nfa, a);				break;			default:				assert(NOTREACHED);				break;		}	}	/* remaining inarcs, if any, incorporate the constraint */	moveins(nfa, from, to);	dropstate(nfa, from);		/* will free the constraint */	return 1;}/* * pushfwd - push forward constraints forward to (with luck) eliminate them */static voidpushfwd(struct nfa * nfa,		FILE *f)				/* for debug output; NULL none */{	struct state *s;	struct state *nexts;	struct arc *a;	struct arc *nexta;	int			progress;	/* find and push until there are no more */	do	{		progress = 0;		for (s = nfa->states; s != NULL && !NISERR(); s = nexts)		{			nexts = s->next;			for (a = s->ins; a != NULL && !NISERR(); a = nexta)			{				nexta = a->inchain;				if (a->type == '$' || a->type == AHEAD)					if (push(nfa, a))						progress = 1;				assert(nexta == NULL || s->no != FREESTATE);			}		}		if (progress && f != NULL)			dumpnfa(nfa, f);	} while (progress && !NISERR());	if (NISERR())		return;	for (a = nfa->post->ins; a != NULL; a = nexta)	{		nexta = a->inchain;		if (a->type == '$')		{			assert(a->co == 0 || a->co == 1);			newarc(nfa, PLAIN, nfa->eos[a->co], a->from, a->to);			freearc(nfa, a);		}	}}/* * push - push a forward constraint forward past its destination state * A significant property of this function is that it deletes at most * one state -- the constraint's to state -- and only if the constraint * was that state's last inarc. */static int						/* 0 couldn't, 1 could */push(struct nfa * nfa,	 struct arc * con){	struct state *from = con->from;	struct state *to = con->to;	struct arc *a;	struct arc *nexta;	struct state *s;	if (to == from)	{							/* circular constraint is pointless */		freearc(nfa, con);		return 1;	}	if (to->flag)				/* can't push forward beyond end */		return 0;	if (to->nouts == 0)	{							/* dead end */		freearc(nfa, con);		return 1;	}	/*	 * DGP 2007-11-15: Here we duplicate the same protections as appear	 * in pull() above to avoid troubles with cloning a state with a	 * circular constraint on its list of ins.  It is not clear whether	 * this is necessary, or is protecting against a "can't happen".	 * Any test case that actually leads to a freearc() call here would	 * be a welcome addition to the test suite.	 */	for (a = to->ins; a != NULL; a = nexta)	{		nexta = a->inchain;		switch (a->type)		{			case '^':			case '$':			case BEHIND:			case AHEAD:				if (a->from == to)					freearc(nfa, a);				break;		}	}	/* first, clone to state if necessary to avoid other inarcs */	if (to->nins > 1)	{		s = newstate(nfa);		if (NISERR())			return 0;		copyouts(nfa, to, s);	/* duplicate outarcs */		cparc(nfa, con, from, s);		/* move constraint */		freearc(nfa, con);		to = s;		con = to->ins;	}	assert(to->nins == 1);	/* propagate the constraint into the to state's outarcs */	for (a = to->outs; a != NULL; a = nexta)	{		nexta = a->outchain;		switch (combine(con, a))		{			case INCOMPATIBLE:	/* destroy the arc */				freearc(nfa, a);				break;			case SATISFIED:		/* no action needed */				break;			case COMPATIBLE:	/* swap the two arcs, more or less */				s = newstate(nfa);				if (NISERR())					return 0;				cparc(nfa, con, s, a->to);		/* anticipate move */				cparc(nfa, a, from, s);				if (NISERR())					return 0;				freearc(nfa, a);				break;			default:				assert(NOTREACHED);				break;		}	}	/* remaining outarcs, if any, incorporate the constraint */	moveouts(nfa, to, from);	dropstate(nfa, to);			/* will free the constraint */	return 1;}/* * combine - constraint lands on an arc, what happens? * * #def INCOMPATIBLE	1	// destroys arc * #def SATISFIED		2	// constraint satisfied * #def COMPATIBLE		3	// compatible but not satisfied yet */static intcombine(struct arc * con,		struct arc * a){#define  CA(ct,at)	 (((ct)<<CHAR_BIT) | (at))	switch (CA(con->type, a->type))	{		case CA('^', PLAIN):	/* newlines are handled separately */		case CA('$', PLAIN):			return INCOMPATIBLE;			break;		case CA(AHEAD, PLAIN):	/* color constraints meet colors */		case CA(BEHIND, PLAIN):			if (con->co == a->co)				return SATISFIED;			return INCOMPATIBLE;			break;		case CA('^', '^'):		/* collision, similar constraints */		case CA('$', '$'):		case CA(AHEAD, AHEAD):		case CA(BEHIND, BEHIND):			if (con->co == a->co)		/* true duplication */				return SATISFIED;			return INCOMPATIBLE;			break;		case CA('^', BEHIND):	/* collision, dissimilar constraints */		case CA(BEHIND, '^'):		case CA('$', AHEAD):		case CA(AHEAD, '$'):			return INCOMPATIBLE;			break;		case CA('^', '$'):		/* constraints passing each other */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -