[refractoring] removed the lang namespace
[ozulis.git] / src / plugins / mugiwara / bison-parser / parser.y
blob66980976746ecab911b8b2d0e6d7b3791740b616
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 {ozulis::ast::File *& file}
13 #include <stdio.h>
14 #include <string.h>
15 #include <stdlib.h>
17 #include <iostream>
18 #include <algorithm>
20 #include <ozulis/core/assert.hh>
21 #include <ozulis/ast/ast.hh>
22 #include <ozulis/ast/node-factory.hh>
24 #include "parser.hh"
25 #include "lexer.hh"
27 static void yyerror(YYLTYPE *yyloccp,
28 yyscan_t /*yyscanner*/,
29 ozulis::ast::File *& file,
30 const char *str)
32 if (file)
33 std::cerr << file->path << ":" ;
34 std::cerr << yyloccp->first_line << "." << yyloccp->first_column << "-"
35 << yyloccp->last_line << "." << yyloccp->last_column
36 << ": " << str << std::endl;
39 #define MAKE_BINARY_EXP(Type, Out, Left, Right) \
40 do { \
41 ozulis::ast::Type * exp = new ozulis::ast::Type(); \
42 assert(Left); \
43 assert(Right); \
44 exp = new ozulis::ast::Type(); \
45 exp->left = (Left); \
46 exp->right = (Right); \
47 (Out) = exp; \
48 } while (0)
50 #define MAKE_UNARY_EXP(Type, Out, Exp) \
51 do { \
52 ozulis::ast::Type * exp = new ozulis::ast::Type(); \
53 assert(Exp); \
54 exp = new ozulis::ast::Type(); \
55 exp->exp = (Exp); \
56 (Out) = exp; \
57 } while (0)
59 static ozulis::ast::Type *
60 createType(const char * name)
62 static const struct {
63 const char * name;
64 bool isSigned;
65 int size;
66 } integerTypes[] = {
67 { "int8", true, 8 },
68 { "uint8", false, 8 },
69 { "int16", true, 16 },
70 { "uint16", false, 16 },
71 { "int32", true, 32 },
72 { "uint32", false, 32 },
73 { "int64", true, 64 },
74 { "uint64", false, 64 },
75 { "int128", true, 128 },
76 { "uint128", false, 128 },
77 { 0, false, 0 }
80 for (int i = 0; integerTypes[i].name; i++)
81 if (!strcmp(name, integerTypes[i].name))
83 ozulis::ast::IntegerType * itype = new ozulis::ast::IntegerType();
84 itype->isSigned = integerTypes[i].isSigned;
85 itype->size = integerTypes[i].size;
86 return itype;
88 if (!strcmp("bool", name))
89 return ozulis::ast::NodeFactory::createBoolType();
90 if (!strcmp("float", name))
91 return ozulis::ast::NodeFactory::createFloatType();
92 if (!strcmp("double", name))
93 return ozulis::ast::NodeFactory::createDoubleType();
94 if (!strcmp("void", name))
95 return ozulis::ast::NodeFactory::createVoidType();
96 /// @todo resolve correctly the type
97 return new ozulis::ast::Type();
102 %union
104 ozulis::ast::Node * node;
105 std::vector<ozulis::ast::Node *> * nodes;
106 ozulis::ast::Function * funcDec;
107 ozulis::ast::Type * type;
108 std::vector<ozulis::ast::VarDecl *> * varDecls;
109 ozulis::ast::VarDecl * varDecl;
110 ozulis::ast::Block * block;
111 ozulis::ast::Exp * exp;
112 std::vector<ozulis::ast::Exp *> * exps;
113 ozulis::ast::NumberExp * nbExp;
115 int number;
116 char * string;
117 bool boolean;
120 %token <nbExp> NUMBER
121 %token <string> ID STRING
122 %token EQ SEMICOL DOT DDOT COMMA
123 %token EQEQ LT LTEQ GT GTEQ NEQ
124 %token ADD SUB DIV STAR MOD AT DOLLAR
125 %token OR AND XOR SHL ASHR LSHR
126 %token NOT BANG OROR ANDAND
127 %token LPAR RPAR LBR RBR LSB RSB
128 %token GOTO CONST CAST RETURN
129 %token IF ELSE WHILE DO FOR
131 %type <nodes> decls
132 %type <node> decl
133 %type <type> type
134 %type <varDecls> var_decls func_params func_params_non_empty
135 %type <varDecl> var_decl
136 %type <node> func_dec
137 %type <block> block
138 %type <nodes> statements
139 %type <node> statement label_statement goto_statement
140 %type <node> if_statement else_statement while_statement
141 %type <node> do_while_statement return_statement
142 %type <node> exp_statement
143 %type <exp> exp assign_exp oror_exp andand_exp or_exp xor_exp and_exp
144 %type <exp> cmp_exp shift_exp add_exp mul_exp unary_exp
145 %type <exp> call_exp
146 %type <exps> call_exp_args call_exp_args_non_empty
150 file: decls {
151 file = new ozulis::ast::File();
152 file->decls = $1;
153 std::reverse(file->decls->begin(), file->decls->end());
156 decls: decl decls {
157 assert($1);
158 assert($2);
159 $$ = $2;
160 $$->push_back($1);
161 } | /* epsilon */ { $$ = new std::vector<ozulis::ast::Node *> (); };
163 decl: func_dec {
164 $$ = $1;
167 func_dec: type ID LPAR func_params RPAR SEMICOL {
168 ozulis::ast::FunctionDecl * func = new ozulis::ast::FunctionDecl;
169 func->returnType = $1;
170 func->name = $2;
171 func->args = $4;
172 $$ = func;
173 } | type ID LPAR func_params RPAR block {
174 ozulis::ast::Function * func = new ozulis::ast::Function;
175 func->returnType = $1;
176 func->name = $2;
177 func->args = $4;
178 func->block = $6;
179 $$ = func;
182 func_params: func_params_non_empty { $$ = $1; }
183 | /* epsilon */ { $$ = new std::vector<ozulis::ast::VarDecl *>(); };
185 func_params_non_empty: var_decl {
186 $$ = new std::vector<ozulis::ast::VarDecl *>();
187 $$->push_back($1);
188 } | func_params_non_empty COMMA var_decl {
189 $$ = $1;
190 $$->push_back($3);
193 block: LBR var_decls statements RBR {
194 $$ = new ozulis::ast::Block();
195 $$->varDecls = $2;
196 $$->statements = $3;
199 var_decls: var_decls var_decl SEMICOL {
200 assert($2);
201 $$ = $1 ? : new std::vector<ozulis::ast::VarDecl *> ();
202 $$->push_back($2);
203 } | /* epsilon */ { $$ = new std::vector<ozulis::ast::VarDecl *> (); };
205 var_decl: type ID {
206 $$ = new ozulis::ast::VarDecl();
207 $$->type = $1;
208 $$->name = $2;
211 statements: statements statement {
212 assert($2);
213 $$ = $1 ? : new std::vector<ozulis::ast::Node *> ();
214 $$->push_back($2);
215 } | /* epsilon */ { $$ = new std::vector<ozulis::ast::Node *> (); };
217 statement: exp_statement { $$ = $1; }
218 | label_statement { $$ = $1; }
219 | goto_statement { $$ = $1; }
220 | if_statement { $$ = $1; }
221 | while_statement { $$ = $1; }
222 | do_while_statement { $$ = $1; }
223 | return_statement { $$ = $1; }
224 | block { $$ = $1; }
225 | SEMICOL { $$ = new ozulis::ast::EmptyStatement(); };
227 exp_statement: exp SEMICOL {
228 assert($1);
229 $$ = $1;
232 label_statement: ID DDOT {
233 ozulis::ast::Label * label = new ozulis::ast::Label();
234 label->name = $1;
235 $$ = label;
238 goto_statement: GOTO ID SEMICOL {
239 ozulis::ast::Goto * gt = new ozulis::ast::Goto();
240 gt->label = $2;
241 $$ = gt;
244 if_statement: IF LPAR exp RPAR statement else_statement {
245 ozulis::ast::If * ifStmt = new ozulis::ast::If();
246 assert($3);
247 assert($5);
248 assert($6);
249 ifStmt->branch = new ozulis::ast::ConditionalBranch;
250 ifStmt->branch->cond = $3;
251 ifStmt->trueBlock = $5;
252 ifStmt->falseBlock = $6;
253 $$ = ifStmt;
256 else_statement: ELSE statement {
257 $$ = $2;
258 } | /* epsylon */ { $$ = new ozulis::ast::EmptyStatement; };
260 while_statement: WHILE LPAR exp RPAR statement {
261 ozulis::ast::While * whileStmt = new ozulis::ast::While;
262 assert($3);
263 assert($5);
264 whileStmt->branch = new ozulis::ast::ConditionalBranch;
265 whileStmt->branch->cond = $3;
266 whileStmt->block = $5;
267 $$ = whileStmt;
270 do_while_statement: DO statement WHILE LPAR exp RPAR SEMICOL {
271 ozulis::ast::DoWhile * doWhileStmt = new ozulis::ast::DoWhile;
272 assert($2);
273 assert($5);
274 doWhileStmt->branch = new ozulis::ast::ConditionalBranch;
275 doWhileStmt->branch->cond = $5;
276 doWhileStmt->block = $2;
277 $$ = doWhileStmt;
280 return_statement: RETURN SEMICOL {
281 ozulis::ast::Return * ret = new ozulis::ast::Return;
282 ret->exp = new ozulis::ast::VoidExp;
283 ret->exp->type = new ozulis::ast::VoidType;
284 $$ = ret;
285 } | RETURN exp SEMICOL {
286 ozulis::ast::Return * ret = new ozulis::ast::Return;
287 ret->exp = $2;
288 $$ = ret;
291 type: ID {
292 $$ = createType($1);
293 $$->name = $1;
294 } | CONST type {
295 $2->isConst = true;
296 $$ = $2;
297 } | AT type {
298 ozulis::ast::PointerType * type = new ozulis::ast::PointerType;
299 type->type = $2;
300 $$ = type;
301 } | LBR NUMBER RBR type {
302 ozulis::ast::ArrayType * type = new ozulis::ast::ArrayType;
303 type->type = $4;
304 type->size = $2->number;
305 $$ = type;
308 exp: assign_exp {
309 assert($1);
310 $$ = $1;
313 assign_exp: exp EQ oror_exp {
314 ozulis::ast::AssignExp * exp = new ozulis::ast::AssignExp();
315 exp->dest = $1;
316 exp->value = $3;
317 $$ = exp;
318 } | oror_exp { assert($1); $$ = $1; };
320 oror_exp: oror_exp OROR andand_exp { MAKE_BINARY_EXP(OrOrExp, $$, $1, $3); }
321 | andand_exp { assert($1); $$ = $1; };
323 andand_exp: andand_exp ANDAND or_exp { MAKE_BINARY_EXP(AndAndExp, $$, $1, $3); }
324 | or_exp { assert($1); $$ = $1; };
326 or_exp: or_exp OR xor_exp { MAKE_BINARY_EXP(OrExp, $$, $1, $3); }
327 | xor_exp { assert($1); $$ = $1; };
329 xor_exp: xor_exp XOR and_exp { MAKE_BINARY_EXP(XorExp, $$, $1, $3); }
330 | and_exp { assert($1); $$ = $1; };
332 and_exp: and_exp AND cmp_exp { MAKE_BINARY_EXP(AndExp, $$, $1, $3); }
333 | cmp_exp { assert($1); $$ = $1; };
335 cmp_exp: shift_exp EQEQ shift_exp { MAKE_BINARY_EXP(EqExp, $$, $1, $3); }
336 | shift_exp NEQ shift_exp { MAKE_BINARY_EXP(NeqExp, $$, $1, $3); }
337 | shift_exp LT shift_exp { MAKE_BINARY_EXP(LtExp, $$, $1, $3); }
338 | shift_exp LTEQ shift_exp { MAKE_BINARY_EXP(LtEqExp, $$, $1, $3); }
339 | shift_exp GT shift_exp { MAKE_BINARY_EXP(GtExp, $$, $1, $3); }
340 | shift_exp GTEQ shift_exp { MAKE_BINARY_EXP(GtEqExp, $$, $1, $3); }
341 | shift_exp { assert($1); $$ = $1; };
343 shift_exp: shift_exp SHL add_exp { MAKE_BINARY_EXP(ShlExp, $$, $1, $3); }
344 | shift_exp ASHR add_exp { MAKE_BINARY_EXP(AShrExp, $$, $1, $3); }
345 | shift_exp LSHR add_exp { MAKE_BINARY_EXP(LShrExp, $$, $1, $3); }
346 | add_exp { assert($1); $$ = $1; };
348 add_exp: add_exp ADD mul_exp { MAKE_BINARY_EXP(AddExp, $$, $1, $3); }
349 | add_exp SUB mul_exp { MAKE_BINARY_EXP(SubExp, $$, $1, $3); }
350 | mul_exp { assert($1); $$ = $1; };
352 mul_exp: mul_exp STAR unary_exp { MAKE_BINARY_EXP(MulExp, $$, $1, $3); }
353 | mul_exp DIV unary_exp { MAKE_BINARY_EXP(DivExp, $$, $1, $3); }
354 | mul_exp MOD unary_exp { MAKE_BINARY_EXP(ModExp, $$, $1, $3); }
355 | unary_exp { assert($1); $$ = $1; };
357 unary_exp: NUMBER { $$ = $1; }
358 | ID {
359 ozulis::ast::IdExp * exp = new ozulis::ast::IdExp;
360 exp->symbol = new ozulis::ast::Symbol;
361 exp->symbol->name = $1;
362 $$ = exp;
363 } | STRING {
364 ozulis::ast::StringExp * exp = new ozulis::ast::StringExp;
365 exp->string = $1;
366 $$ = exp;
367 } | LPAR exp RPAR { assert($2); $$ = $2; }
368 | BANG unary_exp { MAKE_UNARY_EXP(BangExp, $$, $2); }
369 | NOT unary_exp { MAKE_UNARY_EXP(NotExp, $$, $2); }
370 | SUB unary_exp { MAKE_UNARY_EXP(NegExp, $$, $2); }
371 | call_exp { $$ = $1; }
372 | CAST LPAR type COMMA exp RPAR {
373 ozulis::ast::CastExp * cast = new ozulis::ast::CastExp;
374 assert($3);
375 assert($5);
376 cast->type = $3;
377 cast->exp = $5;
378 $$ = cast;
379 } | unary_exp DOLLAR {
380 ozulis::ast::DereferenceExp * exp = new ozulis::ast::DereferenceExp;
381 exp->exp = $1;
382 $$ = exp;
383 } | AT unary_exp {
384 ozulis::ast::AtExp * exp = new ozulis::ast::AtExp;
385 exp->exp = $2;
386 $$ = exp;
387 } | unary_exp LSB exp RSB {
388 ozulis::ast::DereferenceByIndexExp * exp = new ozulis::ast::DereferenceByIndexExp;
389 exp->exp = $1;
390 exp->index = $3;
391 $$ = exp;
394 call_exp: ID LPAR call_exp_args RPAR {
395 assert($1);
396 assert($3);
398 ozulis::ast::CallExp * callExp = new ozulis::ast::CallExp;
399 callExp->id = $1;
400 callExp->args = $3;
401 $$ = callExp;
404 call_exp_args: call_exp_args_non_empty { $$ = $1; }
405 | /* empty */ { $$ = new std::vector<ozulis::ast::Exp *>(); };
407 call_exp_args_non_empty: exp {
408 assert($1);
409 $$ = new std::vector<ozulis::ast::Exp *>();
410 $$->push_back($1);
411 } | call_exp_args_non_empty COMMA exp {
412 assert($1);
413 assert($3);
414 $1->push_back($3);
415 $$ = $1;
420 #ifdef WITH_MAIN
421 int main(void)
423 void *exp;
424 yyscan_t scanner;
426 yylex_init(&scanner);
427 yyparse(scanner, &exp);
428 return 0;
430 #endif /* WITH_MAIN */