comp.y (4387B)
1 %{ 2 #include <stdio.h> 3 #include <stdlib.h> 4 5 #include "lex.h" 6 #include "comp.h" 7 8 extern int yylex(); 9 10 void yyerror(const char *msg); 11 12 List *prog; 13 14 int nerror = 0; 15 16 #define NEW(x, v) x = malloc(sizeof(*x)); memcpy(x, &v, sizeof(v)) 17 #define STR(v, t) v = calloc(1, t->dataend - t->data + 1); memcpy(v, t->data, t->dataend - t->data) 18 %} 19 20 %union { 21 Func *func; 22 Type *type; 23 Rhs *rhs; 24 Expr *expr; 25 Value *value; 26 Name *name; 27 Arg *arg; 28 29 struct Token *tok; 30 31 struct List *list; 32 } 33 34 %token FUNC 35 %token VAR 36 %token NAME 37 %token INT 38 %token FLOAT 39 40 %type <list> prog 41 %type <func> func 42 %type <type> type 43 %type <rhs> rhs 44 %type <expr> expr 45 %type <list> exprs 46 %type <list> params 47 %type <list> args 48 %type <arg> arg 49 %type <value> value 50 %type <name> name 51 %type <tok> INT 52 %type <tok> FLOAT 53 %type <tok> NAME 54 55 %left '(' ')' 56 %left '*' '/' 57 %left '+' '-' 58 59 %% 60 prog : func { 61 NEW($$, ((List){.size = sizeof(Func), .count = 0, .data = NULL})); 62 APPEND($$, $1); 63 prog = $$; 64 } 65 | prog func { 66 APPEND($1, $2); 67 $$ = $1; 68 prog = $$; 69 } 70 | prog error { yyerrok; yyclearin; } 71 ; 72 73 func : FUNC name '(' args ')' type 74 '{' exprs '}' { NEW($$, ((Func){.type = $6, .args = (Arg *)$4->data, .argc = $4->count, .name = $2, .body = (Expr *)$8->data, .exprc = $8->count})); } 75 | FUNC name '(' ')' type 76 '{' exprs '}' { NEW($$, ((Func){.type = $5, .name = $2, .body = (Expr *)$7->data, .exprc = $7->count})); } 77 ; 78 79 name : NAME { 80 NEW($$, ((Name){.name = NULL})); 81 STR($$->name, $1); 82 } 83 ; 84 85 args : arg { 86 NEW($$, ((List){.size = sizeof(Arg), .count = 0, .data = NULL})); 87 APPEND($$, $1); 88 } 89 | args ',' arg { 90 APPEND($1, $3); 91 $$ = $1; 92 } 93 | args ',' error { yyerrok; yyclearin; } 94 ; 95 96 arg : name type { NEW($$, ((Arg){.name = $1, .type = $2})); } 97 ; 98 99 type : name { 100 if (!strlen($1->name)) 101 goto invalid_type; 102 103 enum Types ty = 0; 104 switch (((char *)$1->name)[0]) { 105 case 'i': break; 106 case 'u': ty |= 16; break; 107 case 'f': ty |= 32; break; 108 case 'v': ty = 64; goto void_type; 109 default: 110 yyerror("Invalid type"); 111 goto invalid_type; 112 } 113 114 switch (((char *)$1->name)[1]) { 115 case '8': ty = 1; break; 116 case '1': ty = 2; break; 117 case '3': ty = 4; break; 118 case '6': ty = 8; break; 119 default: 120 yyerror("Invalid type size"); 121 goto invalid_type; 122 } 123 124 void_type: 125 NEW($$, ((Type){.type = ty})); 126 invalid_type: 127 128 } 129 ; 130 131 exprs : expr ';' { 132 NEW($$, ((List){.size = sizeof(Expr), .count = 0, .data = NULL})); 133 APPEND($$, $1); 134 } 135 | exprs expr ';' { APPEND($1, $2); } 136 | exprs error ';' { yyerrok; } 137 ; 138 139 expr : name '(' params ')' { NEW($$, ((Expr){.expr = FCALL_EXPR, .fcall.name = $1, .fcall.args = (Rhs *)$3->data, .fcall.argc = $3->count})); } 140 | VAR name type '=' rhs { NEW($$, ((Expr){.expr = ASSIGN, .assign.type = $3, .assign.name = $2, .assign.rhs = $5})); } 141 ; 142 143 params : rhs { 144 NEW($$, ((List){.size = sizeof(Rhs), .count = 0, .data = NULL})); 145 APPEND($$, $1); 146 } 147 | params ',' rhs { 148 APPEND($1, $3); 149 $$ = $1; 150 } 151 | params ',' error { yyerrok; yyclearin; } 152 ; 153 154 rhs : value { NEW($$, ((Rhs){.rhs = VALUE, .value = $1})); } 155 | name '(' params ')' { NEW($$, ((Rhs){.rhs = FCALL_RHS, .fcall.name = $1})); } 156 | rhs '+' rhs { NEW($$, ((Rhs){.rhs = MATH, .math.op = ADD, .math.lhs = $1, .math.rhs = $3}));} 157 | rhs '-' rhs { NEW($$, ((Rhs){.rhs = MATH, .math.op = SUB, .math.lhs = $1, .math.rhs = $3}));} 158 | rhs '*' rhs { NEW($$, ((Rhs){.rhs = MATH, .math.op = MUL, .math.lhs = $1, .math.rhs = $3}));} 159 | rhs '/' rhs { NEW($$, ((Rhs){.rhs = MATH, .math.op = DIV, .math.lhs = $1, .math.rhs = $3}));} 160 | '(' rhs ')' { NEW($$, ((Rhs){.rhs = BRACE, .brace = $2})); } 161 ; 162 163 value : INT { NEW($$, ((Value){.lval = atoll($1->data)})); } 164 | FLOAT { NEW($$, ((Value){.dval = atof($1->data)})); } 165 ; 166 %% 167 168 char *getpos(struct Pos p) { 169 static char buf[128]; 170 snprintf(buf, 128, "%d:%d", p.row, p.col); 171 return buf; 172 } 173 174 void yyerror(const char *msg) { 175 if (nerror++ > 20) { 176 fprintf(stderr, "To many errors, giving up\n"); 177 exit(1); 178 } 179 fprintf(stderr, "%s: %s\n", getpos(lasttok.pos), msg); 180 }