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

                  
                   
                
  




                        
              

                                                                                                                                                     


                                                                                                                                                

                                
                       
                                                       
                                                                                                                                                               
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
              
  
       
                                                                           





                                                                       

           






                                                                                 
                                             
                               
                                                                                   
                     
     
                                            

                                             
                                                                                      
                     
     

                   

                                                              
                     


          

                       
                                                                          


                
                                                                    


                     
                                                                              

               

                                                                                             

           

                                                                                              


                 

                                                            

              


                                                                                            

                                                                                                                  
                      

                                                        
                                                                                                                                  
                      
     

                                                                                      
                      
     



                                                                                                    


                  
                                                                    
            
                                      
                           



                                                                         
     

               

                                                   

                 



                                                                
 
                 
                                          
                                     
                                            
                                              
                                              
                                                                                 
     
                                                     
                                                                         
     
 


                       
                                                                 








                          

                                                                                                       

                  
                                                                      
                           


                                                                                                         



                                  
                                                                


                                  
                                                              

                   
                                          
                           
                                                                               
     
                                                            

                                                               



                                             
                                                                         

                                                                               
                                                                               






                                  


                                                                                             
 

                           
                                            

                                                                   


                           


                                                                  
















                                          
                                                           

                                                                      


                             
                                                              

                                                                       


                             
                                                           

                                                                   


                       
                                                  

                                                                   


                         
                                              

                                                                   

                   

                                                                   

                                                                  






                             
                                                                  

                                                                  








                             
                                                           

                                                                  






                               
                                                                       

                                                                  






                         
                                                                         

                                                                  







                       
                                         
                                                                        

         
                                              


                                                                 




























                                                                                         


                        




                                                                                                 










                        
                                  

                                                                           

       
                                                                                          
                         
                                            
                                            
                                                                                 



                                                                                          

         

                           
                                                                             


                  



                                                                         

          
                                                                         
  
%{
#include <stdio.h>
#include <stdlib.h>
#include "ast.h"
%}
%union {
    int intval;
    char *strval;
    struct CNode *cnode;
}
%error-verbose
%token IDENTIFIER "identifier" INT_CONST "integer constant" CHAR_CONST "character constant" STR_CONST "string constant" USER_TYPE "typedef name"
%token KW_VOID "void" KW_CHAR "char" KW_INT "int" KW_STRUCT "struct" KW_UNION "union" KW_IF "if" KW_ELSE "else" KW_WHILE "while" KW_TYPEDEF "typedef"
%token KW_FOR "for" KW_CONT "continue" KW_BREAK "break" KW_RET "ret" KW_SIZEOF "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 "stray character"
%token END 0 "end of file"
%type<intval> INT_CONST
%type<strval> IDENTIFIER STR_CONST CHAR_CONST USER_TYPE
%type<intval> additive_operator assignment_operator equality_operator multiplicative_operator relational_operator shift_operator struct_or_union unary_operator
%type<cnode> additive_expression and_expression arguments array_initializer assignment_expression cast_expression comp_decls compound_statement comp_stmts constant_expression declaration declarator declarators equality_expression exclusive_or_expression expression expression_statement function_definition identifier inclusive_or_expression init_declarator init_declarators initializer iteration_statement jump_statement logical_and_expression logical_or_expression multiplicative_expression optional_exp parameters plain_declaration direct_declarator postfix postfix_expression primary_expression prog_list program relational_expression selection_statement shift_expression statement struct_field struct_fields type_name type_specifier unary_expression abstract_declarator direct_abstract_declarator direct_abstract_declarator_opt abstract_declarator_opt user_type
%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
    : KW_TYPEDEF type_specifier { enter_typedef(); } declarators ';' {
        $$ = cnode_add_loc(cnode_create_typedef(
                            $2,
                            cnode_add_loc(cnode_list_wrap(DECLRS, $4), @4)), @$);
        exit_declr();
    }
    | type_specifier ';' {
        $$ = cnode_add_loc(cnode_create_decl(
                            $1,
                            cnode_list_wrap(INIT_DECLRS, cnode_create_nop())), @$);
        exit_declr();
    }
    | type_specifier init_declarators  ';' {
        $$ = cnode_add_loc(cnode_create_decl(
                            $1,
                            cnode_add_loc(cnode_list_wrap(INIT_DECLRS, $2), @2)), @$);
        exit_declr();
    }

function_definition
    : type_specifier declarator compound_statement {
        $$ = cnode_add_loc(cnode_create_func($1, $2, $3), @$);
        exit_declr();
    }

parameters
    : { $$ = NULL; }
    | 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), @$); enter_declr(); }
    | KW_CHAR { $$ = cnode_add_loc(cnode_create_type_spec(KW_CHAR, 0), @$); enter_declr(); }
    | KW_INT { $$ = cnode_add_loc(cnode_create_type_spec(KW_INT, 0), @$); enter_declr(); }
    | struct_or_union identifier '{' struct_fields '}' {
        $$ = cnode_add_loc(cnode_create_type_spec($1, 2, $2, cnode_add_loc(cnode_list_wrap(FIELDS, $4), @4)), @$);
        enter_declr();
    }
    | struct_or_union '{' struct_fields '}'            {
        $$ = cnode_add_loc(cnode_create_type_spec($1, 2, cnode_create_nop(), cnode_add_loc(cnode_list_wrap(FIELDS, $3), @3)), @$);
        enter_declr();
    }
    | struct_or_union identifier {
        $$ = cnode_add_loc(cnode_create_type_spec($1, 2, $2, cnode_create_nop()), @$);
        enter_declr();
    }
    | user_type { $$ = cnode_add_loc(cnode_create_type_spec(USER_TYPE, 1, $1), @$); enter_declr(); }

user_type
    : USER_TYPE { $$ = cnode_add_loc(cnode_create_identifier($1), @$); }

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)), @$);
        exit_declr();
    }

struct_or_union
    : KW_STRUCT { $$ = KW_STRUCT; enter_struct(); }
    | KW_UNION { $$ = KW_UNION; enter_struct(); }

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

direct_declarator
    : identifier { push($1->rec.strval); }
    | '(' declarator ')' { $$ = $2; }
    | direct_declarator '(' parameters ')' {
        $$ = cnode_add_loc(cnode_create_declr(
                            DECLR_FUNC, 2, $1,
                            cnode_add_loc(cnode_list_wrap(PARAMS, $3), @3)), @$);
    }
    | direct_declarator '[' constant_expression ']' {
        $$ = cnode_add_loc(cnode_create_declr(DECLR_ARR, 2, $1, $3), @$);
    }

declarator
    : direct_declarator
    | '*' 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
    : { exit_declr(); enter_block(); } '{' comp_decls comp_stmts '}' {
        $$ = cnode_add_loc(
                cnode_create_stmt(STMT_COMP, 2, cnode_add_loc(cnode_list_wrap(COMP_DECLS, $3), @3),
                                                cnode_add_loc(cnode_list_wrap(COMP_STMTS, $4), @4)), @$);
        exit_block();
    }

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 abstract_declarator_opt {
        $$ = cnode_add_loc(cnode_create_declr(0, 2, $1, $2), @$);
        exit_declr();
    }

abstract_declarator_opt
    : { $$ = cnode_create_nop(); }
    | abstract_declarator

abstract_declarator
    : '*' { $$ = cnode_add_loc(cnode_create_declr('*', 1, cnode_create_nop()), @$); }
    | '*' abstract_declarator { $$ = cnode_add_loc(cnode_create_declr('*', 1, $2), @$); }
    | direct_abstract_declarator

direct_abstract_declarator_opt
    : { $$ = cnode_create_nop(); }
    | direct_abstract_declarator

direct_abstract_declarator
    : '(' abstract_declarator ')' { $$ = $2; }
    | direct_abstract_declarator '(' parameters ')' {
        $$ = cnode_add_loc(cnode_create_declr(
                            DECLR_FUNC, 2, $1,
                            cnode_add_loc(cnode_list_wrap(PARAMS, $3), @3)), @$);
    }
    | '(' parameters ')' {
        $$ = cnode_add_loc(cnode_create_declr(
                            DECLR_FUNC, 2, cnode_create_nop(),
                            cnode_add_loc(cnode_list_wrap(PARAMS, $2), @2)), @$);
    }
    | direct_abstract_declarator_opt '[' constant_expression ']' {
        $$ = cnode_add_loc(cnode_create_declr(DECLR_ARR, 2, $1, $3), @$);
    }

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)), @$); }
    | '.' 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
    : { $$ = NULL; }
    | 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), @$); }
%%