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

📄 moon.c

📁 compiler-compiler. This is a compiler-compiler with table-driven scanner, table-driven parser.
💻 C
📖 第 1 页 / 共 3 页
字号:
				case divr:					rk = fetchreg(ir.fmta.rk);					if (rk == 0)						runtimeerror("division by zero");					else {						storereg(ir.fmta.ri,							fetchreg(ir.fmta.rj) / rk);						newreg = ir.fmta.ri;						}					break;				/* mod Ri, Rj, Rk */				case mod:					rk = fetchreg(ir.fmta.rk);					if (rk == 0)						runtimeerror("modulus with zero operand");					else {						storereg(ir.fmta.ri,							fetchreg(ir.fmta.rj) % rk);						newreg = ir.fmta.ri;						}					break;				/* and Ri, Rj, Rk  (32-bit logical AND) */				case and:					storereg(ir.fmta.ri,						fetchreg(ir.fmta.rj) & fetchreg(ir.fmta.rk));					newreg = ir.fmta.ri;					break;				/* or Ri, Rj, Rk   (32-bit logical OR) */				case or:					storereg(ir.fmta.ri,						fetchreg(ir.fmta.rj) | fetchreg(ir.fmta.rk));					newreg = ir.fmta.ri;					break;				/* ceq Ri, Rj, Rk  (Rj = Rk) */				case ceq:					storereg(ir.fmta.ri,						fetchreg(ir.fmta.rj) == fetchreg(ir.fmta.rk));					newreg = ir.fmta.ri;					break;				/* cne Ri, Rj, Rk */				case cne:					storereg(ir.fmta.ri,						fetchreg(ir.fmta.rj) != fetchreg(ir.fmta.rk));					newreg = ir.fmta.ri;					break;				/* clt Ri, Rj, Rk */				case clt:					storereg(ir.fmta.ri,						fetchreg(ir.fmta.rj) < fetchreg(ir.fmta.rk));					newreg = ir.fmta.ri;					break;				/* cle Ri, Rj, Rk */				case cle:					storereg(ir.fmta.ri,						fetchreg(ir.fmta.rj) <= fetchreg(ir.fmta.rk));					newreg = ir.fmta.ri;					break;				/* cgt Ri, Rj, Rk */				case cgt:					storereg(ir.fmta.ri,						fetchreg(ir.fmta.rj) > fetchreg(ir.fmta.rk));					newreg = ir.fmta.ri;					break;				/* cge Ri, Rj, Rk */				case cge:					storereg(ir.fmta.ri,						fetchreg(ir.fmta.rj) >= fetchreg(ir.fmta.rk));					newreg = ir.fmta.ri;					break;				/* not Ri, Rj  (32-bit complement) */				case not:					if (fetchreg(ir.fmta.rj) == 0)						storereg(ir.fmta.ri, 1);					else						storereg(ir.fmta.ri, 0);					newreg = ir.fmta.ri;					break;				/* jlr Ri, Rj  (Jump to register and link) */				case jlr:					storereg(ir.fmta.ri, ic);					ic = fetchreg(ir.fmta.rj);					newreg = ir.fmta.ri;					break;				/* nop */				case nop:					break;				/* hlt */				case hlt:					running = FALSE;					break;				}			break;		/* Format B instructions have a 16-bit immediate operand. */		case 'b':			switch (ir.fmtb.op) {				/* lw Ri, K(Rj)  (Load word) */				case lw:					storereg(ir.fmtb.ri,							getmemword(fetchreg(ir.fmtb.rj) + (long) ir.fmtb.k));					newreg = ir.fmtb.ri;					break;				/* lb Ri, K(Rj)  (Load byte) */				case lb:					w1 = getmembyte(fetchreg(ir.fmtb.rj) + (long) ir.fmtb.k);					w2 = fetchreg(ir.fmtb.ri);					storereg(ir.fmtb.ri, (w1) | (w2 & ~255));					newreg = ir.fmtb.ri;					break;				/* sw K(Rj), Ri  (Store word) */				case sw:					newmem = fetchreg(ir.fmtb.rj) + (long) ir.fmtb.k;					putmemword(newmem, fetchreg(ir.fmtb.ri));					break;				/* sb K(Rj), Ri  (Store byte) */				case sb:					newmem = fetchreg(ir.fmtb.rj) + (long) ir.fmtb.k;					putmembyte(newmem, (BYTE) (fetchreg(ir.fmtb.ri) & 255));					break;				/* addi Ri, Rj, K  (Add immediate) */				case addi:					storereg(ir.fmtb.ri,						fetchreg(ir.fmtb.rj) + (long) ir.fmtb.k);					newreg = ir.fmtb.ri;					break;				/* subi Ri, Rj, K */				case subi:					storereg(ir.fmtb.ri,						fetchreg(ir.fmtb.rj) - (long) ir.fmtb.k);					newreg = ir.fmtb.ri;					break;				/* muli Ri, Rj, K */				case muli:					storereg(ir.fmtb.ri,						fetchreg(ir.fmtb.rj) * (long) ir.fmtb.k);					newreg = ir.fmtb.ri;					break;				/* divi Ri, Rj, K */				case divi:					k = (long) ir.fmtb.k;					if (k == 0)						runtimeerror("division by zero");					else {						storereg(ir.fmtb.ri,							fetchreg(ir.fmtb.rj) / k);						newreg = ir.fmtb.ri;						}					break;				/* modi Ri, Rj, K */				case modi:					k = (long) ir.fmtb.k;					if (k == 0)						runtimeerror("division by zero");					else {						storereg(ir.fmtb.ri,							fetchreg(ir.fmtb.rj) % k);						newreg = ir.fmtb.ri;						}					break;				/* andi Ri, Rj, K */				case andi:					storereg(ir.fmtb.ri,						fetchreg(ir.fmtb.rj) & (long) ir.fmtb.k);					newreg = ir.fmtb.ri;					break;				/* ori Ri, Rj, K */				case ori:					storereg(ir.fmtb.ri,						fetchreg(ir.fmtb.rj) | (long) ir.fmtb.k);					newreg = ir.fmtb.ri;					break;				/* ceqi Ri, Rj, K */				case ceqi:					storereg(ir.fmtb.ri,						fetchreg(ir.fmtb.rj) == (long) ir.fmtb.k);					newreg = ir.fmtb.ri;					break;				/* cnei Ri, Rj, K */				case cnei:					storereg(ir.fmtb.ri,						fetchreg(ir.fmtb.rj) != (long) ir.fmtb.k);					newreg = ir.fmtb.ri;					break;				/* clti Ri, Rj, K */				case clti:					storereg(ir.fmtb.ri,						fetchreg(ir.fmtb.rj) < (long) ir.fmtb.k);					newreg = ir.fmtb.ri;					break;				/* clei Ri, Rj, K */				case clei:					storereg(ir.fmtb.ri,						fetchreg(ir.fmtb.rj) <= (long) ir.fmtb.k);					newreg = ir.fmtb.ri;					break;				/* cgti Ri, Rj, K */				case cgti:					storereg(ir.fmtb.ri,						fetchreg(ir.fmtb.rj) > (long) ir.fmtb.k);					newreg = ir.fmtb.ri;					break;				/* cgei Ri, Rj, K */				case cgei:					storereg(ir.fmtb.ri,						fetchreg(ir.fmtb.rj) >= (long) ir.fmtb.k);					newreg = ir.fmtb.ri;					break;				/* sl Ri, K  (Shift left logical) */				case sl:					storereg(ir.fmtb.ri,						fetchreg(ir.fmtb.ri) << (long) ir.fmtb.k);					newreg = ir.fmtb.ri;					break;				/* sr Ri, K  (Shift right logical) */				case sr:					storereg(ir.fmtb.ri,						fetchreg(ir.fmtb.ri) >> (long) ir.fmtb.k);					newreg = ir.fmtb.ri;					break;				/* bz Ri, K  (Branch to K if Ri == 0) */				case bz:					if (fetchreg(ir.fmtb.ri) == 0)						ic = (long) ir.fmtb.k;					break;				/* bnz Ri, K  (Branch to K if Ri != 0) */				case bnz:					if (fetchreg(ir.fmtb.ri) != 0)						ic = (long) ir.fmtb.k;					break;				/* jl Ri, K  (Branch to K with link in Ri) */				case jl:					storereg(ir.fmtb.ri, ic);					ic = (long) ir.fmtb.k;					newreg = ir.fmtb.ri;					break;				/* getc Ri  (Read one character to Ri) */				case gtc:					if (tracing) {						char buf [256];						printf("\nEnter data for getc: ");						fgets(buf, 256, stdin);						if (buf[0] == '\0')							ch = '\n';						else							ch = buf[0];						}					else						ch = (BYTE) getchar();					storereg(ir.fmtb.ri, ch);					newreg = ir.fmtb.ri;					break;				/* putc Ri  (Write the character in Ri) */				case ptc:					if (tracing)						printf("  Output from putc: %c",							fetchreg(ir.fmtb.ri));					else						printf("%c", fetchreg(ir.fmtb.ri));					break;				/* jr Ri  (Jump to Ri) */				case jr:					ic = fetchreg(ir.fmtb.ri);					break;				/* j K  (Jump to K) */				case j:					ic = (long) ir.fmtb.k;					break;				}			break;		}	}/* Dump words of memory from addr-10 to addr+10. */void dump (long addr) {	long first = (addr - RANGE) & ~3;	long last = (addr + RANGE) & ~3;	if (first < 0)		first = 0;	if (last > MEMSIZE)		last = MEMSIZE;	for (addr = first; addr < last; addr += 4) {		showword(addr);		printf("\n");		}	}/* Display a register. */void showreg (short regnum) {	wordtype word;	char charbuf [5];	word.data = regs[regnum];	printf("   r%d =  %08lX  %s  %4ld", regnum, word.data,		wordtochars(charbuf, word), word.data);	}/* Execute one instruction in trace mode. */void traceinstr () {	char charbuf [5];	showword(ic);	execinstr(TRUE);	if (running) {		if (newreg >= 0)			showreg(newreg);		else if (newmem >= 0) {			long addr = newmem >> 2;			printf("   M[%ld] =  %08lX  %s  %ld", newmem,				mem[addr].word.data,				wordtochars(charbuf, mem[addr].word),				mem[addr].word.data);			}		printf("\n");		if (mem[ic >> 2].breakpoint) {			printf("%5ld Breakpoint\n", ic);			running = FALSE;			}		}	}/* Execute <steps> instructions in trace mode. */void runfor (long steps) {	long cnt;	running = TRUE;	for (cnt = 0; cnt < steps; cnt++) {		traceinstr();		if (!running)			break;		}	}/* 	Fetch the operand of a trace instruction. The operand should be * either a number or a symbol. */long getoperand (char *cp) {	char *first;	long val;	while (*cp == ' ' || *cp == '\t')		cp++;	first = cp;	if (isdigit(*cp)) {		if (sscanf(first, "%ld", &val) == 1)			return val;		else {			printf("?\n");			return -1;			}		}	else if (isalpha(*cp)) {		val = getsymbolval(cp);		if (val < 0)			printf("?\n");		return val;		}	else {		printf("?\n");		return - 1;		}	}/* Show tracing instructions. */void showtraceusage() {	printf("The tracer prompts with `IC:-\'.  IC is the instruction counter.\n");	printf("Upper or lower case letters are accepted.  n must be positive.\n");	printf("\n");	printf("<cr>     Trace K instructions.\n");	printf("n        Trace n instructions.\n");	printf("B        Display breakpoints.\n");	printf("Bn       Set a breakpoint at n.\n");	printf("C        Clear all breakpoints.\n");	printf("Cn       Clear the breakpoint at n.\n");	printf("D        Dump memory near IC.\n");	printf("Dn       Dump memory near n.\n");	printf("I        Set IC to entry point.\n");	printf("In       Set IC to n.\n");	printf("K        Set K (# steps executed by <cr>) to 10.\n");	printf("Kn       Set K to n.\n");	printf("Q        Quit.\n");	printf("R        Show registers.\n");	printf("S        Show symbols.\n");	printf("X        Run to next break point.\n");	printf("Xn       Run until IC = n.\n");	printf("\n");	}/* Execute the program with tracing. */void exectrace () {	char cmd [BUFLEN];	long addr;	short regnum;	ic = entrypoint;	numsteps = 10;	running = TRUE;	while (1) {		printf("%5ld:- ", ic);		fgets(cmd, BUFLEN, stdin);		if (!strcmp(cmd, "q") || !strcmp(cmd, "Q"))			break;		else if (!strcmp(cmd, ""))			runfor(numsteps);		else if (isdigit(*cmd)) {			long steps = getoperand(cmd);			if (steps > 0)				runfor(steps);			}		else {			char *cp = cmd;			switch (*cp++) {				/* B = show all breakpoints; Bn = set breakpoint. */				case 'b': case 'B':					if (*cp == '\0') {						printf("Breakpoints are at: ");						for (addr = 0; addr < MEMSIZE; addr++) {							if (mem[addr].breakpoint)								printf("%ld ", addr << 2);							}						printf("\n");						}					else {						addr = getoperand(cp);						if (addr >= 0)							mem[addr >> 2].breakpoint = TRUE;						}					break;				/* C = clear all breakpoints; Cn = clear a breakpoint. */				case 'c': case 'C':					if (*cp == '\0') {						for (addr = 0; addr < MEMSIZE; addr++)							mem[addr].breakpoint = FALSE;						}					else {						addr = getoperand(cp);						if (addr >= 0)							mem[addr >> 2].breakpoint = FALSE;						}					break;				/* D = dump memory near <ic>; Dn = dump memory near n. */				case 'd': case 'D':					if (*cp == '\0')						dump(ic);					else {						addr = getoperand(cp);						if (addr >= 0)							dump(addr);						}					break;				/* Explain how to use it. */				case 'h': case 'H': case '?':					showtraceusage();					break;				/* I = set <ic> to entry point; In = set <ic> to n. */				case 'i': case 'I':					if (*cp == '\0')						ic = entrypoint;					else {						addr = getoperand(cp);						if (addr >= 0)							ic = addr;						}					break;				/* K = set steps to 10; Kn = set steps to n. */				case 'k': case 'K':					if (*cp == '\0')						numsteps = 10;					else {						numsteps = getoperand(cp);						if (numsteps < 0)							numsteps = 10;						}					break;				/* R = show registers. */				case 'r': case 'R':					for (regnum = 0; regnum < MAXREG; regnum++) {						showreg(regnum);						printf("\n");						}					break;				/* S = show symbols. */				case 's': case 'S':					showsymbols();					break;				/* X = run to next breakpoint; Xn = run to n. */				case 'x': case 'X':					if (*cp == '\0') {						running = TRUE;						while (running) {							execinstr(FALSE);							if (mem[ic >> 2].breakpoint) {								printf("%5ld Breakpoint\n", ic);								break;								}							}						}					else {						addr = getoperand(cp);						if (addr < 0)							printf("?\n");						else {							running = TRUE;							while (running) {								execinstr(FALSE);								if (ic == addr)									break;								}							}						}					break;				default:					printf("?\n");					break;				}			}		}	printf("\n%ld cycles.\n", cycles);	}/* Execute the program without tracing. */void exec () {	ic = entrypoint;	running = TRUE;	while (running) {		execinstr(FALSE);		}	printf("\n%ld cycles.\n", cycles);	}/******************************* PARSING ***********************************/enum tokentype {	T_BAD, T_REG, T_OP, T_SYM, T_NUM, T_STR, T_COMMA, T_LP, T_RP, T_NULL	};struct {	char symval [TOKLEN];	/* Characters of the token */	enum tokentype kind;	/* Chosen from the enumeration */	char *pos;				/* Pointer to start of token */	short reg;				/* Register number for T_REG */	short op;				/* Op code for T_OP */	long intval;			/* Value for T_NUM */	} token;char oldval [TOKLEN];char errmes [BUFLEN];	/* Error message */int errorcount = 0;		/* Number of errors detected. */char *bp;				/* Buffer pointer *//* Record an error for reporting later; only the first error is recorded. */void syntaxerror (char *message) {	errorcount++;	if (!strcmp(errmes, "")) {		strcpy(errmes, "Error at `");		strcat(errmes, oldval);		strcat(errmes, " ");		strcat(errmes, token.symval);		strcat(errmes, "': ");		strcat(errmes, message);		}	}/* True if character can occur in a symbol */short issymchar (char c) {	return (isalnum(c) || c == '_');	}/* True if the string is a valid register name. */short isreg (char *p) {	long regnum = 0;	if (!(*p == 'R' || *p == 'r'))		return FALSE;	p++;	while (*p) {		if (isdigit(*p))			regnum = 10 * regnum + *p - '0';		else			return FALSE;		p++;		}	if (regnum < MAXREG) {		token.reg = (short) regnum;		return TRUE;		}	else {		syntaxerror("Illegal symbol");		return FALSE;		}	}/* Read a token and store appropriate values in the structure <token>. * For error reporting, the token repesenting the string must be left * in <token.symval>. */

⌨️ 快捷键说明

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