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

📄 cra.c

📁 COCO類似C的編譯器
💻 C
📖 第 1 页 / 共 3 页
字号:
		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(void)
{
	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(void)
{
	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();

	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(void)
{
	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(void)
{
	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(void)
{
	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(void)
{
	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);

	GenCode(fscan, "$1if (%C)",&set1);

	if (t->tc == T_CONTEXT) { /* Transition With Context */
		if (to != sn)  GenCode(fscan, " { ctx++; state = %d;} else$$", to);
		else GenCode(fscan, " ctx++; else$$");
	} else {
		if (is_context) { /* Normal Transition in Context State => Reset Context*/
			if (to != sn)  GenCode(fscan, " {ctx = 0; state = %d;} else$$", to);
			else GenCode(fscan, " ctx = 0; else$$");
		} else {  /* Normal Transition */
			if (to != sn)  GenCode(fscan, " state = %d; else$$", to);
			else GenCode(fscan, " /*same state*/; else$$");
		}
	}
	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 No_Sym;$$", 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(void)
{
	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%s\t/* %s */\n", "MAXT", "No_Sym", "Max Terminals");
}

/* initialize scanner generator tables */
void InitScannerTab(void)
{
	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(void)
{
	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, "No_Sym");
	fprintf(lstfile, "\tAccept Token:  %s (%d)\n", name, tok);
	Set_Done(&set1);
}

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

⌨️ 快捷键说明

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