ref: e8603799ceaa3ef49d8a193b315f2cac94bb358f
dir: /n.y/
%{ #include <u.h> #include <libc.h> #include <bio.h> #include <ctype.h> int goteof; int lineno; int yyparse(void); void yyerror(char*); struct { char *s; /* todo */ } typetab[1000] = { "byte", "int", "long", "vlong", "uint", "ulong", "uvlong", "float32", "float64", nil, }; void addtype(char *s) { int i; for(i = 0; i < nelem(typetab)-1; i++){ if(typetab[i].s != nil) continue; typetab[i].s = s; typetab[i+1].s = nil; } } %} %union { char *sval; long ival; } %token FUNC DEF IF FOR MOD USE OR AND NOTEQ EQ SHIFTL SHIFTR STRUCT ELSE %token TYPE NAME NUM %token <sval> NAME TYPE; %token <ival> NUM %% prog : prog top | top top : FUNC NAME '(' args ')' return '{' stmts '}' | MOD NAME ';' | USE NAME ';' | def ';' sdecls : | sdecls NAME ':' type ';' def : DEF NAME TYPE { addtype($2); } | DEF NAME STRUCT '{' sdecls '}' { addtype($2); } type : TYPE | type '[' ']' | type '[' NUM ']' | type '!' return : '-' '>' type | unary : NUM | NAME | '<' '-' NAME | '(' expr ')' sufexpr : unary '--' | unary '++' | unary mulexpr : mulexpr '*' sufexpr | mulexpr '/' sufexpr | mulexpr '%' sufexpr | sufexpr addexpr : addexpr '+' mulexpr | addexpr '-' mulexpr | mulexpr shifexpr : shifexpr SHIFTL addexpr | shifexpr SHIFTR addexpr | addexpr compexpr : compexpr '>' shifexpr | compexpr '<' shifexpr | compexpr NOTEQ shifexpr | compexpr EQ shifexpr | shifexpr logexpr : logexpr OR compexpr | logexpr AND compexpr | compexpr expr : | expr '=' logexpr | logexpr stmts : | stmts stmt decl : NAME ':' type | NAME ':' '=' expr stmt : expr ';' | '{' stmts '}' | decl ';' | FOR '(' expr ')' stmt | FOR '(' expr ';' expr ';' expr ')' stmt | IF '(' expr ')' stmt ELSE stmt | IF '(' expr ')' stmt arg : NAME type args : | arg | args ',' arg %% struct { char *s; int type; } keytab[] = { "fn", FUNC, "type", DEF, "if", IF, "for", FOR, "mod", MOD, "use", USE, "&&", AND, "||", OR, "!=", NOTEQ, "==", EQ, "<<", SHIFTR, ">>", SHIFTL, "struct", STRUCT, "else", ELSE, }; Biobuf *bin; int getch(void) { int c; c = Bgetc(bin); if(c == Beof){ goteof = 1; return -1; } if(c == '\n') lineno++; return c; } void ungetc(void) { Bungetc(bin); } void wordlex(char *dst, int n) { int c; while(--n > 0){ c = getch(); if((c >= Runeself) || isalnum(c)){ *dst++ = c; continue; } ungetc(); break; } if(n <= 0) yyerror("symbol buffer overrun"); *dst = '\0'; } void yyerror(char *s) { fprint(2, "%d: %s\n", lineno, s); exits(s); } int yylex2(void) { static char buf[200]; int c; int i; Loop: c = getch(); switch(c){ case -1: return -1; case ' ': case '\t': case '\n': goto Loop; case '/': if(getch() != '*'){ ungetc(); goto Loop; } More: while((c = getch()) > 0) if(c == '*') break; if(c != '*') goto Loop; if(getch() == '/') goto Loop; goto More; } switch(c){ case ';': case '=': case '{': case '}': case '[': case ']': case '(': case ')': case '+': case '-': case '*': case '/': case '%': case ':': case '>': case '<': case ',': case '.': return c; } ungetc(); wordlex(buf, sizeof buf); for(i = 0; i < nelem(keytab); i++) if(strcmp(keytab[i].s, buf) == 0) return keytab[i].type; for(i = 0; i < nelem(typetab); i++){ if(typetab[i].s == nil) break; if(strcmp(typetab[i].s, buf) == 0){ yylval.sval = strdup(buf); return TYPE; } } if(isdigit(buf[0])){ yylval.ival = atoi(buf); return NUM; } yylval.sval = strdup(buf); return NAME; } int debug; int yylex(void) { int c; c = yylex2(); if(!debug) return c; if(c < Runeself) fprint(2, "%c\n", c); else if(c == NAME) fprint(2, "NAME %s\n", yylval.sval); else if(c == TYPE) fprint(2, "TYPE %s\n", yylval.sval); else if(c == NUM) fprint(2, "NUM %ld\n", yylval.ival); return c; } void usage(void) { fprint(2, "usage: [-d] %s\n", argv0); exits("usage"); } void main(int argc, char **argv) { ARGBEGIN{ case 'd': debug++; break; default: usage(); break; }ARGEND; if(argc > 0) usage(); bin = Bfdopen(0, OREAD); goteof = 0; while(!goteof) yyparse(); Bterm(bin); exits(nil); }