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

📄 cra.c

📁 自己写的关于编译原理的实验报告的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	for (i = 0; i < c; i++) {
		melt = GetMeltedP(i);
		CR_ASSERT(melt != NULL);
		if (melt->state==s) {
			 Set_Union(set, &melt->set);
			 break;
		}
	}
}

/* get information about states_set */
static int GetStateSet(Set *state_set, Set *set, int *end_of, int *ctx)
{
	int f, s;
	int correct = TRUE;
	PStateNode state;
	char err[100];

	Set_Clean(set);
	*end_of = 0;
	*ctx = T_NONE;
	Set_GetRange(state_set, &s, &f);
	for ( ;s <= f; s++)
		if (Set_IsItem(state_set, s)) {
			if (s <= last_sim_state) Set_AddItem(set, s);
			else AddMeltSet(s, set);
			state = GetStateP(s);
			CR_ASSERT(state != NULL);
			if (state->end_of != 0) {
				if (*end_of == 0 || *end_of == state->end_of) {
					*end_of = state->end_of;
				} else {
					PTermNode tn1 = GetTermP(*end_of),
					tn2 = GetTermP(state->end_of);
					CR_ASSERT(tn1 != NULL);
					CR_ASSERT(tn2 != NULL);
					sprintf(err, "Tokens %s (%d) and %s (%d) cannot be distinguished.",
					tn1->name, *end_of, tn2->name, state->end_of);
					fprintf(lstfile, "%s\n", err);
					correct = FALSE;
				}
			}
			if (state->ctx != T_NONE) {
				*ctx = T_CONTEXT;
				if (state->end_of != 0) {
					PTermNode tn1 = GetTermP(*end_of),
					tn2 = GetTermP(state->end_of);
					CR_ASSERT(tn1 != NULL);
					CR_ASSERT(tn2 != NULL);
					sprintf(err, "Ambiguous CONTEXT clause. Tokens %s (%d) and %s (%d)",
					tn1->name, *end_of, tn2->name, state->end_of);
					fprintf(lstfile, "%s\n", err);
					correct = FALSE;
				}
			}
		}
	return correct;
}

/* copy all the transitions from state_set states to the state 'sn' */
static void FillWithTrans(int sn, Set *state_set)
{
	PTransNode t;
	TransNode t1;
	PStateNode state;
	Collection *trans_tab;
	int i, c, s, f;

	Set_GetRange(state_set, &s, &f);
	for (; s <= f ; s++)
		if (Set_IsItem(state_set, s)) {
			state = GetStateP(s);
			CR_ASSERT(state != NULL);
			trans_tab = &(state->trans_list);
			c = Collection_Count(trans_tab);
			for(i = 0; i < c; i++) {
				t = GetTransP(trans_tab, i);
				CR_ASSERT(t != NULL);
				Collection_Get(trans_tab, i, &t1);
				if (t->type != T_NONE) {
					Set_Init(&t1.to_states);
					Set_Copy(&t1.to_states, &t->to_states);
					AddTrans(sn, &t1);
				}
			}
		}
}

/* melt state_tab appearing with a shift of the same symbol */
static int MeltStates(int s)
{
	int s1, i, c, m, end_of, ctx, change, correct = TRUE;
	PStateNode state, state1;
	PMeltedNode melt;
	Collection *trans_tab;
	Set set;
	PTransNode a;

	Set_Init(&set);
	state = GetStateP(s);
	CR_ASSERT(state != NULL);
	trans_tab = &(state->trans_list);
	c = Collection_Count(trans_tab);
	for (i = 0; i < c; i++) {
		a = GetTransP(trans_tab, i);
		CR_ASSERT(a != NULL);
		if (a->type == T_NONE) continue;  /* Trans Deleted??? */
		if (Set_Elements(&a->to_states) <= 1) continue;  /* Trans to 1 state */
		/* Trans to more than 1 state => melt */
		if (!GetStateSet(&a->to_states, &set, &end_of, &ctx)) correct = FALSE;
		m = KnownMelt(&set);
		if (m == -1) {
			s1 = NewState();
			state1 = GetStateP(s1);
			CR_ASSERT(state1 != NULL);
			state1->end_of = end_of;
			state1->ctx = ctx;
			FillWithTrans(s1, &a->to_states);
			do {
				change = MakeUnique(s1);
			} while (change);
			m = NewMelt(&set, s1);
		}
		melt = GetMeltedP(m);
		CR_ASSERT(melt != NULL);
		Set_Clean(&a->to_states);
		Set_AddItem(&a->to_states, melt->state);
	}
	Set_Done(&set);
	return correct;
}

static void FindCtxStates()
{
	PStateNode state, state1;
	PTransNode t;
	Collection *trans_tab;
	int i, c, s, s1;

	for (s = root_state; s <= last_state; s++) {
		state = GetStateP(s);
		CR_ASSERT(state != NULL);
		trans_tab = &(state->trans_list);
		c = Collection_Count(trans_tab);
		for(i = 0; i < c; i++) {
			t = GetTransP(trans_tab, i);
			CR_ASSERT(t != NULL);
			if (t->type == T_NONE) continue;
			if (t->tc == T_CONTEXT) {
				s1 = Set_MinIndex(&t->to_states);
				state1 = GetStateP(s1);
				CR_ASSERT(state1 != NULL);
				state1->ctx = TRUE;
			}
		}
	}
}

/* mark the state reachable from valid transitions */
static int MarkToStates(PCollection trans_tab)
{
	int s, i, c, change;
	PTransNode t;
	PStateNode state;

	change = FALSE;
	c = Collection_Count(trans_tab);
	for(i = 0; i < c ; i++) {
		t = GetTransP(trans_tab, i);
		CR_ASSERT(t != NULL);
		if (t->type == T_NONE) continue;
		s = Set_MinIndex(&t->to_states);
		state = GetStateP(s);
		CR_ASSERT(state != NULL);
		if (state->gen_state_no == -1) change = TRUE;
		state->gen_state_no = 1;
	}
	return change;
}


/* mark all states not reachable from state 0 */
static void DeleteRedundantStates()
{
	PStateNode state;
	int s, change;

	state = GetStateP(0);
	CR_ASSERT(state != NULL);
	state->gen_state_no = 0;
	do {
		change = FALSE;
		for (s = root_state; s <= last_state; s++) {
			state = GetStateP(s);
			CR_ASSERT(state != NULL);
			if (state->gen_state_no == -1) continue;
			if (MarkToStates(&state->trans_list)) change = TRUE;
		}
	} while (change);
}

int MakeDeterministic()
{
	int s, correct, changed;

	last_sim_state = last_state;

	if (last_state == 0) return TRUE;

	FindCtxStates();
	for (s = root_state; s <= last_state; s++) {
		do {
			changed = MakeUnique(s);
		} while (changed);
	}

	correct = TRUE;
	for (s = root_state; s <= last_state; s++) {
		if (!MeltStates(s)) correct = FALSE;
	}

	CombineShifts();
	CleanGraphTab();
	return correct;
}

int StrToGraph(byte *name)
{
	int next = 0, i, len, gp, first = 0;
	len = strlen((char *) name);
	for (i = 1; i <= len - 2; i++) {
		gp = MakeGraph(T_CHAR, name[i]);
		if (next) next = LinkGraph(next, gp);
		else first = next = gp;
	}
	return first;
}

/* generate Ignore Chars */
static void GenIgnore()
{
	int p;
	PClassNode cn;

	p = FindClass("@ignore_chars");
	cn = GetClassP(p);
	GenCode(fscan, "while (%C) Scan_NextCh();", &cn->data);
}

/* generate comment part in GET*/
static void GenCommentPart()
{
	int p;
	PCommentNode n;
	Set set;

	Set_Init(&set);
	p = 0;
	while (p < Collection_Count(&comment_tab)) {
		n = (PCommentNode) Collection_At(&comment_tab, p);
		Set_AddItem(&set, n->start_token[0]);
		p++;
	}
	if (!Set_Empty(&set))
		GenCode(fscan, "if ((%C) && Comment()) goto start;", &set);
	Set_Done(&set);
}

/* generate State0 vector */
static void GenState0()
{
	int i, n;

	for (i = 0; i <= 254; i++) {
		if (i % 30 == 0 && i / 30 > 0) GenCode(fscan, "$$");
		n = GetTransition(0, (byte) i);
		if (n < 0) n = 0;
		GenCode(fscan, "%d,", n);
	}
	n = GetTransition(0, 255);
	if (n < 0) n = 0;
	GenCode(fscan, "%d", n);
}

/* generate literal class search */

static void fixname(char *s, char *d)
{
	char temp[MAX_ID_LEN];
	strcpy(temp, s); s = temp;
	s[strlen(s) - 1] = '\0'; s++;
	*d++ = '"';
	while (*s) {
		if (*s == '\\') *d++ = '\\';
		if (*s == '"') *d++ = '\\';
		*d++ = *s++;
	}
	*d++ = '"';
	*d = '\0';
}

static void GenLiterals()
{
	char token[MAX_ID_LEN], name[MAX_ID_LEN];
	int i, p, start;
	PTermNode n;

	for (i = 33; i < 127; i++) {
		p = 0;
		start = 0;
		while (p < term_tab.el_free) {
			n = GetTermP(p);
			CR_ASSERT(n != NULL);
			if (n->type == T_LITTOKEN && n->name[1] == i) {
				GetTermName(p, token);
				if (start == 0) {
					if (i != '\\') GenCode(fscan, "$1case '%c':$$", i);
					else GenCode(fscan, "$1case %d:$$", i);
				}
				fixname(n->name, name);
				GenCode(fscan, "$2if (EqualStr(%s)) return %s;$$", name, token);
				start = 1;
			}
			p++;
		}
		if (start) GenCode(fscan, "$2break;$$");
	}
}

/* generate comment function */
static void GenCommentBody(PCommentNode n)
{
	CR_ASSERT(n != NULL);
	GenCode(fscan, "$2while (1) {$$"
			"$3if (Scan_Ch== %#) { /* 5 */$$", n->end_token[0]);
	if (n->end_token[1] == 0) {
		GenCode(fscan, "$4Level--; Scan_NextCh(); Scan_ComEols = Scan_CurrLine - StartLine;$$"
				"$4if(Level == 0) return 1;$$");
	} else {
		GenCode(fscan, "$4Scan_NextCh();$$"
				"$4if (Scan_Ch == %#) { /* 6 */$$", n->end_token[1]);
		GenCode(fscan, "$5Level--; Scan_NextCh(); Scan_ComEols = Scan_CurrLine - StartLine;$$"
				"$5if(Level == 0) return 1;$$"
				"$4} /* 6 */ $$");
	}
	if (n->nested) {
		GenCode(fscan, "$3} else  /* 5 */$$");
		GenCode(fscan, "$3if (Scan_Ch == %#) {$$", n->start_token[0]);
		if (n->start_token[1] == 0) {
			GenCode(fscan, "$4Level++; Scan_NextCh();$$");
		} else {
			GenCode(fscan, "$4Scan_NextCh();$$");
			GenCode(fscan, "$4if (Scan_Ch == %#) { Level++; Scan_NextCh(); }$$", n->start_token[1]);
		}
	}
	GenCode(fscan, "$3} else /* 5 */$$");
	GenCode(fscan, "$3if (Scan_Ch == EOF_CHAR) return 0;$$$3else Scan_NextCh();$$");
	GenCode(fscan, "$2} /* while */$$");
}

/* generate comment */
static void GenComment(PCommentNode n)
{
	CR_ASSERT(n != NULL);
	GenCode(fscan, "if (Scan_Ch == %#) { /* 1 */$$", n->start_token[0]);
	if (n->start_token[1] == 0) {
		GenCode(fscan, "$1Scan_NextCh();$$");
		GenCommentBody(n);
	} else {
		GenCode(fscan, "$1Scan_NextCh();$$"
				"$1if (Scan_Ch == %#) { /* 2 */$$"
				"$2Scan_NextCh();$$", n->start_token[1]);
		GenCommentBody(n);
		GenCode(fscan, "$1} else { /* 2 */$$");
		GenCode(fscan, "$2if (Scan_Ch == LF_CHAR) { Scan_CurrLine--; Scan_LineStart = OldLineStart; }$$");
		GenCode(fscan, "$2Scan_BuffPos -= 2; Scan_CurrCol = OldCol - 1; Scan_NextCh();$$");
		GenCode(fscan, "$1} /* 2 */$$");
	}
	GenCode(fscan, "} /* 1*/$$");
}

/* make the scanner */

/* generate State Transition */
static void GenStateTrans(int sn, PTransNode t, int is_context)
{
	int to;
	Set set1;

	CR_ASSERT(t != NULL);
	Set_Init(&set1);
	if (t->type == T_CHAR) Set_AddItem(&set1, t->sym);
	if (t->type == T_CLASS) {
		PClassNode cn = GetClassP(t->sym);
		Set_Copy(&set1, &cn->data);
	}
	to = Set_MinIndex(&t->to_states);
	if (t->tc == T_CONTEXT) { /* Transition With Context */
		if (to != sn)  GenCode(fscan, "$1if (%C) { ctx++; state = %d;} else$$", &set1, to);
		else GenCode(fscan, "$1if (%C) ctx++; else$$", &set1, to);
	} else {
		if (is_context) { /* Normal Transition in Context State => Reset Context*/
			if (to != sn)  GenCode(fscan, "$1if (%C) {ctx = 0; state = %d;} else$$", &set1, to);
			else GenCode(fscan, "$1if (%C) ctx = 0; else$$", &set1, to);
		} else {  /* Normal Transition */
			if (to != sn)  GenCode(fscan, "$1if (%C) state = %d; else$$", &set1, to);
			else GenCode(fscan, "$1if (%C) /*same state*/; else$$", &set1, to);
		}
	}
	Set_Done(&set1);
}

/* generate accepting token for a state */
static void GenStateAccept(int token, int is_context)
{
	PTermNode tn;

	if (is_context)
		GenCode(fscan, "$1{$$"
				"$2Scan_NextLen -= ctx; Scan_BuffPos -= ctx+1; Scan_CurrCol -= ctx+1; Scan_NextCh(); $$");

	tn = GetTermP(token);
	CR_ASSERT(tn != NULL);
	if (tn->type == T_CLASSLITTOKEN)
		GenCode(fscan, "%Ireturn CheckLiteral(%T);$$", 1 + is_context, token);
	else {
		if (token == 0) GenCode(fscan, "%Ireturn NoSym;$$", 1 + is_context);
		else GenCode(fscan, "%Ireturn %T;$$", 1 + is_context, token);
	}

	if (is_context) GenCode(fscan, "$1}$$");
}

/* generate state */
static void GenState(PStateNode state, int sn)
{
	int i, c, is_context, t_count;
	Collection *trans_tab;
	PTransNode t;

	CR_ASSERT(state != NULL);
	if (state->gen_state_no == -1) return; /* unused stated */
	is_context = (state->ctx == T_CONTEXT);

	if (sn == 0) GenCode(fscan, " /* State 0; valid STATE0 Table$$");
	GenCode(fscan, "case %d:$$", sn);
	trans_tab = &state->trans_list;
	c = Collection_Count(trans_tab);
	t_count = 0;
	for (i = 0; i < c; i++) {
		t = GetTransP(trans_tab, i);
		CR_ASSERT(t != NULL);
		if (t->type == T_NONE) continue;
		GenStateTrans(sn, t, is_context);
		t_count++;
	}
	is_context = (state->ctx == T_CONTEXT && t_count == 0);
	i = state->end_of;
	if (i >= FIRST_PRAGMA) i = (i - FIRST_PRAGMA) + no_sym + 1;
	GenStateAccept(i, is_context);
	if (t_count) GenCode(fscan, "$1break;$$");
	if (sn == 0) GenCode(fscan, " --------- End State0 --------- */$$");
}

void MakeScanner()
{
	DeleteRedundantStates();
}

/* generate scanner */
int GenScannerOptions(FILE *Out, char *option)
{
	fscan = Out;
	if (!stricmp(option, "IgnoreCase")) {
		GenCode(fscan, "%d", ignore_case);
	} else
	if (!stricmp(option, "State0")) {
		GenState0();
	} else
	if (!stricmp(option, "Literals")) {
		GenLiterals();
	} else
	if (!stricmp(option, "Comment")) {
		Collection_ForEach(&comment_tab, (Collection_Func) GenComment);
	} else
	if (!stricmp(option, "GetDFA")) {
		Collection_ForEachPos(&state_tab, (Collection_FuncPos) GenState);
	} else
	if (!stricmp(option, "GetIgnore")) {
		GenIgnore();
	} else
	if (!stricmp(option, "GetComment")) {
		GenCommentPart();
	} else return 0;

	return 1;
}

/* generate header file */
static void Func_GenHeaderItem(PTermNode n, int p)
{
	char s[MAX_ID_LEN];
	GetTermName(p, s);
	fprintf(fhead, "#define %s\t%d\t/* %s */\n", s, p, n->name);
}

void GenScannerTokens(FILE *Out)
{
	fhead = Out;
	Collection_ForEachPos(&term_tab, (Collection_FuncPos) Func_GenHeaderItem);
	fprintf(fhead, "#define %s\t\t\t%s\t/* %s */\n", "MAXT", "NoSym", "Max Terminals");
}

/* initialize scanner generator tables */
void InitScannerTab()
{
	Collection_Init(&state_tab, sizeof(StateNode), 50, 10);
	Collection_Init(&melted_tab, sizeof(MeltedNode), 10, 5);
	Collection_Init(&comment_tab, sizeof(CommentNode), 10, 5);
	last_state = -1;
	root_state = NewState();
}

/* destroy scanner generator tables */
static void Func_DoneState(PStateNode sn)
{
	DoneState(sn);
}

static void Func_DoneMelt(PMeltedNode sn)
{
	Set_Done(&sn->set);
}

void DoneScannerTab()
{
	Collection_ForEach(&state_tab, (Collection_Func) Func_DoneState);
	Collection_ForEach(&melted_tab, (Collection_Func) Func_DoneMelt);
	Collection_Done(&state_tab);
	Collection_Done(&melted_tab);
	Collection_Done(&comment_tab);
}

/* dump state information to list file */
static void ShowState(PStateNode state, int sn)
{
	Name name;
	int i, c, tok;
	Collection *trans_tab;
	PTransNode t;
	Set set1;

	if (state->gen_state_no == -1) return;
	fprintf(lstfile, "\n\nState %d: ", sn);
	if (state->ctx) fprintf(lstfile, " Context State");
	fprintf(lstfile, "\n");
	Set_Init(&set1);
	trans_tab = &state->trans_list;
	c = Collection_Count(trans_tab);
	for (i = 0; i < c; i++) {
		t = GetTransP(trans_tab, i);
		CR_ASSERT(t != NULL);
		if (t->type == T_NONE) continue;
		Set_Clean(&set1);
		if (t->type == T_CHAR) Set_AddItem(&set1, t->sym);
		if (t->type == T_CLASS) {
			PClassNode cn = GetClassP(t->sym);
			Set_Copy(&set1, &cn->data);
		}

		fprintf(lstfile, "\t");
		Set_ForEach(&set1, (Set_Func) PrintAscii);
		fprintf(lstfile, " -> ");
		Set_ForEach(&t->to_states, (Set_Func) PrintInt);

		if (t->tc == T_CONTEXT) fprintf(lstfile, "  CONTEXT Trans");
		fprintf(lstfile, "\n");
	}

	tok = state->end_of;
	if (tok >= FIRST_PRAGMA) tok = (tok - FIRST_PRAGMA) + no_sym + 1;
	if (tok) GetTermName(tok, name);
	else strcpy(name, "NoSym");
	fprintf(lstfile, "\tAccept Token:  %s (%d)\n", name, tok);
	Set_Done(&set1);
}

void ShowDFA()
{
	fprintf(lstfile, "\n\n\nDFA:\n");
	Collection_ForEachPos(&state_tab, (Collection_FuncPos) ShowState);
}

⌨️ 快捷键说明

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