aboutsummaryrefslogblamecommitdiff
path: root/cibic.y
blob: 3cfdad9b989d8d543551bab039b21616c56d1b6e (plain) (tree)
1
2
3
4
5
6
7
8
9

                  
                
  




                        
              



                                                                                         
                                                                                     
              

                                             
                                                                                                                                                               
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
              
  
       
                                                                           





                                                                       

           
                          


                                                                                   
     
                                            


                                                                                       
     


                                                                             


                                                                                   

                                                                  


                                                                                  



                       
                                                                          


                
                                                                    


                     
                                                                              

               

                                                                                             

           

                                                                                              


                 

                                                            

              











                                                                                                          


                  
                                                                    
            
                                       


                                                                                             
     





                                   
                                                                                            

          
                                 


                                                                              

                                           


                                                                                 
     



                      


                                                                          


                

                                                                 








                          

                                                                                                       


                                      


                                                                                                          



                                  
                                                                


                                  
                                                              


                                           

                                                                                

                                                             

                                                               



                                             
                                                                         

                                                                               
                                                                               






                                  


                                                                                             
 

                           
                                             

                                                                   


                           


                                                                  
















                                          
                                                           

                                                                      


                             
                                                              

                                                                       


                             
                                                           

                                                                   


                       
                                                  

                                                                   


                         
                                              

                                                                   

                   

                                                                   

                                                                  






                             
                                                                  

                                                                  








                             
                                                           

                                                                  






                               
                                                                       

                                                                  






                         
                                                                         

                                                                  







                       
                                         
                                                                        


                    
                                                                             


                        




                                                                                                 










                        


                                                                           

       
                                                                                          
                          


                                                                                 
                





                                                                                               


                           
                                                                             


                  



                                                                         

          
                                                                         
  
%{
#include <stdio.h>
#include "ast.h"
%}
%union {
    int intval;
    char *strval;
    struct CNode *cnode;
}
%error-verbose
%token IDENTIFIER INT_CONST CHAR_CONST STR_CONST
%token KW_VOID KW_CHAR KW_INT KW_STRUCT KW_UNION KW_IF KW_ELSE KW_WHILE
%token KW_FOR KW_CONT KW_BREAK KW_RET KW_SIZEOF
%token OPT_OR OPT_AND OPT_EQ OPT_NE OPT_LE OPT_GE OPT_SHL OPT_SHR OPT_INC OPT_DEC OPT_PTR
%token ASS_MUL ASS_DIV ASS_MOD ASS_ADD ASS_SUB ASS_SHL ASS_SHR ASS_AND ASS_XOR ASS_OR
%token UNKNOWN
%type<intval> INT_CONST
%type<strval> IDENTIFIER STR_CONST CHAR_CONST
%type<intval> assignment_operator equality_operator relational_operator shift_operator additive_operator multiplicative_operator unary_operator struct_or_union
%type<cnode> expression assignment_expression constant_expression logical_or_expression logical_and_expression inclusive_or_expression exclusive_or_expression and_expression equality_expression relational_expression shift_expression additive_expression multiplicative_expression cast_expression type_name unary_expression postfix_expression identifier primary_expression arguments postfix type_specifier program declaration function_definition parameters declarators init_declarators init_declarator initializer array_initializer struct_fields struct_field plain_declaration  declarator_array plain_declarator expression_statement compound_statement statement comp_decls comp_stmts selection_statement iteration_statement jump_statement optional_exp declarator prog_list
%start program
%%
program
    : prog_list { ast_root = cnode_create_ast(cnode_list_wrap(PROG, $1)); }

prog_list
    : declaration
    | function_definition
    | prog_list declaration         { $$ = cnode_list_append($1, $2); }
    | prog_list function_definition { $$ = cnode_list_append($1, $2); }

declaration
    : type_specifier ';' {
        $$ = cnode_add_loc(cnode_create_decl(
                            $1, 
                            cnode_list_wrap(INIT_DECLRS, cnode_create_nop())), @$);
    }
    | type_specifier init_declarators ';' { 
        $$ = cnode_add_loc(cnode_create_decl(
                            $1,
                            cnode_add_loc(cnode_list_wrap(INIT_DECLRS, $2), @2)), @$); 
    }

function_definition
    : type_specifier plain_declarator '(' parameters ')' compound_statement {
        $$ = cnode_add_loc(cnode_create_func(
                            $1, $2, cnode_add_loc(
                                        cnode_list_wrap(PARAMS, $4), @4), $6), @$);
    }
    | type_specifier plain_declarator '(' ')' compound_statement {
        $$ = cnode_add_loc(cnode_create_func(
                            $1, $2, 
                            cnode_list_wrap(PARAMS, cnode_create_nop()), $5), @$);
    }

parameters
    : plain_declaration
    | parameters ',' plain_declaration { $$ = cnode_list_append($1, $3); }

declarators
    : declarator
    | declarators ',' declarator { $$ = cnode_list_append($1, $3); }

init_declarators
    : init_declarator
    | init_declarators ',' init_declarator { $$ = cnode_list_append($1, $3); }

init_declarator
    : declarator { $$ = cnode_add_loc(cnode_create_init_declr($1, cnode_create_nop()), @$); }
    | declarator '=' initializer { $$ = cnode_add_loc(cnode_create_init_declr($1, $3), @$); }

initializer
    : assignment_expression { $$ = cnode_add_loc(cnode_create_initr(INITR_NORM, $1), @$); }
    | '{' array_initializer '}' { $$ = cnode_add_loc(cnode_create_initr(INITR_ARR, $2), @$); }

array_initializer
    : initializer
    | array_initializer ',' initializer {
        $$ = cnode_list_append(cnode_add_loc($1, @1), $3); }

type_specifier
    : KW_VOID { $$ = cnode_add_loc(cnode_create_type_spec(KW_VOID, 0), @$); }
    | KW_CHAR { $$ = cnode_add_loc(cnode_create_type_spec(KW_CHAR, 0), @$); }
    | KW_INT { $$ = cnode_add_loc(cnode_create_type_spec(KW_INT, 0), @$); }
    | struct_or_union identifier '{' struct_fields '}' { 
        $$ = cnode_add_loc(cnode_create_type_spec($1, 2, $2, cnode_add_loc($4, @4)), @$); 
    }
    | struct_or_union '{' struct_fields '}'            {
        $$ = cnode_add_loc(cnode_create_type_spec($1, 2, cnode_create_nop(), cnode_add_loc($3, @3)), @$); 
    }
    | struct_or_union identifier { 
        $$ = cnode_add_loc(cnode_create_type_spec($1, 2, $2, cnode_create_nop()), @$); 
    }

struct_fields
    : struct_field
    | struct_fields struct_field { $$ = cnode_list_append($1, $2); }
struct_field
    : type_specifier declarators ';' { 
        $$ = cnode_add_loc(
                cnode_create_struct_field($1,
                                        cnode_add_loc(cnode_list_wrap(DECLRS, $2), @2)), @$);
    }

struct_or_union
    : KW_STRUCT { $$ = KW_STRUCT; }
    | KW_UNION { $$ = KW_UNION; }

plain_declaration
    : type_specifier declarator { $$ = cnode_add_loc(cnode_create_plain_decl($1, $2), @$); }

declarator
    : plain_declarator '(' ')' { 
        $$ = cnode_add_loc(cnode_create_declr(
                            DECLR_FUNC, 2, $1, 
                            cnode_list_wrap(PARAMS, cnode_create_nop())), @$);
    }
    | plain_declarator '(' parameters ')' {
        $$ = cnode_add_loc(cnode_create_declr(
                            DECLR_FUNC, 2, $1, 
                            cnode_add_loc(cnode_list_wrap(PARAMS, $3), @3)), @$);
    }
    | declarator_array

declarator_array
    : plain_declarator
    | declarator_array '[' constant_expression ']' { 
        $$ = cnode_add_loc(cnode_create_declr(DECLR_ARR, 2, $1, $3), @$); 
    }

plain_declarator
    : identifier
    | '*' plain_declarator {
        $$ = cnode_add_loc(cnode_create_declr('*', 1, $2), @$); }

statement
    : expression_statement
    | compound_statement
    | selection_statement
    | iteration_statement
    | jump_statement

expression_statement
    : ';'               { $$ = cnode_add_loc(cnode_create_stmt(STMT_EXP, 1, cnode_create_nop()), @$); }
    | expression ';'    { $$ = cnode_add_loc(cnode_create_stmt(STMT_EXP, 1, $1), @$); }

compound_statement
    : '{' comp_decls comp_stmts '}' { 
        $$ = cnode_add_loc(
                cnode_create_stmt(STMT_COMP, 2, cnode_add_loc(cnode_list_wrap(COMP_DECLS, $2), @2), 
                                                cnode_add_loc(cnode_list_wrap(COMP_STMTS, $3), @3)), @$); 
    }

comp_decls
    : { $$ = cnode_create_nop(); }
    | comp_decls declaration { $$ = cnode_list_append($1, $2); }

comp_stmts
    : { $$ = cnode_create_nop(); }
    | comp_stmts statement { $$ = cnode_list_append($1, $2); }

selection_statement
    : KW_IF '(' expression ')' statement { 
        $$ = cnode_add_loc(
                cnode_create_stmt(STMT_IF, 3, $3, $5, cnode_create_nop()), @$); 
    }
    | KW_IF '(' expression ')' statement KW_ELSE statement { 
        $$ = cnode_add_loc(
                cnode_create_stmt(STMT_IF, 3, $3, $5, $7), @$);
    }

iteration_statement
    : KW_WHILE '(' expression ')' statement {
        $$ = cnode_add_loc(cnode_create_stmt(STMT_WHILE, 2, $3, $5), @$);
    }
    | KW_FOR '(' optional_exp ';' optional_exp ';' optional_exp ')' statement {
        $$ = cnode_add_loc(cnode_create_stmt(STMT_FOR, 4, $3, $5, $7, $9), @$);
    }

optional_exp
    : { $$ = cnode_create_nop(); }
    | expression

jump_statement
    : KW_CONT ';'   { $$ = cnode_add_loc(cnode_create_stmt(STMT_CONT, 0), @$); }
    | KW_BREAK ';'  { $$ = cnode_add_loc(cnode_create_stmt(STMT_BREAK, 0), @$); }
    | KW_RET optional_exp ';' { $$ = cnode_add_loc(cnode_create_stmt(STMT_RET, 1, $2), @$); }

expression
    : assignment_expression
    | expression ',' assignment_expression { 
        @$ = @2;
        $$ = cnode_add_loc(cnode_create_exp(',', 2, $1, $3), @2); }

assignment_expression
    : logical_or_expression
    | unary_expression assignment_operator assignment_expression {
        @$ = @2;
        $$ = cnode_add_loc(cnode_create_exp($2, 2, $1, $3), @2); }

assignment_operator
    : '='           { $$ = '='; }
    | ASS_MUL       { $$ = ASS_MUL; }
    | ASS_DIV       { $$ = ASS_DIV; }
    | ASS_MOD       { $$ = ASS_MOD; }
    | ASS_ADD       { $$ = ASS_ADD; }
    | ASS_SUB       { $$ = ASS_SUB; }
    | ASS_SHL       { $$ = ASS_SHL; }
    | ASS_SHR       { $$ = ASS_SHR; }
    | ASS_AND       { $$ = ASS_AND; }
    | ASS_XOR       { $$ = ASS_XOR; }
    | ASS_OR        { $$ = ASS_OR; }

constant_expression: logical_or_expression
logical_or_expression
    : logical_and_expression
    | logical_or_expression OPT_OR logical_and_expression {
        @$ = @2;
        $$ = cnode_add_loc(cnode_create_exp(OPT_OR, 2, $1, $3), @2); }

logical_and_expression
    : inclusive_or_expression
    | logical_and_expression OPT_AND inclusive_or_expression {
        @$ = @2;
        $$ = cnode_add_loc(cnode_create_exp(OPT_AND, 2, $1, $3), @2); }

inclusive_or_expression
    : exclusive_or_expression
    | inclusive_or_expression '|' exclusive_or_expression {
        @$ = @2;
        $$ = cnode_add_loc(cnode_create_exp('|', 2, $1, $3), @2); }

exclusive_or_expression
    : and_expression
    | exclusive_or_expression '^' and_expression {
        @$ = @2;
        $$ = cnode_add_loc(cnode_create_exp('^', 2, $1, $3), @2); }

and_expression
    : equality_expression
    | and_expression '&' equality_expression {
        @$ = @2;
        $$ = cnode_add_loc(cnode_create_exp('&', 2, $1, $3), @2); }

equality_expression
    : relational_expression
    | equality_expression equality_operator relational_expression {
        @$ = @2;
        $$ = cnode_add_loc(cnode_create_exp($2, 2, $1, $3), @2); }

equality_operator
    : OPT_EQ { $$ = OPT_EQ; }
    | OPT_NE { $$ = OPT_NE; }

relational_expression
    : shift_expression
    | relational_expression relational_operator shift_expression {
        @$ = @2;
        $$ = cnode_add_loc(cnode_create_exp($2, 2, $1, $3), @2); }

relational_operator
    : '<' { $$ = '<'; }
    | '>' { $$ = '>'; }
    | OPT_LE { $$ = OPT_LE; }
    | OPT_GE { $$ = OPT_GE; }

shift_expression
    : additive_expression
    | shift_expression shift_operator additive_expression {
        @$ = @2;
        $$ = cnode_add_loc(cnode_create_exp($2, 2, $1, $3), @2); }

shift_operator
    : OPT_SHL { $$ = OPT_SHL; }
    | OPT_SHR { $$ = OPT_SHR; }

additive_expression
    : multiplicative_expression
    | additive_expression additive_operator multiplicative_expression {
        @$ = @2;
        $$ = cnode_add_loc(cnode_create_exp($2, 2, $1, $3), @2); }

additive_operator
    : '+' { $$ = '+'; }
    | '-' { $$ = '-'; }

multiplicative_expression
    : cast_expression
    | multiplicative_expression multiplicative_operator cast_expression {
        @$ = @2;
        $$ = cnode_add_loc(cnode_create_exp($2, 2, $1, $3), @2); }

multiplicative_operator
    : '*' { $$ = '*'; }
    | '/' { $$ = '/'; }
    | '%' { $$ = '%'; }

cast_expression
    : unary_expression
    | '(' type_name ')' cast_expression {
        $$ = cnode_add_loc(cnode_create_exp(EXP_CAST, 2, $2, $4), @$); }

type_name
    : type_specifier
    | type_name '*' { $$ = cnode_add_loc(cnode_create_exp('*', 1, $1), @$); }

unary_expression
    : postfix_expression
    | OPT_INC unary_expression { $$ = cnode_add_loc(cnode_create_exp(OPT_INC, 1, $2), @$); }
    | OPT_DEC unary_expression { $$ = cnode_add_loc(cnode_create_exp(OPT_DEC, 1, $2), @$); }
    | unary_operator cast_expression { $$ = cnode_add_loc(cnode_create_exp($1, 1, $2), @$); }
    | KW_SIZEOF unary_expression { $$ = cnode_add_loc(cnode_create_exp(KW_SIZEOF, 1, $2), @$); }
    | KW_SIZEOF '(' type_name ')' { $$ = cnode_add_loc(cnode_create_exp(KW_SIZEOF, 1, $3), @$); }

unary_operator
    : '&' { $$ = '&'; }
    | '*' { $$ = '*'; }
    | '+' { $$ = '+'; }
    | '-' { $$ = '-'; }
    | '~' { $$ = '~'; }
    | '!' { $$ = '!'; }

postfix_expression
    : primary_expression
    | postfix_expression postfix { 
        @$ = @2;
        $$ = cnode_add_loc(cnode_create_exp(EXP_POSTFIX, 2, $1, $2), @2); }

postfix
    : '[' expression ']' { $$ = cnode_add_loc(cnode_create_exp(POSTFIX_ARR, 1, $2), @$); }
    | '(' arguments ')' { 
        $$ = cnode_add_loc(cnode_create_exp(
                            POSTFIX_CALL, 1, 
                            cnode_add_loc(cnode_list_wrap(ARGS, $2), @2)), @$); }
    | '(' ')' { 
        $$ = cnode_add_loc(cnode_create_exp(
                            POSTFIX_CALL, 1, cnode_list_wrap(ARGS, cnode_create_nop())), @$); }
    | '.' identifier { $$ = cnode_add_loc(cnode_create_exp(POSTFIX_DOT, 1, $2), @$); }
    | OPT_PTR identifier { $$ = cnode_add_loc(cnode_create_exp(POSTFIX_PTR, 1, $2), @$); }
    | OPT_INC { $$ = cnode_add_loc(cnode_create_exp(OPT_INC, 0), @$); }
    | OPT_DEC { $$ = cnode_add_loc(cnode_create_exp(OPT_DEC, 0), @$); }

arguments
    : assignment_expression
    | arguments ',' assignment_expression { $$ = cnode_list_append($1, $3); }

primary_expression
    : identifier
    | INT_CONST   { $$ = cnode_add_loc(cnode_create_int_const($1), @$); }
    | CHAR_CONST { $$ = cnode_add_loc(cnode_create_char_const($1), @$); }
    | STR_CONST  { $$ = cnode_add_loc(cnode_create_str_const($1), @$); }
    | '(' expression ')' { $$ = cnode_add_loc($2, @$); }

identifier
    : IDENTIFIER { $$ = cnode_add_loc(cnode_create_identifier($1), @$); }
%%