www.pudn.com > 12cocorc.zip > CRX.C


#include "set.h" 
#include "collect.h" 
#include "crx.h" 
#include "crt.h" 
#include "crf.h" 
#include "crs.h" 
#include  
#include  
#include  
#define  MAX_ALT_IF     3 
#define  isspacetab(c)  (c == ' ' || c == '\t') 
 
static FILE *fparser, *fherror; 
static int ErrorNo, CurrentNt; 
 
static char temp_str[250]; 
 
/* add error msg to error file */ 
static void DeclareError(char *Msg) 
{ 
	fprintf(fherror, "         \"%s\",\n", Msg); 
	ErrorNo++; 
} 
 
static char *GetFormatLine (char *s, char *line) 
{ 
	char ch; 
	int i; 
	int col = 1; 
 
	ch = *s; 
	if (ch == 0) return NULL; 
 
	while (ch != LF_CHAR && ch != 0) { 
		if (ch == TAB_CHAR) { 
			i = TAB_SIZE - (col % TAB_SIZE); 
			while (i-- >= 0) {*line++ = ' ';col++;} 
		} else if (ch != CR_CHAR) {*line++ = ch; col++;} 
		s++; 
		ch = *s; 
	} 
 
	*line = 0; 
	if (ch != 0) return s + 1; 
		else return s; 
} 
 
/* generate semantic action code */ 
static void GenSemCode(int tab, long pos, int len, int line, int col, int gencomma) 
{ 
	int i; 
	char *buff, *s, *sb; 
	int Comma = FALSE, firstline = 1; 
 
	if (D_option) fprintf(fparser, "# line %d \"%s\"\n", line, source_name); 
 
	if (pos == -1) { /* a complete null alternative */ 
		GenCode(fparser, "%I/* Empty */$$", tab); 
		return; 
	} 
 
	sb = buff = (char *) malloc(len + 2); 
	S_GetString(pos, len, buff, len); 
 
	/* remove leading and trailing spaces. PT */ 
	while (*sb == ' ') { sb++; col++; } 
	while (len > 0 && buff[len - 1] == ' ') len--; 
	buff[len] = '\0'; 
 
	while ((sb = GetFormatLine(sb, temp_str)) != NULL) { 
		s = temp_str; 
		if (!firstline) { 
			GenCode(fparser, "$$"); 
			i = col - 1;  /* skip spaces (max col + 2) */ 
			while (i-- && isspacetab(*s)) s++; 
		} 
 
		GenCode(fparser, "%I", tab); 
		while (*s != 0) { 
			GenCode(fparser, "%c", *s); 
			if (*s == ';') Comma = FALSE; else 
			if (*s != ' ') Comma = TRUE; 
			s++; 
		} 
		firstline = 0; 
	} 
	if (Comma && gencomma) GenCode(fparser, ";"); 
	GenCode(fparser, "$$"); 
	free(buff); 
} 
 
/* generate attribute code */ 
static void GenAttrCode(int tab, int gen_col, long pos, int len, int c)		/*kws*/ 
{ 
	char *buff, *s; 
	int i; 
 
	s = buff = (char *) malloc(len + 2); 
	S_GetString(pos, len, buff, len); 
	buff[len] = '\0'; 
 
	do { 
		while (isspacetab(*s)) s++; 
		while (*s != 0 && *s != '\n') { 
			if (*s != '\r') GenCode(fparser, "%c", *s); 
			s++; 
		} 
		if (*s == '\n') { 
			GenCode(fparser, "$$%I", tab); 
			i = gen_col; 
			while (i--) GenCode(fparser, " "); 
			s++; 
		} 
	} while (*s); 
	free(buff); 
} 
 
 
/* generate function header */ 
static void GenFuncHeader(PNTermNode n, int header_only) 
{ 
	PGraphNode p; 
 
	if (!header_only && D_option) 
		fprintf(fparser, "# line %d \"%s\"\n", n->line_dec, source_name); 
 
	if (GenCplusplus) { 
		if (header_only) GenCode(fparser, "void %s (", n->name); 
		else GenCode(fparser, "void %sParser::%s (", module_prefix, n->name); 
	} 
	else GenCode(fparser, "static void %s (", n->name); 
 
	if (n->has_attr) { 
		p = GetGraphP(n->attr); 
		GenAttrCode(0, strlen(n->name) + 14, p->SEMPOS, p->SEMLEN, p->SEMCOL); 
	} 
	if (header_only) { 
		GenCode(fparser, ");$$"); 
		return; 
	} 
	GenCode(fparser, ")$$"); 
	if (n->sem != NIL) { 
		p = GetGraphP(n->sem); 
		GenSemCode(4, p->SEMPOS, p->SEMLEN, p->SEMLINE, p->SEMCOL + 2, TRUE); 
	} 
	GenCode(fparser, "{$$"); 
} 
 
/* generate function trailer */ 
static void GenFuncTrailer() 
{ 
	GenCode(fparser, "}$$$$"); 
} 
 
/* return number of alternatives in node 'n' */ 
static int CompAltCount(int n) 
{ 
	PGraphNode p; 
	int c = 0; 
 
	while (n) { 
		c++; 
		p = GetGraphP(n); 
		n = p->ALT; 
	} 
	return c; 
} 
 
/* generate function graph */ 
static void GenFuncGraph(int gp, int tab, Set *chequed) 
{ 
	PGraphNode gn; 
	Set s1, Oldchequed; 
 
	Set_Init(&s1); 
	Set_Init(&Oldchequed); 
	Set_Union(&Oldchequed, chequed); 
 
	while (gp > NIL) { 
		gn = GetGraphP(gp); 
		if (D_option && 
				gn->type != T_SEM) 
			fprintf(fparser, "# line %d \"%s\"\n", 
					gn->SLine, source_name); 
 
		switch(gn->type) { 
		case T_T : 
			if (Set_IsItem(chequed, gn->SYMLINK)) 
				GenCode(fparser, "%IGet();$$", tab); 
			else 
				GenCode(fparser, "%IExpect(%T);$$", tab, (int)gn->SYMLINK); /*kws*/ 
			break; 
		case T_WT: 
			GenCode(fparser, "%IExpectWeak(%T,%d);$$", tab, (int)gn->SYMLINK,/*kws*/ 
					(int)gn->SETLINK1 - first_weak_set + 1);				/*kws*/ 
			break; 
		case T_NT : 
			GenCode(fparser, "%I%N(", tab, (int)gn->SYMLINK);				/*kws*/ 
			if (gn->ALT != NIL) { 
				PGraphNode gn1 = GetGraphP(gn->ALT); 
				if (gn1->type == T_ATTR) { 
					PNTermNode ntn = GetNTermP(gn->SYMLINK); 
					GenAttrCode(tab, strlen(ntn->name) + 1, gn1->SEMPOS, gn1->SEMLEN, gn1->SEMCOL); 
				} 
			} 
			GenCode(fparser, ");$$"); 
			break; 
 
		case T_OPT: 
			Set_Clean(&s1); 
			CompFirstSet(gn->INNER, &s1); 
			if (Set_Equal(chequed, &s1)) GenFuncGraph(gn->INNER, tab, &s1); 
			else { 
				GenCode(fparser, "%Iif (%S) {$$", tab, &s1); 
				GenFuncGraph(gn->INNER, tab + 1, &s1); 
				GenCode(fparser, "%I}$$", tab); 
			} 
			break; 
		case T_REP: 
			{ 
				PGraphNode gn1 = GetGraphP(gn->INNER); 
				if (gn1->type == T_WT) { 
					Set_Clean(&s1); 
					GenCode(fparser, "%Iwhile (WeakSeparator(%T,%d,%d)) {$$", tab, 
							(int)gn1->SYMLINK,								/*kws*/ 
							gn1->SETLINK1-first_weak_set + 1, 
							gn1->SETLINK2-first_weak_set + 1); 
					GenFuncGraph(gn1->next, tab + 1, &s1); 
				} else { 
					Set_Clean(&s1); 
					CompFirstSet(gn->INNER, &s1); 
					GenCode(fparser, "%Iwhile (%S) {$$", tab, &s1); 
					GenFuncGraph(gn->INNER, tab + 1, &s1); 
				} 
				GenCode(fparser, "%I}$$", tab); 
				break; 
			} 
		case T_ALT: 
			{ 
				Set symdone; 
				int gen_err = TRUE; 
				int gp1; 
				PGraphNode gn1; 
				int gen_case; 
 
				Set_Init(&symdone); 
				gen_case = CompAltCount(gp) > MAX_ALT_IF; 
				if (gen_case) GenCode(fparser, "%Iswitch (Sym) {$$", tab); 
				gp1 = gp; 
				while (gp1) { 
					gn1 = GetGraphP(gp1); 
					if (IsNullableGraph(gn1->INNER)) gen_err = FALSE; 
					Set_Clean(&s1); 
					CompExpected(gn1->INNER, CurrentNt, &s1); 
					Set_Diference(&s1, &symdone); 
					Set_Union(&symdone, &s1); 
 
					if (gen_case) GenCode(fparser, "%I%X $$", tab + 1, &s1); 
					else { 
						if (gp1 == gp) GenCode(fparser, "%Iif (%S) {$$", tab, &s1); 
						else GenCode(fparser, "%I} else if (%S) {$$", tab, &s1); 
					} 
					CompExpected(gn1->INNER, CurrentNt, &s1); 
					Set_Union(&s1, chequed); 
					GenFuncGraph(gn1->INNER, tab + 1 + gen_case, &s1); 
					if (gen_case) GenCode(fparser, "%Ibreak;$$", tab + 2); 
					gp1 = gn1->ALT; 
				} 
 
				if (!gen_err && gn->next <= NIL) gen_err = TRUE; 
				if (gen_case) { 
					if (gen_err) GenCode(fparser, "%Idefault :GenError(%d); break;$$", tab+1, ErrorNo); 
					GenCode(fparser, "%I}$$", tab); 
				} else { 
					if (gen_err) GenCode(fparser, "%I} else GenError(%d);$$", tab, ErrorNo); 
					else GenCode(fparser, "%I}$$", tab); 
				} 
 
				if (gen_err) ErrorNo++; 
				Set_Done(&symdone); 
				break; 
			} 
		case T_SEM: 
			GenSemCode(tab, gn->SEMPOS, gn->SEMLEN, gn->SEMLINE, 
				gn->SEMCOL + 2, TRUE); 
			break; 
		case T_ANY : 
			GenCode(fparser, "%IGet();$$", tab); 
			break; 
		case T_SYNC: 
			{ 
				PSymSetNode ssn = GetSymSetP(gn->SETLINK1); 
				GenCode(fparser, "%Iwhile (!(%S)) { GenError(%d); Get(); }$$", 
						tab, &ssn->set, ErrorNo); 
				ErrorNo++; 
				break; 
			} /* case */ 
		} /* switch */ 
		if (gn->type != T_SEM && gn->type != T_SYNC) Set_Clean(chequed); 
		gp = gn->next; 
	} 
 
	Set_Clean(chequed); 
	Set_Union(chequed, &Oldchequed); 
	Set_Done(&Oldchequed); 
	Set_Done(&s1); 
} 
 
/* generate body of function */ 
static void GenParseBody(PNTermNode ntn, int ntp) 
{ 
	Set chequed; 
	if (ntp == 0) return; 
	Set_Init(&chequed); 
	CurrentNt = ntp; 
	GenFuncHeader(ntn, 0); 
	GenFuncGraph(ntn->graph, 1, &chequed); 
	GenFuncTrailer(); 
	Set_Done(&chequed); 
} 
 
/* generate function Error Graph */ 
static void GenFuncErrorGraph(int gp) 
{ 
	PGraphNode gn; 
	while (gp > NIL) { 
		gn = GetGraphP(gp); 
		switch(gn->type) { 
		case T_OPT: 
			GenFuncErrorGraph(gn->INNER); 
			break; 
		case T_REP: 
			{ 
			PGraphNode gn1 = GetGraphP(gn->INNER); 
			if (gn1->type == T_WT) GenFuncErrorGraph(gn1->next); 
			else GenFuncErrorGraph(gn->INNER); 
			break; 
			} 
		case T_ALT: 
			{ 
			int gen_err = TRUE; 
			int gp1; 
			PGraphNode gn1; 
			gp1 = gp; 
			while (gp1) { 
				gn1 = GetGraphP(gp1); 
				if (IsNullableGraph(gn1->INNER)) gen_err = FALSE; 
				GenFuncErrorGraph(gn1->INNER); 
				gp1 = gn1->ALT; 
			} 
 
			if (!gen_err && gn->next <= NIL) gen_err = TRUE; 
			if (gen_err) { 
				PNTermNode ntn = GetNTermP(CurrentNt); 
				sprintf(temp_str, "unexpected symbol in %s", ntn->name); 
				DeclareError(temp_str); 
			} 
			break; 
			} 
		case T_SYNC: 
			{ 
			PNTermNode ntn = GetNTermP(CurrentNt); 
			sprintf(temp_str, "unexpected symbol in %s", ntn->name); 
			DeclareError(temp_str); 
			break; 
			} /* case */ 
		} /* switch */ 
		gp = gn->next; 
	} 
} 
 
static void GenParseError(PNTermNode ntn, int ntp) 
{ 
	if (ntp == 0) return; 
	CurrentNt = ntp; 
	GenFuncErrorGraph(ntn->graph); 
} 
 
/* generate header only */ 
static void GenParseHeader(PNTermNode ntn, int ntp) 
{ 
	if (ntp == 0) return; 
	GenFuncHeader(ntn, 1); 
} 
 
/* generate terminal error */ 
static void GenTermError(PTermNode tn) 
{ 
	char temp[MAX_ID_LEN], temp2[MAX_ID_LEN + 50]; 
	strcpy(temp, tn->name); 
	if (temp[0] == '"' || temp[0] == '\'') { 
		temp[0] = ' '; 
		temp[strlen(temp) - 1] = ' '; 
	} 
	sprintf(temp2, "%s expected", temp); 
	DeclareError(temp2); 
} 
 
/* generate pragma code */ 
static void GenPragma(PPragmaNode pn, int pp) 
{ 
	if (pn->has_attr == 0) return; 
	GenCode(fparser, "if (Sym == %T) { /*%d*/$$", pp + no_sym + 1, pp + no_sym + 1); 
	GenSemCode(1, (long) pn->sem_text.pos, pn->sem_text.len, 
			pn->sem_text.line, pn->sem_text.col, TRUE); 
	GenCode(fparser, "} else$$"); 
} 
 
static int GetSymMax() 
{ 
	return Set_MaxIndex(&ALL_TERMS) / SET_NBITS + 1; 
} 
 
/* generate symbol sets code */ 
static void GenSymSet(PSymSetNode ssn, int ssp) 
{ 
	int i, c, max; 
	if (ssp> 0 && ssn->type != T_WT) return; 
	max = GetSymMax(); 
 
	GenCode(fparser, "/*"); 
	Set_GetRange(&ssn->set, &i, &c); 
	for (; i <= c; i++) 
		if (Set_IsItem(&ssn->set, i)) GenCode(fparser, "%T ", i); 
	GenCode(fparser, "*/$$"); 
 
	GenCode(fparser, "{"); 
	c = ssn->set.size; 
	for (i = 0; i < c; i++) { 
		GenCode(fparser, "0x%x", ssn->set.data[i]); 
		if (i < max - 1) GenCode(fparser, ","); 
	} 
	for (; i < max; i++) { 
		GenCode(fparser, "0x0"); 
		if (i < max - 1) GenCode(fparser, ","); 
	} 
	GenCode(fparser, "},$$"); 
} 
 
void GenParserErrors(FILE *Out) 
{ 
	fherror = Out; 
	ErrorNo = 0; 
	Collection_ForEach(&term_tab, (Collection_Func) GenTermError); 
	ErrorNo = Collection_Count(&term_tab); 
	Collection_ForEachPos(&nterm_tab, (Collection_FuncPos) GenParseError); 
} 
 
/* generate parser */ 
int GenParserOptions(FILE *Out, char *option) 
{ 
	fparser = Out; 
 
	if (!stricmp(option, "UserDeclarations")) { 
		if (global_defs.pos>0) { 
			GenSemCode(0, global_defs.pos, 
			global_defs.len, 
			global_defs.line, 1, FALSE); 
		} 
	} else 
	if (!stricmp(option, "Declarations")) { 
		GenCode(fparser, "#define MAXSYM\t\t%d$$", GetSymMax()); 
	} else 
	if (!stricmp(option, "MaxSymSets")) { 
		GenCode(fparser, "%d", GetSymMax()); 
	} else 
	if (!stricmp(option, "MaxErr")) { 
		GenCode(fparser, "%d", ErrorNo); 
	} else 
 
	if (!stricmp(option, "SymSets")) { 
		Collection_ForEachPos(&symset_tab, (Collection_FuncPos) GenSymSet); 
	} else 
	if (!stricmp(option, "Pragmas")) { 
		Collection_ForEachPos(&pragma_tab, (Collection_FuncPos) GenPragma); 
		GenCode(fparser, "/* Empty Stmt */ ;"); 
	} else 
	if (!stricmp(option, "ProdHeaders")) { 
		Collection_ForEachPos(&nterm_tab, (Collection_FuncPos) GenParseHeader); 
	} else 
	if (!stricmp(option, "Productions")) { 
		ErrorNo = Collection_Count(&term_tab); 
		Collection_ForEachPos(&nterm_tab, (Collection_FuncPos) GenParseBody); 
	} else 
	if (!stricmp(option, "ParseRoot")) { 
		GenCode(fparser, "%s();", compiler_name); 
	} else return 0; 
 
	return 1; 
} 
 
static void downshift(char *s) 
{ 
	while (*s) { 
		if (*s >= 'A' && *s <= 'Z') *s += 32; 
		s++; 
	} 
} 
 
/* make parser */ 
void MakeParser() 
{ 
	PNTermNode nt; 
	int i; 
 
	strcpy(module_prefix, compiler_name); 
	module_prefix[6] = '\0'; 
	downshift(module_prefix); 
	i = FindNTerm(compiler_name); 
	nt = GetNTermP(i); 
	Set_AddItem(&nt->follow, 0); /* Follow(StartSymbol) = EOF */ 
	CompSymbolSets(); 
}