comp

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

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 }