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

📄 crt.c

📁 COCO類似C的編譯器
💻 C
📖 第 1 页 / 共 3 页
字号:
			CompWEAKSet(gn->INNER);
			if (gn->type == T_ALT) CompWEAKSet(gn->ALT);
			break;
		}
		gp = gn->next;
	}
	Set_Done(&set);
}

/* compute all WEAK sets */
static void CompAllWEAKSets(void)
{
	ForEachNTermGraph((Graph_Func) CompWEAKSet);
}

/* compute set of all terminals except pragmas */
static void CompALLTermsSet(void)
{
	Set_Clean(&ALL_TERMS);
	Set_AddRange(&ALL_TERMS, 1, Collection_Count(&term_tab) - 1);
}

static void Func_NTermDeclared(PNTermNode ntn, int ntp)
{
	if (ntp == 0) return;
	if (ntn->graph == NIL) {
		if (Q_option) {
			fprintf(lstfile, "(%s)  (%d, %d )",
			        source_name, ntn->line_use, 0);
			fprintf(lstfile, " %s Not Declared\n", ntn->name);
		}
		else {
			fprintf(lstfile, "\"%s\", Line %d, Col %d :",
			        source_name, ntn->line_use, 0);
			fprintf(lstfile, "**** %s Not Declared\n", ntn->name);
		}
		Errors++;
	} else
	if (!ntn->reachable) {
		if (Q_option) {
			fprintf(lstfile, "(%s)  (%d, %d )",
			        source_name, ntn->line_dec, 0);
			fprintf(lstfile, " %s Declared but not used\n", ntn->name);
		}
		else {
			fprintf(lstfile, "\"%s\", Line %d, Col %d :",
			        source_name, ntn->line_dec, 0);
			fprintf(lstfile, "**** %s Declared but not used\n", ntn->name);
		}
		Errors++;
	}
}

/* check if a nonterminal was use but not defined, or defined and not used */
static void CheckNTermDeclared(void)
{
	Collection_ForEachPos(&nterm_tab, (Collection_FuncPos) Func_NTermDeclared);
}

static void Func_NTermNullable(PNTermNode ntn, int ntp)
{
	if (! ntn->nullable || ntp == 0) return;
	if (Q_option) {
		fprintf(lstfile, "(%s)  (%d, %d )",
		        source_name, S_Line, 0);
		fprintf(lstfile, " Warning : %s is nullable\n", ntn->name);
	}
	else {
		fprintf(lstfile, "\"%s\", Line %d, Col %d :",
		        source_name, S_Line, 0);
	fprintf(lstfile, "**** Warning : %s is nullable\n", ntn->name);
	}
}

/* check if a nonterminal is nullable */
static void CheckNTermNullable(void)
{
	Collection_ForEachPos(&nterm_tab, (Collection_FuncPos) Func_NTermNullable);
}

/* check for nonterminal circular derivations */
static int CompCircularGraph(int gp)
{
	PGraphNode gn;
	int t;

	while (gp > NIL) {
		gn = GetGraphP(gp);
		CR_ASSERT(gn != NULL);
		switch(gn->type) {
		case T_T :
		case T_WT:
			return FALSE;
		case T_NT :
			{
				PNTermNode ntn = GetNTermP(gn->SYMLINK);
				CR_ASSERT(ntn != NULL);
				if (gn->SYMLINK == CurrentNt) return CurrentNt;
				if (Set_IsItem(&Set1, gn->SYMLINK)) return FALSE;
				Set_AddItem(&Set1, gn->SYMLINK);
				if (CompCircularGraph(ntn->graph)) return gn->SYMLINK;
				break;
			}
		case T_OPT:
		case T_REP:
		case T_ALT:
			if ((t = CompCircularGraph(gn->INNER)) != FALSE) return t;
			if (gn->type == T_ALT)
				if ((t = CompCircularGraph(gn->ALT)) != FALSE) return t;
			break;
		}
		if (!IsNullableNode(gp)) break; /* Nullable => Continue */
		gp = gn->next;
	}
	return FALSE;
}

static void Func_CheckCircular(PNTermNode ntn, int ntp)
{
	int t;
	Set_Clean(&Set1);
	CurrentNt = ntp;
	if ((t = CompCircularGraph(ntn->graph)) != FALSE) {
		PNTermNode ntn1 = GetNTermP(t);
		if (Q_option)
			fprintf(lstfile, " Circular Derivation %s -> %s\n", ntn->name, ntn1->name);
		else
			fprintf(lstfile, "**** Circular Derivation %s -> %s\n", ntn->name, ntn1->name);
		Errors++;
	}
}

static void CheckCircular(void)
{
	Collection_ForEachPos(&nterm_tab, (Collection_FuncPos) Func_CheckCircular);
}

static int IsTerminalGraph(int gp)
{
	PGraphNode gn;
	while (gp > NIL) {
		gn = GetGraphP(gp);
		CR_ASSERT(gn != NULL);
		switch(gn->type) {
		case T_NT:
			if (!Set_IsItem(&Set1, gn->SYMLINK)) return FALSE;
			break;
		case T_ALT:
			if (!IsTerminalGraph(gn->INNER) &&
					((gn->ALT == NIL) || !IsTerminalGraph(gn->ALT))) return FALSE;
			break;
		}
		gp = gn->next;
	}
	return TRUE;
}

/* check if a nonterminal can derive to terminals */
static void CheckDeriveTerminals(void)
{
	PNTermNode ntn;
	int c, i, change;

	Set_Clean(&Set1);
	c = Collection_Count(&nterm_tab);
	do {
		change = FALSE;
		for (i = 1; i < c; i++) /* for each Nonterminal */
			if (!Set_IsItem(&Set1, i)) {
				ntn = GetNTermP(i);
				CR_ASSERT(ntn != NULL);
				if (IsTerminalGraph(ntn->graph)) {
					Set_AddItem(&Set1, i);
					change = TRUE;
				}
			}
	} while (change);

	for (i = 1; i < c; i++) /* for each nonterminal */
		if (!Set_IsItem(&Set1, i)) {
			ntn = GetNTermP(i);
			CR_ASSERT(ntn != NULL);
			if (Q_option)
				fprintf(lstfile, " %s Can't derive to Terminals\n", ntn->name);
			else
				fprintf(lstfile, "**** %s Can't derive to Terminals\n", ntn->name);
			Errors++;
		}
}

/* Generate LL(1) errors */
static void LL1Error(int c, int i)
{
	PNTermNode ntn;
	PTermNode tn;

	ntn = GetNTermP(CurrentNt);
	CR_ASSERT(ntn != NULL);
	if (Q_option) {
		fprintf(lstfile, "(%s)  (%d, %d )",
		        source_name, S_Line, 0);
		fprintf(lstfile, " LL(1) Error in %s: ", ntn->name);
	}
	else {
		fprintf(lstfile, "\"%s\", Line %d, Col %d :",
		        source_name, S_Line, 0);
		fprintf(lstfile, "**** LL(1) Error in %s: ", ntn->name);
	}
	if (i > 0) {
		tn = GetTermP(i);
		fprintf(lstfile, "%s is the ", tn->name);
	}
	switch (c) {
	case 1:
		fprintf(lstfile, "start of several alternatives.\n");
		break;
	case 2:
		fprintf(lstfile, "start & successor of nullable structures.\n");
		break;
	case 3:
		fprintf(lstfile, "an ANY node matches no symbol.\n");
		break;
	}
}

/* check if two sets have items in common */
static void CheckSets(int cond, Set *s1, Set *s2)
{
	int i, c;
	Set_GetRange(s1, &i, &c);
	for (; i <= c; i++)
		if (Set_IsItem(s1, i) && Set_IsItem(s2, i)) LL1Error(cond, i);
}

/* perform LL(1) checks in graph */
static void Func_CheckLL1Graph(int gp)
{
	PGraphNode gn;
	while (gp > NIL) {
		gn = GetGraphP(gp);
		CR_ASSERT(gn != NULL);
		switch(gn->type) {
		case T_ALT:
			{
				PGraphNode gn1;
				int gp1;
				gp1 = gp;
				Set_Clean(&Set1);
				while (gp1 > NIL) {
					gn1 = GetGraphP(gp1);
					CR_ASSERT(gn1 != NULL);
					Set_Clean(&Set2);
					CompExpected(gn1->INNER, CurrentNt, &Set2);
					CheckSets(1, &Set1, &Set2);
					Set_Union(&Set1, &Set2);
					gp1 = gn1->ALT;
				}
				gp1 = gp;
				while (gp1 > NIL) {
					gn1 = GetGraphP(gp1);
					CR_ASSERT(gn1 != NULL);
					Func_CheckLL1Graph(gn1->INNER);
					gp1 = gn1->ALT;
				}
				break;
			}
		case T_OPT:
		case T_REP:
			Set_Clean(&Set1);
			Set_Clean(&Set2);
			CompExpected(gn->INNER, CurrentNt, &Set1);
			CompExpected(abs(gn->next), CurrentNt, &Set2);
			CheckSets(2, &Set1, &Set2);
			Func_CheckLL1Graph(gn->INNER);
			break;
		case T_ANY:
			Set_Clean(&Set1);
			GetSymSet(gn->SETLINK1, &Set1);
			if (Set_Empty(&Set1)) LL1Error(3, 0);
			break;
		}
		gp = gn->next;
	}
}

static void CheckLL1(void)
{
	ForEachNTermGraph((Graph_Func) Func_CheckLL1Graph);
}

/* compute all symbol sets needed */
void CompSymbolSets(void)
{
	CheckNTermDeclared();
	if (Errors) return;
	CheckDeriveTerminals();
	if (Errors) return;
	CompALLTermsSet();
	SetupPragmas();
	CompAllFollowNodes();
	CompAllNullable();
	CheckNTermNullable();
	CheckCircular();
	if (Errors) return;

	CompAllFirstSets();
	CompAllFollowSets();
	CompAllANYSets();

	CompAllFirstSets();    /* Second Time: In very few cases */
	CompAllFollowSets();   /* ANY sets can add information to first */
	CompAllANYSets();      /* and Follow */

	CompAllSYNCSets();
	CompAllWEAKSets();
	CheckLL1();
}

/* get expected next symbols */
void CompExpected(int gp, int nterm, Set *set)
{
	CompNextFirstSet(gp, set);
	if (IsNullableNextGraph(gp)) GetNTermFollow(nterm, set);
}

/*****************************************************************
***          General purpose Functions                         ***
*****************************************************************/

/* add ignore sets */
void AddIgnore(Set *set)
{
	int cp;
	PClassNode cn;

	cp = FindClass("@ignore_chars");
	if (cp != UNDEF) {
		cn = GetClassP(cp);
		Set_Union(&cn->data, set);
	}
}

/* install a symbol */
int NewSym(PName name, int typ)
{
	int sp = 0;

	switch (typ) {
	case T_T:
	case T_WT:
		sp = NewTerm(name);
		break;
	case T_P:
		sp = NewPragma(name);
		break;
	case T_NT:
		sp = NewNTerm(name);
		break;
	}
	return sp;
}

/* find symbol */
int FindSym(PName name, int *typ)
{
	int sp;

	sp = FindClass(name);
	if (sp > UNDEF) {
		*typ = T_CLASS;
		return sp;
	}

	sp = FindTerm(name);
	if (sp > UNDEF) {
		*typ = T_T;
		return sp;
	}

	sp = FindPragma(name);
	if (sp > UNDEF) {
		*typ = T_P;
		return sp;
	}

	sp = FindNTerm(name);
	if (sp > UNDEF) {
		*typ = T_NT;
		return sp;
	}

	return UNDEF;
}

/* print ascii char */
void PrintAscii(int s)
{
	if (s <= 32) fprintf(lstfile, " #%d ", s);
	else fprintf(lstfile, "%c", s);
}

/* print integer */
void PrintInt(int s)
{
	fprintf(lstfile, "%d ", s);
}

/* print terminal */
static void PrintTerm(int tp)
{
	PTermNode tn;
	tn = GetTermP(tp);
	fprintf(lstfile, "%s ", tn->name);
}

/* print nonterminal */
static void PrintNTerm(int ntp)
{
	PNTermNode ntn;
	ntn = GetNTermP(ntp);
	CR_ASSERT(ntn != NULL);
	fprintf(lstfile, "%s ", ntn->name);
}


/* create & initialize all module variables */
void InitTab(void)
{
	Collection_Init(&nterm_tab, sizeof(NTermNode), NTERM_SIZE, NTERM_EXTEND);
	Collection_Init(&term_tab, sizeof(TermNode), TERM_SIZE, TERM_EXTEND);
	Collection_Init(&nodes_tab, sizeof(GraphNode), NODES_SIZE, NODES_EXTEND);
	Collection_Init(&class_tab, sizeof(ClassNode), CLASS_SIZE, CLASS_EXTEND);
	Collection_Init(&symset_tab, sizeof(SymSetNode), SYMSET_SIZE, SYMSET_EXTEND);
	Collection_Init(&pragma_tab, sizeof(PragmaNode), PRAGMA_SIZE, PRAGMA_EXTEND);
	Collection_Init(&name_tab, sizeof(NameNode), NAME_SIZE, NAME_EXTEND);

	Set_Init(&ANY_SET);
	Set_Init(&ALL_TERMS);
	Set_Init(&FirstVisited);
	Set_Init(&FollowVisited);
	Set_Init(&Set1);
	Set_Init(&Set2);

	Set_Clean(&ANY_SET);
	(void) NewSymSet(&ANY_SET, T_SYNC);           /* ALL SYNCS symset 0 */

	Set_AddItem(&ANY_SET, ' ');
	(void) NewClass("@ignore_chars", &ANY_SET);  /* IGNORE SET 0 */

	(void) NewSym("EOF", T_T);                   /* EOF_Sym term 0 */
	(void) NewSym("@NTERM", T_NT);               /* No Terminal 0 */

	(void) MakeGraphNode(0);                     /* graph Node 0 */
	Set_AddRange(&ANY_SET, 1, 255);              /* ANY SET */
}

void CleanGraphTab(void)
{
	Collection_Clean(&nodes_tab);
	(void) MakeGraphNode(0);                     /* graph Node 0 */
}

/* destroy all module variables */
void DoneTab(void)
{
	Collection_Done(&nterm_tab);
	Collection_Done(&term_tab);
	Collection_Done(&nodes_tab);
	Collection_Done(&class_tab);
	Collection_Done(&symset_tab);
	Collection_Done(&pragma_tab);
	Collection_Done(&name_tab);
	Set_Done(&ANY_SET);
	Set_Done(&ALL_TERMS);
	Set_Done(&FirstVisited);
	Set_Done(&FollowVisited);
	Set_Done(&Set1);
	Set_Done(&Set2);
}

char *SetVar(char *s)
{
	char name[200], value[200];
	char *n = name, *v = value;

	/* Get the variable name */
	while (*s && *s != '=') *n++ = *s++;
	*n='\0';

	if (*s == '=') s++;

	/* Get the variable Value */
	while (*s) *v++ = *s++;
	*v = '\0';

/*	printf("Variable %s = %s \n", name, value); */

	if (stricmp(name, "CRHEXT") == 0) strcpy(h_ext, value);
	if (stricmp(name, "CRCEXT") == 0) strcpy(c_ext, value);
	if (stricmp(name, "CRFRAMES") == 0) strcpy(Frames_Path, value);

	return s;
}

void SetOptions(char *s)
{
	while (*s) {
		switch (*s) {
		case 'A' :
		case 'a' :
			L_option = TRUE;
			A_option = TRUE;
			S_option = TRUE;
			break;
		case 'C' :
		case 'c' :
			C_option = TRUE;
			break;
		case 'F' :
		case 'f' :
			L_option = TRUE;
			F_option = TRUE;
			S_option = TRUE;
			break;
		case 'G' :
		case 'g' :
			L_option = TRUE;
			G_option = TRUE;
			S_option = TRUE;
			break;
		case 'L' :
		case 'l' :
			L_option = TRUE;
			break;
		case 'O' :
		case 'o' :
			O_option = TRUE;
			break;
		case 'P' :
		case 'p' :
			P_option = TRUE;
			break;
		case 'Q' :
		case 'q' :
			Q_option = TRUE;
			break;
		case 'S' :
		case 's' :
			L_option = TRUE;
			S_option = TRUE;
			break;
		case 'T' :
		case 't' :
			T_option = TRUE;
			break;
		case 'D' :
		case 'd' :
			if (s[1] == '\0')
				D_option = TRUE;
			else {
				s++;
				s=SetVar(s);
				return;
			}
			break;
		case 'X' :
		case 'x' :
			GenCplusplus = TRUE;
			strcpy(c_ext, "cpp");
			strcpy(h_ext, "hpp");
			break;
		case 'Z' :
		case 'z' :
			Z_option = TRUE;
			strcpy(c_ext, "cpp");
			strcpy(h_ext, "hpp");
			break;
		}
		s++;
	}
}

⌨️ 快捷键说明

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