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

📄 hoc.y

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 Y
字号:
%{#include "hoc.h"#define	code2(c1,c2)	code(c1); code(c2)#define	code3(c1,c2,c3)	code(c1); code(c2); code(c3)%}%union {	Symbol	*sym;	/* symbol table pointer */	Inst	*inst;	/* machine instruction */	int	narg;	/* number of arguments */	Formal	*formals;	/* list of formal parameters */}%token	<sym>	NUMBER STRING PRINT VAR BLTIN UNDEF WHILE FOR IF ELSE%token	<sym>	FUNCTION PROCEDURE RETURN FUNC PROC READ%type	<formals>	formals%type	<inst>	expr stmt asgn prlist stmtlist%type	<inst>	cond while for if begin end %type	<sym>	procname%type	<narg>	arglist%right	'=' ADDEQ SUBEQ MULEQ DIVEQ MODEQ%left	OR%left	AND%left	GT GE LT LE EQ NE%left	'+' '-'%left	'*' '/' '%'%left	UNARYMINUS NOT INC DEC%right	'^'%%list:	  /* nothing */	| list '\n'	| list defn '\n'	| list asgn '\n'  { code2(xpop, STOP); return 1; }	| list stmt '\n'  { code(STOP); return 1; } 	| list expr '\n'  { code2(printtop, STOP); return 1; }	| list error '\n' { yyerrok; }	;asgn:	  VAR '=' expr { code3(varpush,(Inst)$1,assign); $$=$3; }	| VAR ADDEQ expr	{ code3(varpush,(Inst)$1,addeq); $$=$3; }	| VAR SUBEQ expr	{ code3(varpush,(Inst)$1,subeq); $$=$3; }	| VAR MULEQ expr	{ code3(varpush,(Inst)$1,muleq); $$=$3; }	| VAR DIVEQ expr	{ code3(varpush,(Inst)$1,diveq); $$=$3; }	| VAR MODEQ expr	{ code3(varpush,(Inst)$1,modeq); $$=$3; }	;stmt:	  expr	{ code(xpop); }	| RETURN { defnonly("return"); code(procret); }	| RETURN expr	        { defnonly("return"); $$=$2; code(funcret); }	| PROCEDURE begin '(' arglist ')'		{ $$ = $2; code3(call, (Inst)$1, (Inst)$4); }	| PRINT prlist	{ $$ = $2; }	| while '(' cond ')' stmt end {		($1)[1] = (Inst)$5;	/* body of loop */		($1)[2] = (Inst)$6; }	/* end, if cond fails */	| for '(' cond ';' cond ';' cond ')' stmt end {		($1)[1] = (Inst)$5;	/* condition */		($1)[2] = (Inst)$7;	/* post loop */		($1)[3] = (Inst)$9;	/* body of loop */		($1)[4] = (Inst)$10; }	/* end, if cond fails */	| if '(' cond ')' stmt end {	/* else-less if */		($1)[1] = (Inst)$5;	/* thenpart */		($1)[3] = (Inst)$6; }	/* end, if cond fails */	| if '(' cond ')' stmt end ELSE stmt end {	/* if with else */		($1)[1] = (Inst)$5;	/* thenpart */		($1)[2] = (Inst)$8;	/* elsepart */		($1)[3] = (Inst)$9; }	/* end, if cond fails */	| '{' stmtlist '}'	{ $$ = $2; }	;cond:	   expr 	{ code(STOP); }	;while:	  WHILE	{ $$ = code3(whilecode,STOP,STOP); }	;for:	  FOR	{ $$ = code(forcode); code3(STOP,STOP,STOP); code(STOP); }	;if:	  IF	{ $$ = code(ifcode); code3(STOP,STOP,STOP); }	;begin:	  /* nothing */		{ $$ = progp; }	;end:	  /* nothing */		{ code(STOP); $$ = progp; }	;stmtlist: /* nothing */		{ $$ = progp; }	| stmtlist '\n'	| stmtlist stmt	;expr:	  NUMBER { $$ = code2(constpush, (Inst)$1); }	| VAR	 { $$ = code3(varpush, (Inst)$1, eval); }	| asgn	| FUNCTION begin '(' arglist ')'		{ $$ = $2; code3(call,(Inst)$1,(Inst)$4); }	| READ '(' VAR ')' { $$ = code2(varread, (Inst)$3); }	| BLTIN '(' expr ')' { $$=$3; code2(bltin, (Inst)$1->u.ptr); }	| '(' expr ')'	{ $$ = $2; }	| expr '+' expr	{ code(add); }	| expr '-' expr	{ code(sub); }	| expr '*' expr	{ code(mul); }	| expr '/' expr	{ code(div); }	| expr '%' expr	{ code(mod); }	| expr '^' expr	{ code (power); }	| '-' expr   %prec UNARYMINUS   { $$=$2; code(negate); }	| expr GT expr	{ code(gt); }	| expr GE expr	{ code(ge); }	| expr LT expr	{ code(lt); }	| expr LE expr	{ code(le); }	| expr EQ expr	{ code(eq); }	| expr NE expr	{ code(ne); }	| expr AND expr	{ code(and); }	| expr OR expr	{ code(or); }	| NOT expr	{ $$ = $2; code(not); }	| INC VAR	{ $$ = code2(preinc,(Inst)$2); }	| DEC VAR	{ $$ = code2(predec,(Inst)$2); }	| VAR INC	{ $$ = code2(postinc,(Inst)$1); }	| VAR DEC	{ $$ = code2(postdec,(Inst)$1); }	;prlist:	  expr			{ code(prexpr); }	| STRING		{ $$ = code2(prstr, (Inst)$1); }	| prlist ',' expr	{ code(prexpr); }	| prlist ',' STRING	{ code2(prstr, (Inst)$3); }	;defn:	  FUNC procname { $2->type=FUNCTION; indef=1; }	    '(' formals ')' stmt { code(procret); define($2, $5); indef=0; }	| PROC procname { $2->type=PROCEDURE; indef=1; }	    '(' formals ')' stmt { code(procret); define($2, $5); indef=0; }	;formals:	{ $$ = 0; }	| VAR			{ $$ = formallist($1, 0); }	| VAR ',' formals	{ $$ = formallist($1, $3); }	;procname: VAR	| FUNCTION	| PROCEDURE	;arglist:  /* nothing */ 	{ $$ = 0; }	| expr			{ $$ = 1; }	| arglist ',' expr	{ $$ = $1 + 1; }	;%%	/* end of grammar */#include <u.h>#include <libc.h>#include <bio.h>#include <ctype.h>char	*progname;int	lineno = 1;jmp_buf	begin;int	indef;char	*infile;	/* input file name */Biobuf	*bin;		/* input file descriptor */Biobuf	binbuf;char	**gargv;	/* global argument list */int	gargc;int c = '\n';	/* global for use by warning() */int	backslash(int), follow(int, int, int);void	defnonly(char*), run(void);void	warning(char*, char*);yylex(void)		/* hoc6 */{	while ((c=Bgetc(bin)) == ' ' || c == '\t')		;	if (c < 0)		return 0;	if (c == '\\') {		c = Bgetc(bin);		if (c == '\n') {			lineno++;			return yylex();		}	}	if (c == '#') {		/* comment */		while ((c=Bgetc(bin)) != '\n' && c >= 0)			;		if (c == '\n')			lineno++;		return c;	}	if (c == '.' || isdigit(c)) {	/* number */		double d;		Bungetc(bin);		Bgetd(bin, &d);		yylval.sym = install("", NUMBER, d);		return NUMBER;	}	if (isalpha(c) || c == '_' || c >= 0x80) {		Symbol *s;		char sbuf[100], *p = sbuf;		do {			if (p >= sbuf + sizeof(sbuf) - 1) {				*p = '\0';				execerror("name too long", sbuf);			}			*p++ = c;		} while ((c=Bgetc(bin)) >= 0 && (isalnum(c) || c == '_' || c >= 0x80));		Bungetc(bin);		*p = '\0';		if ((s=lookup(sbuf)) == 0)			s = install(sbuf, UNDEF, 0.0);		yylval.sym = s;		return s->type == UNDEF ? VAR : s->type;	}	if (c == '"') {	/* quoted string */		char sbuf[100], *p;		for (p = sbuf; (c=Bgetc(bin)) != '"'; p++) {			if (c == '\n' || c == Beof)				execerror("missing quote", "");			if (p >= sbuf + sizeof(sbuf) - 1) {				*p = '\0';				execerror("string too long", sbuf);			}			*p = backslash(c);		}		*p = 0;		yylval.sym = (Symbol *)emalloc(strlen(sbuf)+1);		strcpy((char*)yylval.sym, sbuf);		return STRING;	}	switch (c) {	case '+':	return follow('+', INC, follow('=', ADDEQ, '+'));	case '-':	return follow('-', DEC, follow('=', SUBEQ, '-'));	case '*':	return follow('=', MULEQ, '*');	case '/':	return follow('=', DIVEQ, '/');	case '%':	return follow('=', MODEQ, '%');	case '>':	return follow('=', GE, GT);	case '<':	return follow('=', LE, LT);	case '=':	return follow('=', EQ, '=');	case '!':	return follow('=', NE, NOT);	case '|':	return follow('|', OR, '|');	case '&':	return follow('&', AND, '&');	case '\n':	lineno++; return '\n';	default:	return c;	}}backslash(int c)	/* get next char with \'s interpreted */{	static char transtab[] = "b\bf\fn\nr\rt\t";	if (c != '\\')		return c;	c = Bgetc(bin);	if (islower(c) && strchr(transtab, c))		return strchr(transtab, c)[1];	return c;}follow(int expect, int ifyes, int ifno)	/* look ahead for >=, etc. */{	int c = Bgetc(bin);	if (c == expect)		return ifyes;	Bungetc(bin);	return ifno;}voidyyerror(char* s)	/* report compile-time error */{/*rob	warning(s, (char *)0);	longjmp(begin, 0);rob*/	execerror(s, (char *)0);}voidexecerror(char* s, char* t)	/* recover from run-time error */{	warning(s, t);	Bseek(bin, 0L, 2);		/* flush rest of file */	restoreall();	longjmp(begin, 0);}voidfpecatch(void)	/* catch floating point exceptions */{	execerror("floating point exception", (char *) 0);}voidintcatch(void)	/* catch interrupts */{	execerror("interrupt", 0);}voidrun(void)	/* execute until EOF */{	setjmp(begin);	for (initcode(); yyparse(); initcode())		execute(progbase);}voidmain(int argc, char* argv[])	/* hoc6 */{	static int first = 1;#ifdef YYDEBUG	extern int yydebug;	yydebug=3;#endif	progname = argv[0];	init();	if (argc == 1) {	/* fake an argument list */		static char *stdinonly[] = { "-" };		gargv = stdinonly;		gargc = 1;	} else if (first) {	/* for interrupts */		first = 0;		gargv = argv+1;		gargc = argc-1;	}	Binit(&binbuf, 0, OREAD);	bin = &binbuf;	while (moreinput())		run();	exits(0);}moreinput(void){	char *expr;	static char buf[64];	int fd;	static Biobuf b;	if (gargc-- <= 0)		return 0;	if (bin && bin != &binbuf)		Bterm(bin);	infile = *gargv++;	lineno = 1;	if (strcmp(infile, "-") == 0) {		bin = &binbuf;		infile = 0;		return 1;	}	if(strncmp(infile, "-e", 2) == 0) {		if(infile[2]==0){			if(gargc == 0){				fprint(2, "%s: no argument for -e\n", progname);				return 0;			}			gargc--;			expr = *gargv++;		}else			expr = infile+2;		sprint(buf, "/tmp/hocXXXXXXX");		infile = mktemp(buf);		fd = create(infile, ORDWR|ORCLOSE, 0600);		if(fd < 0){			fprint(2, "%s: can't create temp. file: %r\n", progname);			return 0;		}		fprint(fd, "%s\n", expr);		/* leave fd around; file will be removed on exit */		/* the following looks weird but is required for unix version */		bin = &b;		seek(fd, 0, 0);		Binit(bin, fd, OREAD);	} else {		bin=Bopen(infile, OREAD);		if (bin == 0) {			fprint(2, "%s: can't open %s\n", progname, infile);			return moreinput();		}	}	return 1;}voidwarning(char* s, char* t)	/* print warning message */{	fprint(2, "%s: %s", progname, s);	if (t)		fprint(2, " %s", t);	if (infile)		fprint(2, " in %s", infile);	fprint(2, " near line %d\n", lineno);	while (c != '\n' && c != Beof)		if((c = Bgetc(bin)) == '\n')	/* flush rest of input line */			lineno++;}voiddefnonly(char *s)	/* warn if illegal definition */{	if (!indef)		execerror(s, "used outside definition");}

⌨️ 快捷键说明

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