cleaned mugiwara's parser
[ozulis.git] / src / plugins / lang / mugiwara / bison-parser / parser.y
blob32b9934e9a4048082ccde74365b7a845d8e1859d
1 %glr-parser
2 %pure-parser
3 %locations
4 %start file
5 %defines
6 %error-verbose
7 %name-prefix "mugiwara"
9 %lex-param {yyscan_t yyscanner}
10 %parse-param {yyscan_t yyscanner}
11 %parse-param {ozulis::ast::File *& file}
14 #include <stdio.h>
15 #include <string.h>
16 #include <stdlib.h>
18 #include <iostream>
19 #include <algorithm>
21 #include <ozulis/core/assert.hh>
22 #include <ozulis/ast/ast.hh>
23 #include <ozulis/ast/node-factory.hh>
25 #include "parser.hh"
26 #include "lexer.hh"
28 static void yyerror(YYLTYPE *yyloccp,
29 yyscan_t /*yyscanner*/,
30 ozulis::ast::File *& file,
31 const char *str)
33 if (file)
34 std::cerr << file->path << ":" ;
35 std::cerr << yyloccp->first_line << "." << yyloccp->first_column << "-"
36 << yyloccp->last_line << "." << yyloccp->last_column
37 << ": " << str << std::endl;
40 #define MAKE_BINARY_EXP(Type, Out, Left, Right) \
41 do { \
42 ozulis::ast::Type * exp = new ozulis::ast::Type(); \
43 assert(Left); \
44 assert(Right); \
45 exp = new ozulis::ast::Type(); \
46 exp->left = (Left); \
47 exp->right = (Right); \
48 (Out) = exp; \
49 } while (0)
51 #define MAKE_UNARY_EXP(Type, Out, Exp) \
52 do { \
53 ozulis::ast::Type * exp = new ozulis::ast::Type(); \
54 assert(Exp); \
55 exp = new ozulis::ast::Type(); \
56 exp->exp = (Exp); \
57 (Out) = exp; \
58 } while (0)
60 static ozulis::ast::Type *
61 createType(const char * name)
63 static const struct {
64 const char * name;
65 bool isSigned;
66 int size;
67 } integerTypes[] = {
68 { "int8", true, 8 },
69 { "uint8", false, 8 },
70 { "int16", true, 16 },
71 { "uint16", false, 16 },
72 { "int32", true, 32 },
73 { "uint32", false, 32 },
74 { "int64", true, 64 },
75 { "uint64", false, 64 },
76 { "int128", true, 128 },
77 { "uint128", false, 128 },
78 { 0, false, 0 }
81 for (int i = 0; integerTypes[i].name; i++)
82 if (!strcmp(name, integerTypes[i].name))
84 ozulis::ast::IntegerType * itype = new ozulis::ast::IntegerType();
85 itype->isSigned = integerTypes[i].isSigned;
86 itype->size = integerTypes[i].size;
87 return itype;
89 if (!strcmp("bool", name))
90 return ozulis::ast::NodeFactory::createBoolType();
91 if (!strcmp("float", name))
92 return ozulis::ast::NodeFactory::createFloatType();
93 if (!strcmp("double", name))
94 return ozulis::ast::NodeFactory::createDoubleType();
95 if (!strcmp("void", name))
96 return ozulis::ast::NodeFactory::createVoidType();
97 ozulis::ast::NamedType * type = new ozulis::ast::NamedType;
98 type->name = name;
99 return type;
104 %union
106 ozulis::ast::Node * node;
107 std::vector<ozulis::ast::Node *> * nodes;
108 ozulis::ast::Function * funcDec;
109 ozulis::ast::Type * type;
110 std::vector<ozulis::ast::VarDecl *> * varDecls;
111 ozulis::ast::VarDecl * varDecl;
112 ozulis::ast::Block * block;
113 ozulis::ast::Exp * exp;
114 std::vector<ozulis::ast::Exp *> * exps;
115 ozulis::ast::NumberExp * nbExp;
117 int number;
118 char * string;
119 bool boolean;
122 %token <nbExp> NUMBER
123 %token <string> ID STRING
124 %token EQ SEMICOL DOT DDOT COMMA
125 %token EQEQ LT LTEQ GT GTEQ NEQ
126 %token ADD SUB DIV STAR MOD AT DOLLAR
127 %token OR AND XOR SHL ASHR LSHR
128 %token NOT BANG OROR ANDAND
129 %token LPAR RPAR LBR RBR LSB RSB
130 %token GOTO CONST CAST RETURN
131 %token IF ELSE WHILE DO FOR
133 %type <nodes> decls
134 %type <node> decl
135 %type <type> type
136 %type <varDecls> var_decls func_params func_params_non_empty
137 %type <varDecl> var_decl
138 %type <node> func_dec
139 %type <block> block
140 %type <nodes> statements
141 %type <node> statement label_statement goto_statement
142 %type <node> if_statement else_statement while_statement
143 %type <node> do_while_statement return_statement
144 %type <node> exp_statement
145 %type <exp> exp assign_exp oror_exp andand_exp or_exp xor_exp and_exp
146 %type <exp> cmp_exp shift_exp add_exp mul_exp unary_exp
147 %type <exp> call_exp
148 %type <exps> call_exp_args call_exp_args_non_empty
152 file: decls {
153 file = new ozulis::ast::File();
154 file->decls = $1;
155 if (!file->varDecls)
156 file->varDecls = new ozulis::ast::File::varDecls_t;
157 std::reverse(file->decls->begin(), file->decls->end());
160 decls: decl decls {
161 assert($1);
162 assert($2);
163 $$ = $2;
164 $$->push_back($1);
165 } | /* epsilon */ { $$ = new std::vector<ozulis::ast::Node *> (); };
167 decl: func_dec {
168 $$ = $1;
171 func_dec: type ID LPAR func_params RPAR SEMICOL {
172 ozulis::ast::FunctionDecl * func = new ozulis::ast::FunctionDecl;
173 func->returnType = $1;
174 func->name = $2;
175 func->args = $4;
176 $$ = func;
177 } | type ID LPAR func_params RPAR block {
178 ozulis::ast::Function * func = new ozulis::ast::Function;
179 func->returnType = $1;
180 func->name = $2;
181 func->args = $4;
182 func->block = $6;
183 $$ = func;
186 func_params: func_params_non_empty { $$ = $1; }
187 | /* epsilon */ { $$ = new std::vector<ozulis::ast::VarDecl *>(); };
189 func_params_non_empty: var_decl {
190 $$ = new std::vector<ozulis::ast::VarDecl *>();
191 $$->push_back($1);
192 } | func_params_non_empty COMMA var_decl {
193 $$ = $1;
194 $$->push_back($3);
197 block: LBR var_decls statements RBR {
198 $$ = new ozulis::ast::Block();
199 $$->varDecls = $2;
200 $$->statements = $3;
203 var_decls: var_decls var_decl SEMICOL {
204 assert($2);
205 $$ = $1 ? : new std::vector<ozulis::ast::VarDecl *> ();
206 $$->push_back($2);
207 } | /* epsilon */ { $$ = new std::vector<ozulis::ast::VarDecl *> (); };
209 var_decl: type ID {
210 $$ = new ozulis::ast::VarDecl();
211 $$->type = $1;
212 $$->name = $2;
215 statements: statements statement {
216 assert($2);
217 $$ = $1 ? : new std::vector<ozulis::ast::Node *> ();
218 $$->push_back($2);
219 } | /* epsilon */ { $$ = new std::vector<ozulis::ast::Node *> (); };
221 statement: exp_statement { $$ = $1; }
222 | label_statement { $$ = $1; }
223 | goto_statement { $$ = $1; }
224 | if_statement { $$ = $1; }
225 | while_statement { $$ = $1; }
226 | do_while_statement { $$ = $1; }
227 | return_statement { $$ = $1; }
228 | block { $$ = $1; }
229 | SEMICOL { $$ = new ozulis::ast::EmptyStatement(); };
231 exp_statement: exp SEMICOL {
232 assert($1);
233 $$ = $1;
236 label_statement: ID DDOT {
237 ozulis::ast::Label * label = new ozulis::ast::Label();
238 label->name = $1;
239 $$ = label;
242 goto_statement: GOTO ID SEMICOL {
243 ozulis::ast::Goto * gt = new ozulis::ast::Goto();
244 gt->label = $2;
245 $$ = gt;
248 if_statement: IF LPAR exp RPAR statement else_statement {
249 ozulis::ast::If * ifStmt = new ozulis::ast::If();
250 assert($3);
251 assert($5);
252 assert($6);
253 ifStmt->branch = new ozulis::ast::ConditionalBranch;
254 ifStmt->branch->cond = $3;
255 ifStmt->trueBlock = $5;
256 ifStmt->falseBlock = $6;
257 $$ = ifStmt;
260 else_statement: ELSE statement {
261 $$ = $2;
262 } | /* epsylon */ { $$ = new ozulis::ast::EmptyStatement; };
264 while_statement: WHILE LPAR exp RPAR statement {
265 ozulis::ast::While * whileStmt = new ozulis::ast::While;
266 assert($3);
267 assert($5);
268 whileStmt->branch = new ozulis::ast::ConditionalBranch;
269 whileStmt->branch->cond = $3;
270 whileStmt->block = $5;
271 $$ = whileStmt;
274 do_while_statement: DO statement WHILE LPAR exp RPAR SEMICOL {
275 ozulis::ast::DoWhile * doWhileStmt = new ozulis::ast::DoWhile;
276 assert($2);
277 assert($5);
278 doWhileStmt->branch = new ozulis::ast::ConditionalBranch;
279 doWhileStmt->branch->cond = $5;
280 doWhileStmt->block = $2;
281 $$ = doWhileStmt;
284 return_statement: RETURN SEMICOL {
285 ozulis::ast::Return * ret = new ozulis::ast::Return;
286 ret->exp = new ozulis::ast::VoidExp;
287 ret->exp->type = new ozulis::ast::VoidType;
288 $$ = ret;
289 } | RETURN exp SEMICOL {
290 ozulis::ast::Return * ret = new ozulis::ast::Return;
291 ret->exp = $2;
292 $$ = ret;
295 type: ID {
296 $$ = createType($1);
297 } | CONST type {
298 $2->isConst = true;
299 $$ = $2;
300 } | AT type {
301 ozulis::ast::PointerType * type = new ozulis::ast::PointerType;
302 type->type = $2;
303 $$ = type;
304 } | LSB NUMBER COMMA type RSB {
305 ozulis::ast::ArrayType * type = new ozulis::ast::ArrayType;
306 type->type = $4;
307 type->size = $2->number;
308 $$ = type;
311 exp: assign_exp {
312 assert($1);
313 $$ = $1;
316 assign_exp: exp EQ oror_exp {
317 ozulis::ast::AssignExp * exp = new ozulis::ast::AssignExp();
318 exp->dest = $1;
319 exp->value = $3;
320 $$ = exp;
321 } | oror_exp { assert($1); $$ = $1; };
323 oror_exp: oror_exp OROR andand_exp { MAKE_BINARY_EXP(OrOrExp, $$, $1, $3); }
324 | andand_exp { assert($1); $$ = $1; };
326 andand_exp: andand_exp ANDAND or_exp { MAKE_BINARY_EXP(AndAndExp, $$, $1, $3); }
327 | or_exp { assert($1); $$ = $1; };
329 or_exp: or_exp OR xor_exp { MAKE_BINARY_EXP(OrExp, $$, $1, $3); }
330 | xor_exp { assert($1); $$ = $1; };
332 xor_exp: xor_exp XOR and_exp { MAKE_BINARY_EXP(XorExp, $$, $1, $3); }
333 | and_exp { assert($1); $$ = $1; };
335 and_exp: and_exp AND cmp_exp { MAKE_BINARY_EXP(AndExp, $$, $1, $3); }
336 | cmp_exp { assert($1); $$ = $1; };
338 cmp_exp: shift_exp EQEQ shift_exp { MAKE_BINARY_EXP(EqExp, $$, $1, $3); }
339 | shift_exp NEQ shift_exp { MAKE_BINARY_EXP(NeqExp, $$, $1, $3); }
340 | shift_exp LT shift_exp { MAKE_BINARY_EXP(LtExp, $$, $1, $3); }
341 | shift_exp LTEQ shift_exp { MAKE_BINARY_EXP(LtEqExp, $$, $1, $3); }
342 | shift_exp GT shift_exp { MAKE_BINARY_EXP(GtExp, $$, $1, $3); }
343 | shift_exp GTEQ shift_exp { MAKE_BINARY_EXP(GtEqExp, $$, $1, $3); }
344 | shift_exp { assert($1); $$ = $1; };
346 shift_exp: shift_exp SHL add_exp { MAKE_BINARY_EXP(ShlExp, $$, $1, $3); }
347 | shift_exp ASHR add_exp { MAKE_BINARY_EXP(AShrExp, $$, $1, $3); }
348 | shift_exp LSHR add_exp { MAKE_BINARY_EXP(LShrExp, $$, $1, $3); }
349 | add_exp { assert($1); $$ = $1; };
351 add_exp: add_exp ADD mul_exp { MAKE_BINARY_EXP(AddExp, $$, $1, $3); }
352 | add_exp SUB mul_exp { MAKE_BINARY_EXP(SubExp, $$, $1, $3); }
353 | mul_exp { assert($1); $$ = $1; };
355 mul_exp: mul_exp STAR unary_exp { MAKE_BINARY_EXP(MulExp, $$, $1, $3); }
356 | mul_exp DIV unary_exp { MAKE_BINARY_EXP(DivExp, $$, $1, $3); }
357 | mul_exp MOD unary_exp { MAKE_BINARY_EXP(ModExp, $$, $1, $3); }
358 | unary_exp { assert($1); $$ = $1; };
360 unary_exp: NUMBER { $$ = $1; }
361 | ID {
362 ozulis::ast::IdExp * exp = new ozulis::ast::IdExp;
363 exp->symbol = new ozulis::ast::Symbol;
364 exp->symbol->name = $1;
365 $$ = exp;
366 } | STRING {
367 ozulis::ast::StringExp * exp = new ozulis::ast::StringExp;
368 exp->string = $1;
369 $$ = exp;
370 } | LPAR exp RPAR { assert($2); $$ = $2; }
371 | BANG unary_exp { MAKE_UNARY_EXP(BangExp, $$, $2); }
372 | NOT unary_exp { MAKE_UNARY_EXP(NotExp, $$, $2); }
373 | SUB unary_exp { MAKE_UNARY_EXP(NegExp, $$, $2); }
374 | call_exp { $$ = $1; }
375 | CAST LPAR type COMMA exp RPAR {
376 ozulis::ast::CastExp * cast = new ozulis::ast::CastExp;
377 assert($3);
378 assert($5);
379 cast->type = $3;
380 cast->exp = $5;
381 $$ = cast;
382 } | unary_exp DOLLAR {
383 ozulis::ast::DereferenceExp * exp = new ozulis::ast::DereferenceExp;
384 exp->exp = $1;
385 $$ = exp;
386 } | AT unary_exp {
387 ozulis::ast::AtExp * exp = new ozulis::ast::AtExp;
388 exp->exp = $2;
389 $$ = exp;
390 } | unary_exp LSB exp RSB {
391 ozulis::ast::DereferenceByIndexExp * exp = new ozulis::ast::DereferenceByIndexExp;
392 exp->exp = $1;
393 exp->index = $3;
394 $$ = exp;
397 call_exp: ID LPAR call_exp_args RPAR {
398 assert($1);
399 assert($3);
401 ozulis::ast::CallExp * callExp = new ozulis::ast::CallExp;
402 callExp->id = $1;
403 callExp->args = $3;
404 $$ = callExp;
407 call_exp_args: call_exp_args_non_empty { $$ = $1; }
408 | /* empty */ { $$ = new std::vector<ozulis::ast::Exp *>(); };
410 call_exp_args_non_empty: exp {
411 assert($1);
412 $$ = new std::vector<ozulis::ast::Exp *>();
413 $$->push_back($1);
414 } | call_exp_args_non_empty COMMA exp {
415 assert($1);
416 assert($3);
417 $1->push_back($3);
418 $$ = $1;
423 #ifdef WITH_MAIN
424 int main(void)
426 void *exp;
427 yyscan_t scanner;
429 yylex_init(&scanner);
430 yyparse(scanner, &exp);
431 return 0;
433 #endif /* WITH_MAIN */