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

📄 crt.c

📁 COCO類似C的編譯器
💻 C
📖 第 1 页 / 共 3 页
字号:
{
	PSymSetNode sn;
	if (sp == NIL) return;
	sn = GetSymSetP(sp);
	Set_Union(set, &sn->set);
}

/* symset union by index */
void IncludeSymSet(int sp, PSet set)
{
	PSymSetNode sn;
	sn = GetSymSetP(sp);
	CR_ASSERT(sn != NULL);
	Set_Union(&sn->set, set);
}

/* symset diference by index */
void ExcludeSymSet(int sp, PSet set)
{
	PSymSetNode sn;
	sn = GetSymSetP(sp);
	CR_ASSERT(sn != NULL);
	Set_Diference(&sn->set, set);
}

/* show symset */
static void Func_ShowSymSet(PSymSetNode sn, int sp)
{
	CR_ASSERT(sn != NULL);
	fprintf(lstfile, "%3d|", sp);
	switch (sn->type) {
	case T_WT  :
		fprintf(lstfile, "WEAK T = \t");
		break;
	case T_ANY :
		fprintf(lstfile, "ANY    = \t");
		break;
	case T_SYNC:
		fprintf(lstfile, "SYNC   = \t");
		break;
	}
	Set_ForEach(&sn->set, (Set_Func) PrintTerm);
	fprintf(lstfile, "\n");
}

void ShowSymSetTab(void)
{
	fprintf(lstfile, "\nSYMBOL SETS\n");
	Collection_ForEachPos(&symset_tab, (Collection_FuncPos) Func_ShowSymSet);
}

/*****************************************************************
***         Nonterminals management Functions                  ***
*****************************************************************/

/* find a nonterminal by name */
static int CompNTerm(PNTermNode ntn, PName name)
{
	return !strcmp(ntn->name, name);
}

int FindNTerm(PName name)
{
	int ntp;
	ntp = Collection_FirstThat(&nterm_tab, (Collection_Comp) CompNTerm, name);
	return ntp;
}

/* install a nonterminal */
int NewNTerm(PName name)
{
	int ntp;
	PNTermNode ntn;

	if ((ntp = FindNTerm(name)) == UNDEF) {
		ntp = Collection_New(&nterm_tab);
		ntn = GetNTermP(ntp);
		CR_ASSERT(ntn != NULL);
		strcpy(ntn->name, name);
		ntn->graph     = NIL;
		ntn->sem       = NIL;
		ntn->nullable  = FALSE;
		ntn->ready     = FALSE;
		ntn->has_attr  = FALSE;
		ntn->reachable = FALSE;
		ntn->attr      = NIL;
		Set_Init(&ntn->first);
		Set_Init(&ntn->follow);
		Set_Init(&ntn->AuxNt);
	}
	return ntp;
}

/* get nonterminal First Set */
static void GetNTermFirst(int ntp, Set *first)
{
	PNTermNode ntn;
	ntn = GetNTermP(ntp);
	CR_ASSERT(ntn != NULL);
	Set_Union(first, &(ntn->first));
}

/* get nonterminal Follow Set */
static void GetNTermFollow(int ntp, Set *follow)
{
	PNTermNode ntn;
	ntn = GetNTermP(ntp);
	CR_ASSERT(ntn != NULL);
	Set_Union(follow, &(ntn->follow));
}

/* get nonterminal Nullable */
static int IsNTermNullable(int ntp)
{
	PNTermNode ntn;
	ntn = GetNTermP(ntp);
	CR_ASSERT(ntn != NULL);
	return ntn->nullable;
}

/* show nonterminal */
static void Func_ShowNTerm(PNTermNode ntn, int ntp)
{
	if (!ntp) return;
	fprintf(lstfile, "%3d|%s\t:", ntp, ntn->name);
	if (ntn->nullable) fprintf(lstfile, "    (Nullable)");
	if (G_option) {
		fprintf(lstfile, "\n\tGraph: ");
		ShowGraph(ntn->graph);
	}
	if (F_option) {
		fprintf(lstfile, "\n\tStart With :\t");
		Set_ForEach(&ntn->first, (Set_Func) PrintTerm);
		fprintf(lstfile, "\n\tFollow =\t");
		Set_ForEach(&ntn->follow, (Set_Func) PrintTerm);
	}
	fprintf(lstfile, "\n");
}

/* show nonterminal tab */
void ShowNTermTab(void)
{
	fprintf(lstfile, "\nNO TERMINALS\n");
	Collection_ForEachPos(&nterm_tab, (Collection_FuncPos) Func_ShowNTerm);
}

/* apply "fn" to each nonterminal graph */
static void ForEachNTermGraph(Graph_Func fn)
{
	PNTermNode ntn;
	int c, i;
	c = Collection_Count(&nterm_tab);
	for (i = 1; i < c; i++) { /* for each nonterminal */
		CurrentNt = i;
		ntn = GetNTermP(i);
		CR_ASSERT(ntn != NULL);
		(*fn) (ntn->graph);
	}
}

/* apply "fn" to each nonterminal graph pasing an "p" as parameter */
static void ForEachNTermGraph_Int(Graph_FuncInt fn, int p)
{
	PNTermNode ntn;
	int c, i;
	c = Collection_Count(&nterm_tab);
	for (i = 1; i < c; i++) {
		CurrentNt = i;
		ntn = GetNTermP(i);
		CR_ASSERT(ntn != NULL);
		(*fn) (ntn->graph, p);
	}
}

/*****************************************************************
***          First & Follow Functions                          ***
*****************************************************************/

/* compute follow links in a graph */
void CompFollowNode(int gp, int fgp)
{
	PGraphNode gn;
	int next;

	while (gp>NIL) {
		gn = GetGraphP(gp);
		CR_ASSERT(gn != NULL);
		next = (gn->next != NIL) ? gn->next : fgp;
		switch(gn->type) {
		case T_OPT:
			CompFollowNode(gn->INNER, next);
			break;
		case T_REP:
			CompFollowNode(gn->INNER, gp);
			break;
		case T_ALT:
			{
				PGraphNode gn1;
				int gp1 = gp;
				while (gp1 > NIL) {
					gn1 = GetGraphP(gp1);
					CR_ASSERT(gn1 != NULL);
					CompFollowNode(gn1->INNER, next);
					gp1 = gn1->ALT;
				}
				break;
			}
		}
		if (gn->next == NIL) gn->next = -fgp;
		gp = gn->next;
	}
}

/* compute Follow links for all graphs */
static void CompAllFollowNodes(void)
{
	ForEachNTermGraph_Int((Graph_FuncInt) CompFollowNode, 0);
}

/* TRUE => node is Nullable */
static int IsNullableNode(int gp)
{
	PGraphNode gn;
	if (gp <= NIL) return TRUE;
	gn = GetGraphP(gp);
	CR_ASSERT(gn != NULL);
	switch(gn->type) {
	case T_NT :
		return IsNTermNullable(gn->SYMLINK);
	case T_OPT:
	case T_REP:
	case T_SEM:
	case T_SYNC:
		return TRUE;
	case T_ALT:
		if (IsNullableGraph(gn->INNER)) return TRUE;
		if (gn->ALT) return IsNullableNode(gn->ALT);
	}
	return FALSE; /* Terminal, Weak Terminal => Not Nullable */
}

/* TRUE => graph is Nullable */
int IsNullableGraph(int gp)
{
	if (gp <= NIL) return TRUE;
	if (IsNullableNode(gp)) {
		PGraphNode gn = GetGraphP(gp);
		CR_ASSERT(gn != NULL);
		return IsNullableGraph(gn->next);
	}
	return FALSE;
}

/* TRUE => graph is Nullable (use follow links) */
static int IsNullableNextGraph(int gp)
{
	if (gp <= NIL) return TRUE;
	if (IsNullableNode(gp)) {
		PGraphNode gn = GetGraphP(gp);
		CR_ASSERT(gn != NULL);
		return IsNullableNextGraph(abs(gn->next));
	}
	return FALSE;
}

static void CompAllNullable(void)
{
	PNTermNode ntn;
	int i, c, change;

	do { /* Loop until nothing changes */
		change = FALSE;
		c = Collection_Count(&nterm_tab);
		for (i = 1; i < c; i++) { /* for each nonterminal */
			ntn = GetNTermP(i);
			CR_ASSERT(ntn != NULL);
			if (!ntn->nullable)
				if (IsNullableNextGraph(ntn->graph)) {
					ntn->nullable = TRUE;
					ntn->ready    = TRUE;
					change        = TRUE;
				}
		}
	} while (change);
}

/* get First Terminals of a graph
   STRICT = TRUE ==> don't use follow links
*/
static void CompFirst(int gp, Set *first, int STRICT)
{
	PGraphNode gn;

	while (gp > NIL && !Set_IsItem(&FirstVisited, gp)) {
		Set_AddItem(&FirstVisited, gp);
		gn = GetGraphP(gp);
		CR_ASSERT(gn != NULL);
		switch(gn->type) {
		case T_T :
		case T_WT:
			Set_AddItem(first, gn->SYMLINK);
			break;
		case T_NT :
			{
				PNTermNode ntn = GetNTermP(gn->SYMLINK);
				CR_ASSERT(ntn != NULL);
				if (ntn->ready) GetNTermFirst(gn->SYMLINK, first);
				else CompFirst(ntn->graph, first, STRICT);
				break;
			}
		case T_ANY:
			GetSymSet(gn->SETLINK1, first);
			break;
		case T_OPT:
		case T_REP:
		case T_ALT:
			CompFirst(gn->INNER, first, STRICT);
			if (gn->type == T_ALT) CompFirst(gn->ALT, first, STRICT);
			break;
		}
		if (!IsNullableNode(gp)) break; /* Nullable => Continue */
		gp = (STRICT)? gn->next: abs(gn->next);
	}
}

/* get First Set of a graph */
void CompFirstSet(int gp, PSet first)
{
	Set_Clean(&FirstVisited);
	CompFirst(gp, first, TRUE);
}

/* get First Set of a graph (use follow links) */
static void CompNextFirstSet(int gp, Set *first)
{
	Set_Clean(&FirstVisited);
	CompFirst(gp, first, FALSE);
}

static void CompNTermFirstSet(PNTermNode ntn)
{
	ntn->ready = FALSE;
	CompFirstSet(ntn->graph, &ntn->first);
	ntn->ready = TRUE;
}

/* compute all First Sets of a nonterminal */
static void CompAllFirstSets(void)
{
	Collection_ForEach(&nterm_tab, (Collection_Func) CompNTermFirstSet);
}

/* compute Follow Set of each nonterminal in graph */
static void CompFollowSet(int gp)
{
	PGraphNode gn;

	while (gp > NIL && !Set_IsItem(&FollowVisited, gp)) {
		Set_AddItem(&FollowVisited, gp);
		gn = GetGraphP(gp);
		CR_ASSERT(gn != NULL);
		switch(gn->type) {
		case T_NT:
			{
				PNTermNode ntn = GetNTermP(gn->SYMLINK);
				CR_ASSERT(ntn != NULL);
				CompNextFirstSet(abs(gn->next), &(ntn->follow));
				if (IsNullableNextGraph(abs(gn->next)))
					Set_AddItem(&ntn->AuxNt, CurrentNt);
				break;
			}
		case T_OPT:
		case T_REP:
		case T_ALT:
			CompFollowSet(gn->INNER);
			if (gn->type == T_ALT) CompFollowSet(gn->ALT);
			break;
		}
		gp = gn->next;
	}
}

/* complete follow set by indirect nonterminal links */
static void CompleteFollow(int curr_nt)
{
	int i, c;
	PNTermNode ntn, ntn1;

	if (Set_IsItem(&FollowVisited, curr_nt)) return;
	Set_AddItem(&FollowVisited, curr_nt);
	ntn = GetNTermP(curr_nt);
	CR_ASSERT(ntn != NULL);
	Set_GetRange(&ntn->AuxNt, &i, &c);
	for (; i <= c; i++)
		if (Set_IsItem(&ntn->AuxNt, i)) {
			ntn1 = GetNTermP(i);
			CR_ASSERT(ntn1 != NULL);
			CompleteFollow(i);
			Set_Union(&ntn->follow, &ntn1->follow);
			Set_DelItem(&ntn->AuxNt, i);
		}
}

static void Func_CompFollowSet(int gp)
{
	Set_Clean(&FollowVisited);
	CompFollowSet(gp);
}

static void Func_CompleteFollowSet(int gp)
{
	Set_Clean(&FollowVisited);
	CompleteFollow(CurrentNt);
}

/* compute Follow of all nonterminals */
static void CompAllFollowSets(void)
{
	ForEachNTermGraph((Graph_Func) Func_CompFollowSet);
	ForEachNTermGraph((Graph_Func) Func_CompleteFollowSet);
}

/* return graph node index of a leading ANY in graph */
static int LeadingANY(int gp)
{
	PGraphNode gn;
	int a;

	if (gp <= NIL) return NIL;
	gn = GetGraphP(gp);
	CR_ASSERT(gn != NULL);
	switch (gn->type) {
	case T_ANY:
		return gp;
	case T_OPT:
	case T_REP:
		return LeadingANY(gn->INNER);
	case T_ALT:
		if ((a = LeadingANY(gn->INNER)) != NIL) return a;
		return a = LeadingANY(gn->ALT);
	}
	if (IsNullableNode(gp)) return LeadingANY(gn->next);
	return NIL;
}

/* exclude terminals from ANY set */
static void ExcludeANY(int gp, PSet set)
{
	PGraphNode gn;
	gn = GetGraphP(gp);
	CR_ASSERT(gn != NULL);
	if (gn->SETLINK1 == NIL) gn->SETLINK1 = NewANY();
	ExcludeSymSet(gn->SETLINK1, set);
}

/* compute ANY sets in graph */
static void CompANYSet(int gp)
{
	PGraphNode gn;
	Set set;

	Set_Init(&set);
	while (gp > NIL) {
		gn = GetGraphP(gp);
		CR_ASSERT(gn != NULL);
		switch(gn->type) {
		case T_OPT:
		case T_REP:
			{
				int a;
				CompANYSet(gn->INNER);
				if ((a = LeadingANY(gn->INNER)) != NIL) {
					Set_Clean(&set);
					CompExpected(abs(gn->next), CurrentNt, &set);
					ExcludeANY(a, &set);
				}
				break;
			}
		case T_ALT:
			{
				int gp1 = gp;
				int a;
				PGraphNode gn1;

				Set_Clean(&set);
				while (gp1 != NIL) {
					gn1 = GetGraphP(gp1);
					CR_ASSERT(gn1 != NULL);
					CompANYSet(gn1->INNER);
					if ((a = LeadingANY(gn1->INNER)) != NIL) {
						CompExpected(gn1->ALT, CurrentNt, &set);
						ExcludeANY(a, &set);
					} else CompExpected(gn1->INNER, CurrentNt, &set);
					gp1 = gn1->ALT;
				}
				break;
			} /* case */
		} /* switch */
		gp = gn->next;
	}
	Set_Done(&set);
}

static void Func_CompAnySet(int gp)
{
	Set_Clean(&FollowVisited);
	CompANYSet(gp);
}

/* compute all ANY sets */
static void CompAllANYSets(void)
{
	ForEachNTermGraph((Graph_Func) Func_CompAnySet);
}

/* compute SYNC sets in a graph */
static void CompSYNCSet(int gp)
{
	PGraphNode gn;
	Set set;

	Set_Init(&set);
	while (gp > NIL) {
		gn = GetGraphP(gp);
		CR_ASSERT(gn != NULL);
		switch(gn->type) {
		case T_SYNC:
			Set_Clean(&set);
			CompExpected(abs(gn->next), CurrentNt, &set);
			Set_AddItem(&set, EOFSYM);
			IncludeSymSet(ALL_SYNCS, &set);
			gn->SETLINK1 = NewSymSet(&set, T_SYNC);
			break;
		case T_OPT:
		case T_REP:
		case T_ALT:
			CompSYNCSet(gn->INNER);
			if (gn->type == T_ALT) CompSYNCSet(gn->ALT);
			break;
		}
		gp = gn->next;
	}
	Set_Done(&set);
}

/* compute all SYNC sets */
static void CompAllSYNCSets(void)
{
	Set set;

	Set_Init(&set);
	Set_AddItem(&set, EOFSYM);
	IncludeSymSet(ALL_SYNCS, &set);
	ForEachNTermGraph((Graph_Func) CompSYNCSet);
}

/* compute WEAK Terminal sets in a graph */
static void CompWEAKSet(int gp)
{
	PGraphNode gn, gn1;
	Set set;

	Set_Init(&set);
	while (gp > NIL) {
		gn = GetGraphP(gp);
		CR_ASSERT(gn != NULL);
		switch(gn->type) {
		case T_WT:
			Set_Clean(&set);
			CompExpected(abs(gn->next), CurrentNt, &set);  /* Follow WEAK TERMINAL */
			gn->SETLINK1 = NewSymSet(&set, T_WT);
			break;
		case T_REP:
			gn1 = GetGraphP(gn->INNER);
			CR_ASSERT(gn1 != NULL);
			if (gn1->type == T_WT) {
				Set_Clean(&set);
				CompExpected(abs(gn->next), CurrentNt, &set); /* Follow LOOP */
				gn1->SETLINK2 = NewSymSet(&set, T_WT);
			}
			CompWEAKSet(gn->INNER);
			break;
		case T_OPT:
		case T_ALT:

⌨️ 快捷键说明

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