ref: dd9a8551019ff0bfb4c5af583dc60419d28c4bb1
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*); %} %union { char *sval; long ival; } %token FUNC DEF IF FOR STRUCT MOD USE TYPE NAME NUM OR AND NOTEQ SHIFTL SHIFTR %token <sval> NAME TYPE; %token <ival> NUM %% prog : prog top | top sem : ';' top : FUNC NAME '(' args ')' '-' '>' return '{' stmts '}' | MOD NAME sem | USE NAME sem return : TYPE | unary : NUM | NAME mulexpr : mulexpr '*' unary | mulexpr '/' unary | mulexpr '%' unary | unary addexpr : addexpr '+' mulexpr | addexpr '-' mulexpr | mulexpr compexpr : compexpr '>' addexpr | compexpr '<' addexpr | compexpr NOTEQ addexpr | addexpr logexpr : logexpr OR compexpr | logexpr AND compexpr | compexpr expr : | expr '=' logexpr | logexpr stmts : | stmts stmt decl : NAME ':' expr stmt : expr sem | '{' stmts '}' | decl sem args : NAME %% 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 '<': return c; } ungetc(); wordlex(buf, sizeof buf); if(strcmp(buf, "fn") == 0) return FUNC; if(strcmp(buf, "||") == 0) return OR; if(strcmp(buf, "&&") == 0) return AND; if(isdigit(buf[0])){ yylval.ival = atoi(buf); return NUM; } yylval.sval = strdup(buf); return NAME; } int yylex(void) { int c; c = yylex2(); return c; } void usage(void) { fprint(2, "usage: %s\n", argv0); exits("usage"); } void main(int argc, char **argv) { ARGBEGIN{ default: usage(); break; }ARGEND; if(argc > 0) usage(); bin = Bfdopen(0, OREAD); goteof = 0; while(!goteof) yyparse(); Bterm(bin); exits(nil); }