[pointers] finished :-)
[ozulis.git] / src / lang / mugiwara / bison-parser / parser.y
blobf4ea8b3e15a39dafa2a4acd3ec3f8c991b554950
1 %glr-parser
2 %pure-parser
3 %locations
4 %start file
5 %defines
6 %error-verbose
8 %lex-param {yyscan_t yyscanner}
9 %parse-param {yyscan_t yyscanner}
10 %parse-param {ast::File *& file}
13 #include <stdio.h>
14 #include <string.h>
15 #include <stdlib.h>
17 #include <iostream>
18 #include <algorithm>
20 #include <core/assert.hh>
21 #include <ast/ast.hh>
23 #include "parser.hh"
24 #include "lexer.hh"
26 static void yyerror(YYLTYPE *yyloccp,
27 yyscan_t /*yyscanner*/,
28 ast::File *& file,
29 const char *str)
31 if (file)
32 std::cerr << file->path << ":" ;
33 std::cerr << yyloccp->first_line << "." << yyloccp->first_column << "-"
34 << yyloccp->last_line << "." << yyloccp->last_column
35 << ": " << str << std::endl;
38 #define MAKE_BINARY_EXP(Type, Out, Left, Right) \
39 do { \
40 ast::Type * exp = new ast::Type(); \
41 assert(Left); \
42 assert(Right); \
43 exp = new ast::Type(); \
44 exp->left = (Left); \
45 exp->right = (Right); \
46 (Out) = exp; \
47 } while (0)
49 #define MAKE_UNARY_EXP(Type, Out, Exp) \
50 do { \
51 ast::Type * exp = new ast::Type(); \
52 assert(Exp); \
53 exp = new ast::Type(); \
54 exp->exp = (Exp); \
55 (Out) = exp; \
56 } while (0)
58 static ast::Type *
59 createType(const char * name)
61 static const struct {
62 const char * name;
63 bool isSigned;
64 int size;
65 } integerTypes[] = {
66 { "int8", true, 8 },
67 { "uint8", false, 8 },
68 { "int16", true, 16 },
69 { "uint16", false, 16 },
70 { "int32", true, 32 },
71 { "uint32", false, 32 },
72 { "int64", true, 64 },
73 { "uint64", false, 64 },
74 { "int128", true, 128 },
75 { "uint128", false, 128 },
76 { 0, false, 0 }
79 for (int i = 0; integerTypes[i].name; i++)
80 if (!strcmp(name, integerTypes[i].name))
82 ast::IntegerType * itype = new ast::IntegerType();
83 itype->isSigned = integerTypes[i].isSigned;
84 itype->size = integerTypes[i].size;
85 return itype;
87 if (!strcmp("bool", name))
88 return new ast::BoolType();
89 if (!strcmp("float", name))
90 return new ast::FloatType();
91 if (!strcmp("double", name))
92 return new ast::DoubleType();
93 if (!strcmp("void", name))
94 return new ast::VoidType();
95 /// @todo resolve correctly the type
96 return new ast::Type();
101 %union
103 ast::Node * node;
104 std::vector<ast::Node *> * nodes;
105 ast::Function * funcDec;
106 ast::Type * type;
107 std::vector<ast::VarDecl *> * varDecls;
108 ast::VarDecl * varDecl;
109 ast::Block * block;
110 ast::Exp * exp;
111 std::vector<ast::Exp *> * exps;
112 ast::NumberExp * nbExp;
114 int number;
115 char * string;
116 bool boolean;
119 %token <nbExp> NUMBER
120 %token <string> ID
121 %token EQ SEMICOL DOT DDOT COMMA
122 %token EQEQ LT LTEQ GT GTEQ NEQ
123 %token ADD SUB DIV STAR MOD
124 %token OR AND XOR SHL ASHR LSHR
125 %token NOT BANG OROR ANDAND
126 %token LPAR RPAR LBR RBR LSB RSB
127 %token GOTO CONST CAST RETURN
128 %token IF ELSE WHILE DO FOR
130 %type <nodes> decls
131 %type <node> decl
132 %type <type> type
133 %type <varDecls> var_decls func_params func_params_non_empty
134 %type <varDecl> var_decl
135 %type <funcDec> func_dec
136 %type <block> block
137 %type <nodes> statements
138 %type <node> statement label_statement goto_statement
139 %type <node> if_statement else_statement while_statement
140 %type <node> do_while_statement return_statement
141 %type <node> exp_statement
142 %type <exp> exp assign_exp oror_exp andand_exp or_exp xor_exp and_exp
143 %type <exp> cmp_exp shift_exp add_exp mul_exp unary_exp
144 %type <exp> call_exp
145 %type <exps> call_exp_args call_exp_args_non_empty
149 file: decls {
150 file = new ast::File();
151 file->decls = $1;
152 std::reverse(file->decls->begin(), file->decls->end());
155 decls: decl decls {
156 assert($1);
157 assert($2);
158 $$ = $2;
159 $$->push_back($1);
160 } | /* epsilon */ { $$ = new std::vector<ast::Node *> (); };
162 decl: func_dec {
163 $$ = $1;
166 func_dec: type ID LPAR func_params RPAR block {
167 $$ = new ast::Function();
168 $$->returnType = $1;
169 $$->name = $2;
170 $$->args = $4;
171 $$->block = $6;
174 func_params: func_params_non_empty { $$ = $1; }
175 | /* epsilon */ { $$ = new std::vector<ast::VarDecl *>(); };
177 func_params_non_empty: var_decl {
178 $$ = new std::vector<ast::VarDecl *>();
179 $$->push_back($1);
180 } | func_params_non_empty COMMA var_decl {
181 $$ = $1;
182 $$->push_back($3);
185 block: LBR var_decls statements RBR {
186 $$ = new ast::Block();
187 $$->varDecls = $2;
188 $$->statements = $3;
191 var_decls: var_decls var_decl SEMICOL {
192 assert($2);
193 $$ = $1 ? : new std::vector<ast::VarDecl *> ();
194 $$->push_back($2);
195 } | /* epsilon */ { $$ = new std::vector<ast::VarDecl *> (); };
197 var_decl: type ID {
198 $$ = new ast::VarDecl();
199 $$->type = $1;
200 $$->name = $2;
203 statements: statements statement {
204 assert($2);
205 $$ = $1 ? : new std::vector<ast::Node *> ();
206 $$->push_back($2);
207 } | /* epsilon */ { $$ = new std::vector<ast::Node *> (); };
209 statement: exp_statement { $$ = $1; }
210 | label_statement { $$ = $1; }
211 | goto_statement { $$ = $1; }
212 | if_statement { $$ = $1; }
213 | while_statement { $$ = $1; }
214 | do_while_statement { $$ = $1; }
215 | return_statement { $$ = $1; }
216 | block { $$ = $1; }
217 | SEMICOL { $$ = new ast::EmptyStatement(); };
219 exp_statement: exp SEMICOL {
220 assert($1);
221 $$ = $1;
224 label_statement: ID DDOT {
225 ast::Label * label = new ast::Label();
226 label->name = $1;
227 $$ = label;
230 goto_statement: GOTO ID SEMICOL {
231 ast::Goto * gt = new ast::Goto();
232 gt->label = $2;
233 $$ = gt;
236 if_statement: IF LPAR exp RPAR statement else_statement {
237 ast::If * ifStmt = new ast::If();
238 assert($3);
239 assert($5);
240 assert($6);
241 ifStmt->branch = new ast::ConditionalBranch;
242 ifStmt->branch->cond = $3;
243 ifStmt->trueBlock = $5;
244 ifStmt->falseBlock = $6;
245 $$ = ifStmt;
248 else_statement: ELSE statement {
249 $$ = $2;
250 } | /* epsylon */ { $$ = new ast::EmptyStatement; };
252 while_statement: WHILE LPAR exp RPAR statement {
253 ast::While * whileStmt = new ast::While;
254 assert($3);
255 assert($5);
256 whileStmt->branch = new ast::ConditionalBranch;
257 whileStmt->branch->cond = $3;
258 whileStmt->block = $5;
259 $$ = whileStmt;
262 do_while_statement: DO statement WHILE LPAR exp RPAR SEMICOL {
263 ast::DoWhile * doWhileStmt = new ast::DoWhile;
264 assert($2);
265 assert($5);
266 doWhileStmt->branch = new ast::ConditionalBranch;
267 doWhileStmt->branch->cond = $5;
268 doWhileStmt->block = $2;
269 $$ = doWhileStmt;
272 return_statement: RETURN SEMICOL {
273 ast::Return * ret = new ast::Return;
274 ret->exp = new ast::VoidExp;
275 ret->exp->type = new ast::VoidType;
276 $$ = ret;
277 } | RETURN exp SEMICOL {
278 ast::Return * ret = new ast::Return;
279 ret->exp = $2;
280 $$ = ret;
283 type: ID {
284 $$ = createType($1);
285 $$->name = $1;
286 } | CONST type {
287 $2->isConst = true;
288 $$ = $2;
289 } | STAR type {
290 ast::PointerType * type = new ast::PointerType;
291 type->type = $2;
292 $$ = type;
293 } | LBR NUMBER RBR type {
294 ast::ArrayType * type = new ast::ArrayType;
295 type->type = $4;
296 type->size = $2->number;
297 $$ = type;
300 exp: assign_exp {
301 assert($1);
302 $$ = $1;
305 assign_exp: ID EQ oror_exp {
306 ast::AssignExp * exp = new ast::AssignExp();
307 exp->dest = new ast::Symbol();
308 exp->dest->name = $1;
309 exp->value = $3;
310 $$ = exp;
311 } | oror_exp { assert($1); $$ = $1; };
313 oror_exp: oror_exp OROR andand_exp { MAKE_BINARY_EXP(OrOrExp, $$, $1, $3); }
314 | andand_exp { assert($1); $$ = $1; };
316 andand_exp: andand_exp ANDAND or_exp { MAKE_BINARY_EXP(AndAndExp, $$, $1, $3); }
317 | or_exp { assert($1); $$ = $1; };
319 or_exp: or_exp OR xor_exp { MAKE_BINARY_EXP(OrExp, $$, $1, $3); }
320 | xor_exp { assert($1); $$ = $1; };
322 xor_exp: xor_exp XOR and_exp { MAKE_BINARY_EXP(XorExp, $$, $1, $3); }
323 | and_exp { assert($1); $$ = $1; };
325 and_exp: and_exp AND cmp_exp { MAKE_BINARY_EXP(AndExp, $$, $1, $3); }
326 | cmp_exp { assert($1); $$ = $1; };
328 cmp_exp: shift_exp EQEQ shift_exp { MAKE_BINARY_EXP(EqExp, $$, $1, $3); }
329 | shift_exp NEQ shift_exp { MAKE_BINARY_EXP(NeqExp, $$, $1, $3); }
330 | shift_exp LT shift_exp { MAKE_BINARY_EXP(LtExp, $$, $1, $3); }
331 | shift_exp LTEQ shift_exp { MAKE_BINARY_EXP(LtEqExp, $$, $1, $3); }
332 | shift_exp GT shift_exp { MAKE_BINARY_EXP(GtExp, $$, $1, $3); }
333 | shift_exp GTEQ shift_exp { MAKE_BINARY_EXP(GtEqExp, $$, $1, $3); }
334 | shift_exp { assert($1); $$ = $1; };
336 shift_exp: shift_exp SHL add_exp { MAKE_BINARY_EXP(ShlExp, $$, $1, $3); }
337 | shift_exp ASHR add_exp { MAKE_BINARY_EXP(AShrExp, $$, $1, $3); }
338 | shift_exp LSHR add_exp { MAKE_BINARY_EXP(LShrExp, $$, $1, $3); }
339 | add_exp { assert($1); $$ = $1; };
341 add_exp: add_exp ADD mul_exp { MAKE_BINARY_EXP(AddExp, $$, $1, $3); }
342 | add_exp SUB mul_exp { MAKE_BINARY_EXP(SubExp, $$, $1, $3); }
343 | mul_exp { assert($1); $$ = $1; };
345 mul_exp: mul_exp STAR unary_exp { MAKE_BINARY_EXP(MulExp, $$, $1, $3); }
346 | mul_exp DIV unary_exp { MAKE_BINARY_EXP(DivExp, $$, $1, $3); }
347 | mul_exp MOD unary_exp { MAKE_BINARY_EXP(ModExp, $$, $1, $3); }
348 | unary_exp { assert($1); $$ = $1; };
350 unary_exp: NUMBER { $$ = $1; }
351 | ID {
352 ast::IdExp * exp = new ast::IdExp();
353 exp->symbol = new ast::Symbol;
354 exp->symbol->name = $1;
355 $$ = exp;
356 } | LPAR exp RPAR { assert($2); $$ = $2; }
357 | BANG unary_exp { MAKE_UNARY_EXP(BangExp, $$, $2); }
358 | NOT unary_exp { MAKE_UNARY_EXP(NotExp, $$, $2); }
359 | SUB unary_exp { MAKE_UNARY_EXP(NegExp, $$, $2); }
360 | call_exp { $$ = $1; }
361 | CAST LPAR type COMMA exp RPAR {
362 ast::CastExp * cast = new ast::CastExp;
363 assert($3);
364 assert($5);
365 cast->type = $3;
366 cast->exp = $5;
367 $$ = cast;
368 } | unary_exp STAR {
369 ast::DereferenceExp * exp = new ast::DereferenceExp;
370 exp->exp = $1;
371 $$ = exp;
374 call_exp: ID LPAR call_exp_args RPAR {
375 assert($1);
376 assert($3);
378 ast::CallExp * callExp = new ast::CallExp;
379 callExp->id = $1;
380 callExp->args = $3;
381 $$ = callExp;
384 call_exp_args: call_exp_args_non_empty { $$ = $1; }
385 | /* empty */ { $$ = new std::vector<ast::Exp *>(); };
387 call_exp_args_non_empty: exp {
388 assert($1);
389 $$ = new std::vector<ast::Exp *>();
390 $$->push_back($1);
391 } | call_exp_args_non_empty COMMA exp {
392 assert($1);
393 assert($3);
394 $1->push_back($3);
395 $$ = $1;
400 #ifdef WITH_MAIN
401 int main(void)
403 void *exp;
404 yyscan_t scanner;
406 yylex_init(&scanner);
407 yyparse(scanner, &exp);
408 return 0;
410 #endif /* WITH_MAIN */