7 %name
-prefix
"mugiwara"
9 %lex
-param
{yyscan_t yyscanner
}
10 %parse
-param
{yyscan_t yyscanner
}
11 %parse
-param
{ozulis
::ast
::File
*& file
}
21 #include <ozulis/core/assert.hh>
22 #include <ozulis/ast/ast.hh>
23 #include <ozulis/ast/node-factory.hh>
28 static void yyerror(YYLTYPE *yyloccp
,
29 yyscan_t
/*yyscanner*/,
30 ozulis
::ast
::File
*& 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) \
42 ozulis
::ast
::Type
* exp
= new ozulis
::ast
::Type
(); \
45 exp
= new ozulis
::ast
::Type
(); \
47 exp
->right
= (Right
); \
51 #define MAKE_UNARY_EXP(Type, Out, Exp) \
53 ozulis
::ast
::Type
* exp
= new ozulis
::ast
::Type
(); \
55 exp
= new ozulis
::ast
::Type
(); \
60 static ozulis
::ast
::Type
*
61 createType
(const char * name
)
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 },
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
;
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
;
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
;
122 %token
<nbExp
> NUMBER
123 %token
<string> ID STRING
136 %token RETURN
"return"
146 %type
<varDecls
> var_decls func_params func_params_non_empty
147 %type
<varDecl
> var_decl
148 %type
<node
> func_dec
150 %type
<nodes
> statements
151 %type
<node
> statement label_statement goto_statement
152 %type
<node
> if_statement else_statement while_statement
153 %type
<node
> do_while_statement return_statement
154 %type
<node
> exp_statement
155 %type
<exp
> exp assign_exp oror_exp andand_exp or_exp xor_exp and_exp
156 %type
<exp
> cmp_exp shift_exp add_exp mul_exp unary_exp
158 %type
<exps
> call_exp_args call_exp_args_non_empty
163 file
= new ozulis
::ast
::File
();
166 file
->varDecls
= new ozulis
::ast
::File
::varDecls_t
;
167 std
::reverse
(file
->decls
->begin
(), file
->decls
->end
());
175 } |
/* epsilon */ { $$
= new std
::vector
<ozulis
::ast
::Node
*> (); };
181 func_dec: type ID
'(' func_params
')' ';' {
182 ozulis
::ast
::FunctionDecl
* func
= new ozulis
::ast
::FunctionDecl
;
183 func
->returnType
= $1;
187 } | type ID
'(' func_params
')' block
{
188 ozulis
::ast
::Function
* func
= new ozulis
::ast
::Function
;
189 func
->returnType
= $1;
196 func_params: func_params_non_empty
{ $$
= $1; }
197 |
/* epsilon */ { $$
= new std
::vector
<ozulis
::ast
::VarDecl
*>(); };
199 func_params_non_empty: var_decl
{
200 $$
= new std
::vector
<ozulis
::ast
::VarDecl
*>();
202 } | func_params_non_empty
',' var_decl
{
207 block: '[' var_decls statements
']' {
208 $$
= new ozulis
::ast
::Block
();
213 var_decls: var_decls var_decl
';' {
215 $$
= $1 ?
: new std
::vector
<ozulis
::ast
::VarDecl
*> ();
217 } |
/* epsilon */ { $$
= new std
::vector
<ozulis
::ast
::VarDecl
*> (); };
220 $$
= new ozulis
::ast
::VarDecl
();
225 statements: statements statement
{
227 $$
= $1 ?
: new std
::vector
<ozulis
::ast
::Node
*> ();
229 } |
/* epsilon */ { $$
= new std
::vector
<ozulis
::ast
::Node
*> (); };
231 statement: exp_statement
{ $$
= $1; }
232 | label_statement
{ $$
= $1; }
233 | goto_statement
{ $$
= $1; }
234 | if_statement
{ $$
= $1; }
235 | while_statement
{ $$
= $1; }
236 | do_while_statement
{ $$
= $1; }
237 | return_statement
{ $$
= $1; }
239 |
';' { $$
= new ozulis
::ast
::EmptyStatement
(); };
241 exp_statement: exp
';' {
246 label_statement: ID
':' {
247 ozulis
::ast
::Label
* label
= new ozulis
::ast
::Label
();
252 goto_statement: "goto" ID
';' {
253 ozulis
::ast
::Goto
* gt
= new ozulis
::ast
::Goto
();
258 if_statement: "if" '(' exp
')' statement else_statement
{
259 ozulis
::ast
::If
* ifStmt
= new ozulis
::ast
::If
();
263 ifStmt
->branch
= new ozulis
::ast
::ConditionalBranch
;
264 ifStmt
->branch
->cond
= $3;
265 ifStmt
->trueBlock
= $5;
266 ifStmt
->falseBlock
= $6;
270 else_statement: "else" statement
{
272 } |
/* epsylon */ { $$
= new ozulis
::ast
::EmptyStatement
; };
274 while_statement: "while" '(' exp
')' statement
{
275 ozulis
::ast
::While
* whileStmt
= new ozulis
::ast
::While
;
278 whileStmt
->branch
= new ozulis
::ast
::ConditionalBranch
;
279 whileStmt
->branch
->cond
= $3;
280 whileStmt
->block
= $5;
284 do_while_statement: "do" statement
"while" '(' exp
')' ';' {
285 ozulis
::ast
::DoWhile
* doWhileStmt
= new ozulis
::ast
::DoWhile
;
288 doWhileStmt
->branch
= new ozulis
::ast
::ConditionalBranch
;
289 doWhileStmt
->branch
->cond
= $5;
290 doWhileStmt
->block
= $2;
294 return_statement: "return" ';' {
295 ozulis
::ast
::Return
* ret
= new ozulis
::ast
::Return
;
296 ret
->exp
= new ozulis
::ast
::VoidExp
;
297 ret
->exp
->type
= new ozulis
::ast
::VoidType
;
299 } |
"return" exp
';' {
300 ozulis
::ast
::Return
* ret
= new ozulis
::ast
::Return
;
311 ozulis
::ast
::PointerType
* type
= new ozulis
::ast
::PointerType
;
314 } |
'{' NUMBER
',' type
'}' {
315 ozulis
::ast
::ArrayType
* type
= new ozulis
::ast
::ArrayType
;
317 type
->size
= $2->number
;
326 assign_exp: exp
'=' oror_exp
{
327 ozulis
::ast
::AssignExp
* exp
= new ozulis
::ast
::AssignExp
();
331 } | oror_exp
{ assert
($1); $$
= $1; };
333 oror_exp: oror_exp
"||" andand_exp
{ MAKE_BINARY_EXP
(OrOrExp
, $$
, $1, $3); }
334 | andand_exp
{ assert
($1); $$
= $1; };
336 andand_exp: andand_exp
"&&" or_exp
{ MAKE_BINARY_EXP
(AndAndExp
, $$
, $1, $3); }
337 | or_exp
{ assert
($1); $$
= $1; };
339 or_exp: or_exp
'|' xor_exp
{ MAKE_BINARY_EXP
(OrExp
, $$
, $1, $3); }
340 | xor_exp
{ assert
($1); $$
= $1; };
342 xor_exp: xor_exp
'^' and_exp
{ MAKE_BINARY_EXP
(XorExp
, $$
, $1, $3); }
343 | and_exp
{ assert
($1); $$
= $1; };
345 and_exp: and_exp
'&' cmp_exp
{ MAKE_BINARY_EXP
(AndExp
, $$
, $1, $3); }
346 | cmp_exp
{ assert
($1); $$
= $1; };
348 cmp_exp: shift_exp
"==" shift_exp
{ MAKE_BINARY_EXP
(EqExp
, $$
, $1, $3); }
349 | shift_exp
"!=" shift_exp
{ MAKE_BINARY_EXP
(NeqExp
, $$
, $1, $3); }
350 | shift_exp
'<' shift_exp
{ MAKE_BINARY_EXP
(LtExp
, $$
, $1, $3); }
351 | shift_exp
"<=" shift_exp
{ MAKE_BINARY_EXP
(LtEqExp
, $$
, $1, $3); }
352 | shift_exp
'>' shift_exp
{ MAKE_BINARY_EXP
(GtExp
, $$
, $1, $3); }
353 | shift_exp
">=" shift_exp
{ MAKE_BINARY_EXP
(GtEqExp
, $$
, $1, $3); }
354 | shift_exp
{ assert
($1); $$
= $1; };
356 shift_exp: shift_exp
"<<" add_exp
{ MAKE_BINARY_EXP
(ShlExp
, $$
, $1, $3); }
357 | shift_exp
">>>" add_exp
{ MAKE_BINARY_EXP
(AShrExp
, $$
, $1, $3); }
358 | shift_exp
">>" add_exp
{ MAKE_BINARY_EXP
(LShrExp
, $$
, $1, $3); }
359 | add_exp
{ assert
($1); $$
= $1; };
361 add_exp: add_exp
'+' mul_exp
{ MAKE_BINARY_EXP
(AddExp
, $$
, $1, $3); }
362 | add_exp
'-' mul_exp
{ MAKE_BINARY_EXP
(SubExp
, $$
, $1, $3); }
363 | mul_exp
{ assert
($1); $$
= $1; };
365 mul_exp: mul_exp
'*' unary_exp
{ MAKE_BINARY_EXP
(MulExp
, $$
, $1, $3); }
366 | mul_exp
'/' unary_exp
{ MAKE_BINARY_EXP
(DivExp
, $$
, $1, $3); }
367 | mul_exp
'%' unary_exp
{ MAKE_BINARY_EXP
(ModExp
, $$
, $1, $3); }
368 | unary_exp
{ assert
($1); $$
= $1; };
370 unary_exp: NUMBER
{ $$
= $1; }
372 ozulis
::ast
::IdExp
* exp
= new ozulis
::ast
::IdExp
;
373 exp
->symbol
= new ozulis
::ast
::Symbol
;
374 exp
->symbol
->name
= $1;
377 ozulis
::ast
::StringExp
* exp
= new ozulis
::ast
::StringExp
;
380 } |
'(' exp
')' { assert
($2); $$
= $2; }
381 |
'!' unary_exp
{ MAKE_UNARY_EXP
(BangExp
, $$
, $2); }
382 |
'~' unary_exp
{ MAKE_UNARY_EXP
(NotExp
, $$
, $2); }
383 |
'-' unary_exp
{ MAKE_UNARY_EXP
(NegExp
, $$
, $2); }
384 | call_exp
{ $$
= $1; }
385 |
"cast" '(' type
',' exp
')' {
386 ozulis
::ast
::CastExp
* cast
= new ozulis
::ast
::CastExp
;
393 ozulis
::ast
::DereferenceExp
* exp
= new ozulis
::ast
::DereferenceExp
;
397 ozulis
::ast
::AtExp
* exp
= new ozulis
::ast
::AtExp
;
400 } | unary_exp
'{' exp
'}' {
401 ozulis
::ast
::DereferenceByIndexExp
* exp
= new ozulis
::ast
::DereferenceByIndexExp
;
407 call_exp: ID
'(' call_exp_args
')' {
411 ozulis
::ast
::CallExp
* callExp
= new ozulis
::ast
::CallExp
;
417 call_exp_args: call_exp_args_non_empty
{ $$
= $1; }
418 |
/* empty */ { $$
= new std
::vector
<ozulis
::ast
::Exp
*>(); };
420 call_exp_args_non_empty: exp
{
422 $$
= new std
::vector
<ozulis
::ast
::Exp
*>();
424 } | call_exp_args_non_empty
',' exp
{