interim commit
This commit is contained in:
		| @ -1,11 +1,11 @@ | ||||
|  | ||||
| AUTOMAKE_OPTIONS = nostdinc | ||||
| AM_CPPFLAGS = -I$(top_srcdir)/include | ||||
| AM_CPPFLAGS = -I$(top_srcdir)/include  | ||||
|  | ||||
| lib_LTLIBRARIES = libqsecmn.la | ||||
| libqsecmn_la_SOURCES = \ | ||||
| 	syscall.h mem.h \ | ||||
| 	mem.c chr.c chr_cnv.c rex.c \ | ||||
| 	mem.c chr.c chr_cnv.c rex.c rex1.c \ | ||||
| 	str_bas.c str_cnv.c str_dyn.c str_utl.c \ | ||||
| 	lda.c map.c sll.c dll.c opt.c \ | ||||
| 	tio.c tio_get.c tio_put.c \ | ||||
|  | ||||
| @ -55,10 +55,10 @@ am__installdirs = "$(DESTDIR)$(libdir)" | ||||
| libLTLIBRARIES_INSTALL = $(INSTALL) | ||||
| LTLIBRARIES = $(lib_LTLIBRARIES) | ||||
| libqsecmn_la_DEPENDENCIES = | ||||
| am_libqsecmn_la_OBJECTS = mem.lo chr.lo chr_cnv.lo rex.lo str_bas.lo \ | ||||
| 	str_cnv.lo str_dyn.lo str_utl.lo lda.lo map.lo sll.lo dll.lo \ | ||||
| 	opt.lo tio.lo tio_get.lo tio_put.lo fio.lo pio.lo sio.lo \ | ||||
| 	time.lo misc.lo assert.lo main.lo stdio.lo | ||||
| am_libqsecmn_la_OBJECTS = mem.lo chr.lo chr_cnv.lo rex.lo rex1.lo \ | ||||
| 	str_bas.lo str_cnv.lo str_dyn.lo str_utl.lo lda.lo map.lo \ | ||||
| 	sll.lo dll.lo opt.lo tio.lo tio_get.lo tio_put.lo fio.lo \ | ||||
| 	pio.lo sio.lo time.lo misc.lo assert.lo main.lo stdio.lo | ||||
| libqsecmn_la_OBJECTS = $(am_libqsecmn_la_OBJECTS) | ||||
| libqsecmn_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ | ||||
| 	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ | ||||
| @ -217,11 +217,11 @@ top_build_prefix = @top_build_prefix@ | ||||
| top_builddir = @top_builddir@ | ||||
| top_srcdir = @top_srcdir@ | ||||
| AUTOMAKE_OPTIONS = nostdinc | ||||
| AM_CPPFLAGS = -I$(top_srcdir)/include | ||||
| AM_CPPFLAGS = -I$(top_srcdir)/include  | ||||
| lib_LTLIBRARIES = libqsecmn.la | ||||
| libqsecmn_la_SOURCES = \ | ||||
| 	syscall.h mem.h \ | ||||
| 	mem.c chr.c chr_cnv.c rex.c \ | ||||
| 	mem.c chr.c chr_cnv.c rex.c rex1.c \ | ||||
| 	str_bas.c str_cnv.c str_dyn.c str_utl.c \ | ||||
| 	lda.c map.c sll.c dll.c opt.c \ | ||||
| 	tio.c tio_get.c tio_put.c \ | ||||
| @ -316,6 +316,7 @@ distclean-compile: | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opt.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pio.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rex.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rex1.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sio.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sll.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stdio.Plo@am__quote@ | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * $Id: rex.c 299 2009-10-19 13:33:40Z hyunghwan.chung $ | ||||
|  * $Id: rex.c 300 2009-11-13 14:01:57Z hyunghwan.chung $ | ||||
|  *  | ||||
|     Copyright 2006-2009 Chung, Hyung-Hwan. | ||||
|     This file is part of QSE. | ||||
| @ -341,6 +341,7 @@ static struct __char_class_t __char_class[] = | ||||
| 	{ QSE_NULL,          0, QSE_NULL } | ||||
| }; | ||||
|  | ||||
| #if 0 | ||||
| qse_rex_t* qse_rex_open (qse_mmgr_t* mmgr, qse_size_t xtn) | ||||
| { | ||||
| 	qse_rex_t* rex; | ||||
| @ -394,6 +395,7 @@ int qse_rex_match ( | ||||
| 		rex->mmgr, rex->depth.match, rex->code, rex->option, | ||||
| 		str, len, substr, sublen, match, &rex->errnum); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| void* qse_buildrex ( | ||||
| 	qse_mmgr_t* mmgr, qse_size_t depth, int option, | ||||
|  | ||||
							
								
								
									
										755
									
								
								qse/lib/cmn/rex1.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										755
									
								
								qse/lib/cmn/rex1.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,755 @@ | ||||
| /* | ||||
|  * $Id$ | ||||
|  | ||||
| {LICENSE HERE} | ||||
|  | ||||
|  */ | ||||
|  | ||||
| #include <qse/cmn/rex.h> | ||||
| #include <qse/cmn/str.h> | ||||
| #include <qse/cmn/lda.h> | ||||
| #include "mem.h" | ||||
|  | ||||
| #define GETC(c) do { if getc(c) <= -1) return -1; } while (0) | ||||
| #define OCC_MAX QSE_TYPE_MAX(qse_size_t) | ||||
|  | ||||
| struct qse_rex_t | ||||
| { | ||||
| 	QSE_DEFINE_COMMON_FIELDS (rex) | ||||
|  | ||||
| 	int errnum; | ||||
| 	qse_rex_node_t* code; | ||||
| }; | ||||
|  | ||||
| typedef struct comp_t comp_t; | ||||
| struct comp_t | ||||
| { | ||||
| 	qse_rex_t* rex; | ||||
|  | ||||
| 	qse_cstr_t re; | ||||
| 	const qse_char_t* ptr; | ||||
| 	const qse_char_t* end; | ||||
| 	qse_cint_t c; | ||||
| 	qse_size_t grouplvl; | ||||
|  | ||||
| 	qse_rex_node_t* start; | ||||
| }; | ||||
|  | ||||
| typedef struct exec_t exec_t; | ||||
| struct exec_t | ||||
| { | ||||
| 	qse_rex_t* rex; | ||||
|  | ||||
| 	qse_cstr_t str; | ||||
| 	qse_cstr_t sub; | ||||
|  | ||||
| 	qse_lda_t cand[2]; /* candidate arrays */ | ||||
| 	int xxx, yyy; | ||||
| 	qse_size_t matched; | ||||
| }; | ||||
|  | ||||
| typedef struct pair_t pair_t; | ||||
| struct pair_t | ||||
| { | ||||
| 	qse_rex_node_t* head; | ||||
| 	qse_rex_node_t* tail; | ||||
| }; | ||||
|  | ||||
| typedef struct group_t group_t; | ||||
| struct group_t | ||||
| { | ||||
| 	qse_rex_node_t* node; | ||||
| 	qse_size_t occ; | ||||
| 	group_t* next; | ||||
| }; | ||||
|  | ||||
| typedef struct cand_t cand_t; | ||||
| struct cand_t | ||||
| { | ||||
| 	qse_rex_node_t* node; | ||||
| 	qse_size_t occ; | ||||
| 	group_t* group; | ||||
| }; | ||||
|  | ||||
| qse_rex_t* qse_rex_open (qse_mmgr_t* mmgr, qse_size_t xtn, void* code) | ||||
| { | ||||
| 	qse_rex_t* rex; | ||||
|  | ||||
| 	if (mmgr == QSE_NULL)  | ||||
| 	{ | ||||
| 		mmgr = QSE_MMGR_GETDFL(); | ||||
|  | ||||
| 		QSE_ASSERTX (mmgr != QSE_NULL, | ||||
| 			"Set the memory manager with QSE_MMGR_SETDFL()"); | ||||
|  | ||||
| 		if (mmgr == QSE_NULL) return QSE_NULL; | ||||
| 	} | ||||
|  | ||||
| 	rex = (qse_rex_t*) QSE_MMGR_ALLOC (mmgr, QSE_SIZEOF(qse_rex_t) + xtn); | ||||
| 	if (rex == QSE_NULL) return QSE_NULL; | ||||
|  | ||||
| 	QSE_MEMSET (rex, 0, QSE_SIZEOF(*rex)); | ||||
| 	rex->mmgr = mmgr; | ||||
| 	/* TODO: must duplicate? */ | ||||
| 	rex->code = code; | ||||
|  | ||||
| 	return rex; | ||||
| } | ||||
|  | ||||
| static void freenode (qse_rex_node_t* node, qse_mmgr_t* mmgr) | ||||
| { | ||||
| 	if (node->id == QSE_REX_NODE_CHARSET) | ||||
| 	{ | ||||
| 		// TODO:  | ||||
| 		QSE_MMGR_FREE (mmgr, node->u.cs); | ||||
| 	} | ||||
|  | ||||
| 	QSE_MMGR_FREE (mmgr, node); | ||||
| } | ||||
|  | ||||
| static void freeallnodes (qse_rex_node_t* start) | ||||
| { | ||||
| 	qse_rex_node_t* x, * y; | ||||
| 	qse_mmgr_t* mmgr; | ||||
|  | ||||
| 	QSE_ASSERT (start->id == QSE_REX_NODE_START); | ||||
|  | ||||
| 	mmgr = start->u.s.mmgr; | ||||
| 	x = start->u.s.link; | ||||
| 	while (x != QSE_NULL) | ||||
| 	{ | ||||
| 		y = x->link; | ||||
| 		freenode (x, mmgr); | ||||
| 		x = y; | ||||
| 	} | ||||
|  | ||||
| 	QSE_MMGR_FREE (mmgr, start); | ||||
| } | ||||
|  | ||||
| void qse_rex_close (qse_rex_t* rex) | ||||
| { | ||||
| 	if (rex->code != QSE_NULL) freeallnodes (rex->code); | ||||
| 	QSE_MMGR_FREE (rex->mmgr, rex); | ||||
| } | ||||
|  | ||||
| static qse_rex_node_t* newnode (comp_t* c, qse_rex_node_id_t id) | ||||
| { | ||||
| 	qse_rex_node_t* node; | ||||
|  | ||||
| 	node = (qse_rex_node_t*)  | ||||
| 		QSE_MMGR_ALLOC (c->rex->mmgr, QSE_SIZEOF(qse_rex_node_t)); | ||||
| 	if (node == QSE_NULL)  | ||||
| 	{ | ||||
| // TODO set error code | ||||
| 		return QSE_NULL; | ||||
| 	} | ||||
|  | ||||
| 	QSE_MEMSET (node, 0, QSE_SIZEOF(*node)); | ||||
| 	node->id = id; | ||||
|  | ||||
| 	if (c->start != QSE_NULL)  | ||||
| 	{ | ||||
| 		QSE_ASSERT (c->start->id == QSE_REX_NODE_START); | ||||
| 		node->link = c->start->u.s.link; | ||||
| 		c->start->u.s.link = node; | ||||
| 	} | ||||
|  | ||||
| 	return node; | ||||
| } | ||||
|  | ||||
| static qse_rex_node_t* newstartnode (comp_t* c) | ||||
| { | ||||
| 	qse_rex_node_t* n = newnode (c, QSE_REX_NODE_START); | ||||
| 	if (n != QSE_NULL)  | ||||
| 	{ | ||||
| 		n->u.s.mmgr = c->rex->mmgr; | ||||
| 		n->u.s.link = QSE_NULL; | ||||
| 	} | ||||
| 	return n; | ||||
| } | ||||
|  | ||||
| static qse_rex_node_t* newendnode (comp_t* c) | ||||
| { | ||||
| 	return newnode (c, QSE_REX_NODE_END); | ||||
| } | ||||
|  | ||||
| static qse_rex_node_t* newnopnode (comp_t* c) | ||||
| { | ||||
| 	return newnode (c, QSE_REX_NODE_NOP); | ||||
| } | ||||
|  | ||||
| static qse_rex_node_t* newgroupnode (comp_t* c, qse_rex_node_t* head) | ||||
| { | ||||
| 	qse_rex_node_t* n = newnode (c, QSE_REX_NODE_GROUP); | ||||
| 	if (n != QSE_NULL) n->u.g.head = head; | ||||
| 	return n; | ||||
| } | ||||
|  | ||||
| static qse_rex_node_t* newgroupendnode (comp_t* c, qse_rex_node_t* group) | ||||
| { | ||||
| 	qse_rex_node_t* n = newnode (c, QSE_REX_NODE_GROUPEND); | ||||
| 	if (n != QSE_NULL) n->u.ge.group = group; | ||||
| 	return n; | ||||
| } | ||||
|  | ||||
| static qse_rex_node_t* newcharnode (comp_t* c, qse_char_t ch) | ||||
| { | ||||
| 	qse_rex_node_t* n = newnode (c, QSE_REX_NODE_CHAR); | ||||
| 	if (n != QSE_NULL) n->u.c = ch; | ||||
| 	return n; | ||||
| } | ||||
|  | ||||
| static qse_rex_node_t* newbranchnode ( | ||||
| 	comp_t* c, qse_rex_node_t* left, qse_rex_node_t* right) | ||||
| { | ||||
| 	qse_rex_node_t* n = newnode (c, QSE_REX_NODE_BRANCH); | ||||
| 	if (n != QSE_NULL) | ||||
| 	{ | ||||
| 		n->u.b.left = left;  | ||||
| 		n->u.b.right = right; | ||||
| 	} | ||||
| 	return n; | ||||
| } | ||||
|  | ||||
| static int getc (comp_t* c) | ||||
| { | ||||
| 	c->c = (c->ptr < c->end)? *c->ptr++: QSE_CHAR_EOF; | ||||
| if (c->c == QSE_CHAR_EOF) | ||||
| qse_printf (QSE_T("getc => <EOF>\n")); | ||||
| else qse_printf (QSE_T("getc => %c\n"), c->c); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static qse_rex_node_t* comp0 (comp_t* c, qse_rex_node_t* ge); | ||||
|  | ||||
| static qse_rex_node_t* comp2 (comp_t* c) | ||||
| { | ||||
| 	qse_rex_node_t* n; | ||||
|  | ||||
| 	switch (c->c) | ||||
| 	{ | ||||
| 		case QSE_T('('): | ||||
| 		{ | ||||
| 			qse_rex_node_t* x, * ge; | ||||
| 			 | ||||
| 			n = newgroupnode (c, QSE_NULL); | ||||
| 			if (n == QSE_NULL) return QSE_NULL; | ||||
|  | ||||
| 			ge = newgroupendnode (c, n); | ||||
| 			if (ge == QSE_NULL)  | ||||
| 			{ | ||||
| 				// free n | ||||
| 				return QSE_NULL; | ||||
| 			} | ||||
|  | ||||
| 			if (getc(c) <= -1) | ||||
| 			{ | ||||
| 				// freere (ge); | ||||
| 				// freere (n); | ||||
| 				return QSE_NULL; | ||||
| 			} | ||||
|  | ||||
| 			c->grouplvl++; | ||||
| 			x = comp0 (c, ge); | ||||
| 			if (x == QSE_NULL) | ||||
| 			{ | ||||
| 				// freere (ge); | ||||
| 				// freere (n); | ||||
| 				return QSE_NULL; | ||||
| 			} | ||||
|  | ||||
| 			if (c->c != QSE_T(')'))  | ||||
| 			{ | ||||
| qse_printf (QSE_T("expecting )\n")); | ||||
| 				// UNBALANCED PAREN. | ||||
| 				// freere (x); | ||||
| 				// freere (n); | ||||
| 				return QSE_NULL; | ||||
| 			} | ||||
|  | ||||
| 			c->grouplvl--; | ||||
| 			if (getc(c) <= -1) | ||||
| 			{ | ||||
| 				// freere (x); | ||||
| 				// freere (n); | ||||
| 				return QSE_NULL; | ||||
| 			} | ||||
|  | ||||
| 			n->u.g.head = x; | ||||
| 			break; | ||||
| 		} | ||||
| 			 | ||||
| 		case QSE_T('.'): | ||||
| 			n = newnode (c, QSE_REX_NODE_ANYCHAR); | ||||
| 			if (n == QSE_NULL) return QSE_NULL; | ||||
| 			if (getc(c) <= -1) | ||||
| 			{ | ||||
| 				// TODO: error handling.. | ||||
| 				return QSE_NULL; | ||||
| 			} | ||||
| 			break; | ||||
|  | ||||
| 		/* | ||||
| 		case QSE_T('['): | ||||
| 			.... | ||||
| 		*/ | ||||
|  | ||||
| 		default: | ||||
| 			/* normal character */ | ||||
| 			n = newcharnode (c, c->c); | ||||
| 			if (n == QSE_NULL) return QSE_NULL; | ||||
| 			if (getc(c) <= -1) | ||||
| 			{ | ||||
| 				// TODO: error handling.. | ||||
| 				return QSE_NULL; | ||||
| 			} | ||||
| 			break; | ||||
| 	} | ||||
|  | ||||
| 	/* handle the occurrence specifier, if any */ | ||||
| 	switch (c->c) | ||||
| 	{ | ||||
| 		case QSE_T('?'): | ||||
| 			n->occ.min = 0; | ||||
| 			n->occ.max = 1; | ||||
| 			if (getc(c) <= -1) | ||||
| 			{ | ||||
| 				// TODO: error handling.. | ||||
| 				//free n | ||||
| 				return QSE_NULL; | ||||
| 			} | ||||
| 			break; | ||||
| 			 | ||||
| 		case QSE_T('*'): | ||||
| 			n->occ.min = 0; | ||||
| 			n->occ.max = OCC_MAX; | ||||
| 			if (getc(c) <= -1) | ||||
| 			{ | ||||
| 				// TODO: error handling.. | ||||
| 				//free n | ||||
| 				return QSE_NULL; | ||||
| 			} | ||||
| 			break; | ||||
|  | ||||
| 		case QSE_T('+'): | ||||
| 			n->occ.min = 1; | ||||
| 			n->occ.max = OCC_MAX; | ||||
| 			if (getc(c) <= -1) | ||||
| 			{ | ||||
| 				// TODO: error handling.. | ||||
| 				//free n | ||||
| 				return QSE_NULL; | ||||
| 			} | ||||
| 			break; | ||||
|  | ||||
| 		/* | ||||
| 		case QSE_T('{'): | ||||
| 			 // TODO -------------- | ||||
| 			break; | ||||
| 		*/ | ||||
|  | ||||
| 		default: | ||||
| 			n->occ.min = 1; | ||||
| 			n->occ.max = 1; | ||||
| 	} | ||||
|  | ||||
| 	return n; | ||||
| } | ||||
|  | ||||
| static qse_rex_node_t* comp1 (comp_t* c, pair_t* pair) | ||||
| { | ||||
| 	pair->head = newnopnode (c); | ||||
| 	if (pair->head == QSE_NULL) return QSE_NULL; | ||||
|  | ||||
| 	pair->tail = pair->head; | ||||
|  | ||||
| 	while (c->c != QSE_T('|') && c->c != QSE_CHAR_EOF &&  | ||||
| 	       !(c->grouplvl >= 0 && c->c == QSE_T(')'))) | ||||
| 	{ | ||||
| 		qse_rex_node_t* tmp = comp2 (c); | ||||
| 		if (tmp == QSE_NULL)  | ||||
| 		{ | ||||
| 			/* TODO: free all nodes... from head down to tail... */ | ||||
| 			return QSE_NULL; | ||||
| 		} | ||||
|  | ||||
| 		pair->tail->next = tmp; | ||||
| 		pair->tail = tmp; | ||||
| 	} | ||||
|  | ||||
| 	return pair->head; | ||||
| } | ||||
|  | ||||
| static qse_rex_node_t* comp0 (comp_t* c, qse_rex_node_t* ge) | ||||
| { | ||||
| 	qse_rex_node_t* left, * right, * tmp; | ||||
| 	pair_t xpair; | ||||
|  | ||||
| 	left = comp1 (c, &xpair); | ||||
| 	if (left == QSE_NULL) return QSE_NULL; | ||||
| 	xpair.tail->next = ge; | ||||
|  | ||||
| 	while (c->c == QSE_T('|')) | ||||
| 	{ | ||||
| 		if (getc (c) <= -1)  | ||||
| 		{ | ||||
| 			//freere (left); | ||||
| 			return QSE_NULL; | ||||
| 		} | ||||
| 		 | ||||
| 		right = comp1 (c, &xpair); | ||||
| 		if (right == QSE_NULL) | ||||
| 		{ | ||||
| 			//freere (l and r); | ||||
| 			return QSE_NULL; | ||||
| 		} | ||||
| 		xpair.tail->next = ge; | ||||
|  | ||||
| 		tmp = newbranchnode (c, left, right); | ||||
| 		if (tmp == QSE_NULL) | ||||
| 		{ | ||||
| 			//freere (left and right); | ||||
| 			return QSE_NULL; | ||||
| 		} | ||||
|  | ||||
| 		left = tmp; | ||||
| 	}  | ||||
|  | ||||
| 	return left; | ||||
| } | ||||
|  | ||||
| qse_rex_node_t* qse_rex_comp ( | ||||
| 	qse_rex_t* rex, const qse_char_t* ptr, qse_size_t len) | ||||
| { | ||||
| 	comp_t c; | ||||
|  | ||||
| 	if (rex->code != QSE_NULL) | ||||
| 	{ | ||||
| 		freeallnodes (rex->code); | ||||
| 		rex->code = QSE_NULL; | ||||
| 	} | ||||
|  | ||||
| 	c.rex = rex; | ||||
| 	c.re.ptr = ptr; | ||||
| 	c.re.len = len;	 | ||||
|  | ||||
| 	c.ptr = ptr; | ||||
| 	c.end = ptr + len; | ||||
| 	c.c = QSE_CHAR_EOF; | ||||
| 	c.grouplvl = 0; | ||||
| 	c.start = QSE_NULL; | ||||
|  | ||||
| 	if (getc(&c) <= -1) return QSE_NULL; | ||||
|  | ||||
| 	c.start = newstartnode (&c); | ||||
| 	if (c.start != QSE_NULL) | ||||
| 	{ | ||||
| 		qse_rex_node_t* end; | ||||
| 		end = newendnode (&c); | ||||
| 		if (end == QSE_NULL) | ||||
| 		{ | ||||
| 			freenode (c.start, c.rex->mmgr); | ||||
| 			c.start = QSE_NULL; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			qse_rex_node_t* tmp; | ||||
| 			//tmp = comp0 (&c, QSE_NULL); | ||||
| 			tmp = comp0 (&c, end); | ||||
| 			if (tmp == QSE_NULL)  | ||||
| 			{ | ||||
| 				//freenode (c.start, c.rex->mmgr); | ||||
| 				freeallnodes (c.start); | ||||
| 				c.start = QSE_NULL; | ||||
| 			} | ||||
| 			else  | ||||
| 			{ | ||||
| qse_printf (QSE_T("start has tmp...\n")); | ||||
| 				c.start->next = tmp; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	rex->code = c.start; | ||||
| 	return rex->code; | ||||
| } | ||||
|  | ||||
| static group_t* pushgroup (exec_t* e, group_t* pg, qse_rex_node_t* gn) | ||||
| { | ||||
| 	group_t* g; | ||||
| 	QSE_ASSERT (gn->id == QSE_REX_NODE_GROUP); | ||||
|  | ||||
| 	g = (group_t*) QSE_MMGR_ALLOC (e->rex->mmgr, QSE_SIZEOF(*g)); | ||||
| 	if (g == QSE_NULL) | ||||
| 	{ | ||||
| 		/* TODO: set error info */ | ||||
| 		return QSE_NULL; | ||||
| 	} | ||||
|  | ||||
| 	g->node = gn; | ||||
| 	g->occ = 0; | ||||
| 	g->next = pg; | ||||
|  | ||||
| 	return g; | ||||
| } | ||||
|  | ||||
| static int addsimplecand ( | ||||
| 	exec_t* e, cand_t* pcand, qse_rex_node_t* node, qse_size_t occ) | ||||
| { | ||||
| 	QSE_ASSERT ( | ||||
| 		node->id == QSE_REX_NODE_CHAR || | ||||
| 		node->id == QSE_REX_NODE_CHARSET | ||||
| 	); | ||||
|  | ||||
| 	cand_t cand; | ||||
|  | ||||
| 	cand.node = node; | ||||
| 	cand.occ = occ; | ||||
| 	cand.group = pcand->group; | ||||
|  | ||||
| if (node->id == QSE_REX_NODE_CHAR) | ||||
| qse_printf (QSE_T("adding %d %c\n"), node->id, node->u.c); | ||||
| else | ||||
| qse_printf (QSE_T("adding %d NA\n"), node->id); | ||||
| 		 | ||||
| 	if (qse_lda_insert ( | ||||
| 		&e->cand[e->xxx], | ||||
| 		QSE_LDA_SIZE(&e->cand[e->xxx]), | ||||
| 		&cand, 1) == (qse_size_t)-1) | ||||
| 	{ | ||||
| 		/* TODO: set error code: ENOERR */ | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int addnextcands (exec_t* e, group_t* group, qse_rex_node_t* cur) | ||||
| { | ||||
| 	/* skip all NOP nodes */ | ||||
| 	while (cur && cur->id == QSE_REX_NODE_NOP) cur = cur->next; | ||||
|  | ||||
| 	/* nothing to add */ | ||||
| 	if (cur == QSE_NULL) return 0; | ||||
|  | ||||
| 	if (cur->id == QSE_REX_NODE_END) | ||||
| 	{ | ||||
| 		qse_printf (QSE_T("== ADDING THE END(MATCH) NODE MEANING MATCH FOUND == \n")); | ||||
| 		e->matched++; | ||||
| 	} | ||||
| 	else if (cur->id == QSE_REX_NODE_BRANCH) | ||||
| 	{ | ||||
| 	#if 0 | ||||
| 		QSE_ASSERT (cur->next == QSE_NULL); | ||||
| 		if (addnextcands (e, group, cur->u.b.left) <= -1) return -1; | ||||
| 		if (addnextcands (e, group, cur->u.b.right) <= -1) return -1; | ||||
| 	#endif | ||||
| 	} | ||||
| 	else if (cur->id == QSE_REX_NODE_GROUP) | ||||
| 	{ | ||||
| 		group_t* g = pushgroup (e, group, cur); | ||||
| 		if (g == QSE_NULL) return -1; | ||||
|  | ||||
| 		/* add the first node in the group */ | ||||
| 		if (addnextcands (e, g, cur->u.g.head) <= -1) return -1; | ||||
|  | ||||
| 		if (cur->occ.min <= 0) | ||||
| 		{ | ||||
| 			/* if the group node is optional,  | ||||
| 			 * add the next node to the candidate array. | ||||
| 			 * branch case => dup group */ | ||||
| 			if (addnextcands (e, group, cur->next) <= -1) return -1; | ||||
| 		} | ||||
| 	} | ||||
| 	else if (cur->id == QSE_REX_NODE_GROUPEND) | ||||
| 	{ | ||||
| 		group_t* group; | ||||
| 		qse_rex_node_t* node; | ||||
|  | ||||
| 		group = cand->group; | ||||
| 		QSE_ASSERT (group != QSE_NULL); | ||||
|  | ||||
| 		node = group->node; | ||||
| 		QSE_ASSERT (node == cur->u.ge.group); | ||||
|  | ||||
| 		if (group->occ < node->occ.max) | ||||
| 		{ | ||||
| 			/* need to repeat itself */ | ||||
| 			group->occ++; | ||||
| 			if (addnextcands (e, cand, node->u.g.head) <= -1) return -1; | ||||
| 		} | ||||
|  | ||||
| 		if (group->occ >= node->occ.min) | ||||
| 		{ | ||||
| 			/* take the next atom as a candidate. | ||||
| 			 * it is actually a branch case. */ | ||||
|  | ||||
| 			cand = dupgrouppoppingtop (cand); | ||||
|  | ||||
| 			if (addnextcands (e, pg, node->next) <= -1) return -1; | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		if (addsimplecand (e, cand, cur, 1) <= -1) return -1; | ||||
| 		if (cur->occ.min <= 0) | ||||
| 		{ | ||||
| 			/* if the node is optional, | ||||
| 			 * add the next node to the candidate array */ | ||||
| 			if (addnextcands (e, pg, cur->next) <= -1) return -1; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int match (exec_t* e, const qse_char_t* curp) | ||||
| { | ||||
| 	qse_size_t i; | ||||
| 	qse_char_t curc = *curp; | ||||
|  | ||||
| 	for (i = 0; i < QSE_LDA_SIZE(&e->cand[e->yyy]); i++) | ||||
| 	{ | ||||
| 		cand_t* cand = QSE_LDA_DPTR(&e->cand[e->yyy],i); | ||||
| 		qse_rex_node_t* node = cand->node; | ||||
|  | ||||
| 		if (node->id == QSE_REX_NODE_CHAR) | ||||
| 		{ | ||||
| 			if (node->u.c == curc) | ||||
| 			{ | ||||
| 				qse_printf (QSE_T("matched %c\n"), node->u.c); | ||||
|  | ||||
| 				if (cand->occ < node->occ.max) | ||||
| 				{ | ||||
| 					if (addsimplecand (e, cand, node, cand->occ+1) <= -1) return -1; | ||||
| 				} | ||||
| 				if (cand->occ >= node->occ.min) | ||||
| 				{ | ||||
|  | ||||
| 					if (addnextcands (e, cand, node->next) <= -1) return -1; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			QSE_ASSERT (node->id == QSE_REX_NODE_CHARSET); | ||||
| 			qse_printf (QSE_T("charset not implemented...\n")); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int exec (exec_t* e) | ||||
| { | ||||
| 	const qse_char_t* ptr = e->sub.ptr; | ||||
| 	const qse_char_t* end = e->sub.ptr + e->sub.len; | ||||
|  | ||||
| 	e->matched = 0; | ||||
| 	e->xxx = 0; | ||||
| 	e->yyy = 1; | ||||
|  | ||||
| 	/* collect the initial candidates to cand[xxx] */ | ||||
| 	qse_lda_clear (&e->cand[e->xxx]);  | ||||
|  | ||||
| 	if (addnextcands (e, QSE_NULL, e->rex->code->next) <= -1) return -1; | ||||
|  | ||||
| 	while (ptr < end) | ||||
| 	{ | ||||
| 		/* kind of swap cand[xxx] and cand[yyy] by swapping indices */ | ||||
| 		int tmp = e->xxx; | ||||
| 		e->xxx = e->yyy; | ||||
| 		e->yyy = tmp; | ||||
|  | ||||
| 		/* check if there are any next candidates */ | ||||
| 		if (QSE_LDA_SIZE(&e->cand[e->yyy]) <= 0) | ||||
| 		{ | ||||
| 			/* if none, break */ | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| 		/* clear the array to hold the next candidates */ | ||||
| 		qse_lda_clear (&e->cand[e->xxx]);  | ||||
|  | ||||
| qse_printf (QSE_T("MATCHING %c\n"), *ptr); | ||||
| 		if (match (e, ptr) <= -1) return -1; | ||||
|  | ||||
| 		ptr++; | ||||
| 	} | ||||
|  | ||||
| 	qse_printf (QSE_T("TOTAL MATCHES FOUND... %d\n"), e->matched); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int init_exec_dds (exec_t* e, qse_mmgr_t* mmgr) | ||||
| { | ||||
| 	/* initializes dynamic data structures */ | ||||
| 	if (qse_lda_init (&e->cand[0], mmgr, 100) == QSE_NULL) | ||||
| 	{ | ||||
| 		/* TOOD: set error */ | ||||
| 		return -1; | ||||
| 	} | ||||
| 	if (qse_lda_init (&e->cand[1], mmgr, 100) == QSE_NULL) | ||||
| 	{ | ||||
| 		/* TOOD: set error */ | ||||
| 		qse_lda_fini (&e->cand[0]); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	qse_lda_setscale (&e->cand[0], QSE_SIZEOF(cand_t)); | ||||
| 	qse_lda_setscale (&e->cand[1], QSE_SIZEOF(cand_t)); | ||||
|  | ||||
| 	qse_lda_setcopier (&e->cand[0], QSE_LDA_COPIER_INLINE); | ||||
| 	qse_lda_setcopier (&e->cand[1], QSE_LDA_COPIER_INLINE); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static void fini_exec_dds (exec_t* e) | ||||
| { | ||||
| 	qse_lda_fini (&e->cand[1]); | ||||
| 	qse_lda_fini (&e->cand[0]); | ||||
| } | ||||
|  | ||||
| int qse_rex_exec (qse_rex_t* rex,  | ||||
| 	const qse_char_t* str, qse_size_t len, | ||||
| 	const qse_char_t* substr, qse_size_t sublen) | ||||
| { | ||||
| 	exec_t e; | ||||
| 	int n = 0; | ||||
|  | ||||
| 	if (rex->code == QSE_NULL) | ||||
| 	{ | ||||
| 		//* TODO:  set error code: no regular expression compiled. | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	QSE_MEMSET (&e, 0, QSE_SIZEOF(e)); | ||||
| 	e.rex = rex; | ||||
| 	e.str.ptr = str; | ||||
| 	e.str.len = len; | ||||
| 	e.sub.ptr = substr; | ||||
| 	e.sub.len = sublen; | ||||
|  | ||||
| 	if (init_exec_dds (&e, rex->mmgr) <= -1) return -1; | ||||
|  | ||||
| // TOOD: may have to execute exec in case sublen is 0. | ||||
| 	while (e.sub.len > 0) | ||||
| 	{ | ||||
| 		n = exec (&e); | ||||
| 		if (n <= -1)  | ||||
| 		{ | ||||
| 			n = -1; | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| 		if (e.matched > 0) break; | ||||
|  | ||||
| 		e.sub.ptr++; | ||||
| 		e.sub.len--; | ||||
| 	} | ||||
|  | ||||
| 	fini_exec_dds (&e); | ||||
|  | ||||
| 	return n; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user