summaryrefslogblamecommitdiffstats
path: root/src/parser.y
blob: e69cbbfb20131f1a5f5bed489610fe041e480fba (plain) (tree)
1
2
3
4
5
6
7
8
9


                                  
                                                   
  



                    

                       
                
                  
 


                   


       
                 

                                

  
  
                                                                          

                                                                                      

  
                 
                         


            
              



            
             



                



             





            









                 
 

                     









                                                                   






                               

                                  

                                                                        

                                                       


                     

                                                                        
                                        

                     


                                              
                                                              






                                












                                
 
                                                                                  
                     

                                                                          
                                                             
                                                                           

                                                               

                                                                          
                                            


                                                                                  

                                                                          
                                                             
                                                                           

                                                               



                                                                          
                                            
                     























                                                                            

                                                                        

                                                                          
                                                                   
                                                                           
                                                            

                                                                          
                                                  


                                                                        

                                                                          
                                                                   
                                                                           
                                                        



                                                                          
                                                  


                     
                                        
                 
                                                          


                   
                            


                 
                     
                 

                                                                                
                                                        

                                                                       


                            

                                                                                

                                                        

                                                                               

                 
 
                                           




                                             
                                                          
                 
             
 
                 
                 
                            


                 
                                                                               


                 

                                 
                                                                                 

                                                    

                                                                            
                                               

                                                                   


                       
                                                                                 

                                               

                                                                   


                       
                                                                                 

                                               

                                                                            

                 
                                                                                 

                 
 
                            
                 
                                                          


                  
                            


                 
                       








                            
                                             
                 

                                                                  
                                                             


                                             




                                                                           


                 
                                          
                 

                                                                      
                                                             


                                   




                                                                           


                 
                 
                 

                                                                  


                   

                                                                  


                 
                
                 

                                                                  


                                 


                                                                       


                                          



                                                                               


                         


                                                                          
                 
             
 
                                       
                 



                                                
                                                          
                 
             
 
                                 
                 

                                                                      
                                                             


                                                      

                                                                      
                                                             


                    
                            

                 
 
                                   
                 

                                                                      
                                                             


                                   

                                                                      
                                                             


                     
                            


                 
                 
                 

                                                                        
                                         


                                       
                            


                 





                                           
                                                          

                 
 
                
                 

                                                                  


                         
                                                

                                                                          


                                     

                                                                     
                                                   


                 
                            
                 
                                                          


                  
                            


                 
                                       
                 



                                                       
                                                                                       
                                                             
                 

                                                                                                                  
                                                                                     
                                                                     


                                                     
                                                                                        
                                                             
                 

                                                    
                                                                                    
                                                            
                                                                               
                 
                                                              
                 
                                                                                    
                                                                 
                 

                                                               
                                                                                               
                                                    
                                                                                            
                 

                        
                                                                               


                               
                                                                                        


                                          
                                                                                        
                                                   


                 

                                           
                                           
                                                                                          
                                                       


                     
                                                                                   




                                                                            
                                                                         





                                           
 
                                              
                     

                                                                        
                                                                 


                            
                                
                     
                 
 





                                             

                                                                          
                                                                 

                     
 





                                                

                                                                          
                                                                 

                     
 
                      
                     
                                


                                  
                                
                                                                 


                     

                       

                                                                          


                       

                                                                          


                       

                                                                          


                       

                                                                          


                       

                                                                          


                       

                                                                          

                     

 
                                          
                     
                                           
                                                                                         
                                                       


                     
                                                                                   


                     

                                                                      
                                                                      





                                        
 
                              
                 
                            
                                                             


                  
                            


                 
                    
                 

                                                                      


                    

                                                                      


                 
                                
                 
                            
                                                             


                    
                            


                 
                    
                 

                                                                      


                    

                                                                      


                 
                                            
                 



                                                   

                                                                          
                                                   


                                                   

                                                                          
                                                   
                 

                                                   

                                                                                  
                                                   


                   
                                                                                       
                                         
                 

                          



                                                                          

                                                           


                          



                                                                          

                                                           
                 

                          



                                                                                  

                                                           


                                                    
                                            
                                                                           
                                                    

                                                                           


                                                           

                                                                          
                                                             
                                                                           
                                                           

                                                                           
                                                          


                                                           

                                                                          
                                                             
                                                                           
                                                           

                                                                           
                                                          
                 

                                                           

                                                                                  
                                                             
                                                                           
                                                           

                                                                           
                                                          


                     



                            

                                                                          
                                                   


                            

                                                                          
                                                   
                 

                            

                                                                                  
                                                   


                 
                
                 

                                                                  


                         

                                                                 
                                                   



                 
                                               
                 
                                                          


                                      
                            
                 
             


  
                                                                                     
 

                                                                    

            

                               
%define api.prefix {ccmmc_parser_}
%define api.pure full
%lex-param {yyscan_t scanner}
%parse-param {yyscan_t scanner} {CcmmcState *state}
%{
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

typedef void* yyscan_t;

#include "ast.h"
#include "state.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
%}

%union{
    char *lexeme;
    CcmmcAst *node;
    CcmmcValueConst value_const;
};

%{
extern int ccmmc_parser_lex(CCMMC_PARSER_STYPE *yylval, yyscan_t scanner);
extern char *ccmmc_parser_get_text(yyscan_t scanner);
static void ccmmc_parser_error(yyscan_t scanner, CcmmcState *state, const char *mesg);
%}

%token <lexeme>ID
%token <value_const>CONST
%token VOID
%token INT
%token FLOAT
%token TYPEDEF
%token IF
%token ELSE
%token WHILE
%token FOR
%token RETURN
%token OP_ASSIGN
%token OP_OR
%token OP_AND
%token OP_NOT
%token OP_ADD
%token OP_SUB
%token OP_MUL
%token OP_DIV
%token OP_GT
%token OP_LT
%token OP_GE
%token OP_LE
%token OP_NE
%token OP_EQ
%token DL_LPAREN
%token DL_RPAREN
%token DL_LBRACK
%token DL_RBRACK
%token DL_LBRACE
%token DL_RBRACE
%token DL_COMMA
%token DL_SEMICOL
%token DL_DOT
%token ERROR

%right DL_RPAREN ELSE

%type <node> program
%type <node> global_decl_list global_decl
%type <node> function_decl param_list param dim_fn expr_null block
%type <node> decl_list decl type_decl var_decl type
%type <node> id_list dim_decl cexpr mcexpr cfactor
%type <node> init_id_list init_id stmt_list stmt
%type <node> assign_expr_list nonempty_assign_expr_list assign_expr
%type <node> relop_expr relop_term relop_factor rel_op
%type <node> relop_expr_list nonempty_relop_expr_list
%type <node> expr add_op term mul_op factor var_ref dim_list

%start program

%%

/* ==== Grammar Section ==== */

program         : global_decl_list
                    {
                        $$ = ccmmc_ast_new(
                            CCMMC_AST_NODE_PROGRAM, state->line_number);
                        ccmmc_ast_append_child($$, $1);
                        state->ast = $$;
                    }
                |
                    {
                        $$ = ccmmc_ast_new(
                            CCMMC_AST_NODE_PROGRAM, state->line_number);
                        state->ast = $$;
                    }
                ;

global_decl_list: global_decl_list global_decl
                    {
                        $$ = ccmmc_ast_append_sibling($1, $2);
                    }
                | global_decl
                    {
                        $$ = $1;
                    }
                ;

global_decl     : type_decl
                    {
                        $$ = $1;
                    }
                | var_decl
                    {
                        $$ = $1;
                    }
                | function_decl
                    {
                        $$ = $1;
                    }
                ;

function_decl   : type ID DL_LPAREN param_list DL_RPAREN DL_LBRACE block DL_RBRACE
                    {
                        $$ = ccmmc_ast_new_decl(
                            CCMMC_KIND_DECL_FUNCTION, state->line_number);
                        CcmmcAst *param_list = ccmmc_ast_new(
                            CCMMC_AST_NODE_PARAM_LIST, state->line_number);
                        ccmmc_ast_append_child(param_list, $4);
                        ccmmc_ast_append_children($$, 4, $1,
                            ccmmc_ast_new_id($2,
                                CCMMC_KIND_ID_NORMAL, state->line_number),
                            param_list, $7);
                    }
                | VOID ID DL_LPAREN param_list DL_RPAREN DL_LBRACE block DL_RBRACE
                    {
                        $$ = ccmmc_ast_new_decl(
                            CCMMC_KIND_DECL_FUNCTION, state->line_number);
                        CcmmcAst *param_list = ccmmc_ast_new(
                            CCMMC_AST_NODE_PARAM_LIST, state->line_number);
                        ccmmc_ast_append_child(param_list, $4);
                        ccmmc_ast_append_children($$, 4,
                            ccmmc_ast_new_id("void",
                                CCMMC_KIND_ID_NORMAL, state->line_number),
                            ccmmc_ast_new_id($2,
                                CCMMC_KIND_ID_NORMAL, state->line_number),
                            param_list, $7);
                    }
                | type ID DL_LPAREN VOID DL_RPAREN DL_LBRACE block DL_RBRACE
                    {
                        $$ = ccmmc_ast_new_decl(
                            CCMMC_KIND_DECL_FUNCTION, state->line_number);
                        CcmmcAst *empty_param_list = ccmmc_ast_new(
                            CCMMC_AST_NODE_PARAM_LIST, state->line_number);
                        ccmmc_ast_append_children($$, 4, $1,
                            ccmmc_ast_new_id($2,
                                CCMMC_KIND_ID_NORMAL, state->line_number),
                            empty_param_list, $7);
                    }
                | VOID ID DL_LPAREN VOID DL_RPAREN DL_LBRACE block DL_RBRACE
                    {
                        $$ = ccmmc_ast_new_decl(
                            CCMMC_KIND_DECL_FUNCTION, state->line_number);
                        CcmmcAst *empty_param_list = ccmmc_ast_new(
                            CCMMC_AST_NODE_PARAM_LIST, state->line_number);
                        ccmmc_ast_append_children($$, 4,
                            ccmmc_ast_new_id("void",
                                CCMMC_KIND_ID_NORMAL, state->line_number),
                            ccmmc_ast_new_id($2,
                                CCMMC_KIND_ID_NORMAL, state->line_number),
                            empty_param_list, $7);
                    }
                | type ID DL_LPAREN  DL_RPAREN DL_LBRACE block DL_RBRACE
                    {
                        $$ = ccmmc_ast_new_decl(
                            CCMMC_KIND_DECL_FUNCTION, state->line_number);
                        CcmmcAst *empty_param_list = ccmmc_ast_new(
                            CCMMC_AST_NODE_PARAM_LIST, state->line_number);
                        ccmmc_ast_append_children($$, 4, $1,
                            ccmmc_ast_new_id($2,
                                CCMMC_KIND_ID_NORMAL, state->line_number),
                            empty_param_list, $6);
                    }
                | VOID ID DL_LPAREN  DL_RPAREN DL_LBRACE block DL_RBRACE
                    {
                        $$ = ccmmc_ast_new_decl(
                            CCMMC_KIND_DECL_FUNCTION, state->line_number);
                        CcmmcAst *empty_param_list = ccmmc_ast_new(
                            CCMMC_AST_NODE_PARAM_LIST, state->line_number);
                        ccmmc_ast_append_children($$, 4,
                            ccmmc_ast_new_id("void",
                                CCMMC_KIND_ID_NORMAL, state->line_number),
                            ccmmc_ast_new_id($2,
                                CCMMC_KIND_ID_NORMAL, state->line_number),
                            empty_param_list, $6);
                    }
                ;

param_list  : param_list DL_COMMA  param
                {
                    $$ = ccmmc_ast_append_sibling($1, $3);
                }
            | param
                {
                    $$ = $1;
                }
            ;

param       : type ID
                {
                    $$ = ccmmc_ast_new_decl(
                        CCMMC_KIND_DECL_FUNCTION_PARAMETER, state->line_number);
                    ccmmc_ast_append_children($$, 2, $1,
                        ccmmc_ast_new_id($2,
                            CCMMC_KIND_ID_NORMAL, state->line_number));
                }
            | type ID dim_fn
                {
                    $$ = ccmmc_ast_new_decl(
                        CCMMC_KIND_DECL_FUNCTION_PARAMETER, state->line_number);
                    ccmmc_ast_append_children($$, 2, $1,
                        ccmmc_ast_append_child(
                            ccmmc_ast_new_id($2,
                                CCMMC_KIND_ID_ARRAY, state->line_number), $3));
                }
            ;

dim_fn      : DL_LBRACK expr_null DL_RBRACK
                {
                    $$ = $2;
                }
            | dim_fn DL_LBRACK expr DL_RBRACK
                {
                    $$ = ccmmc_ast_append_sibling($1, $3);
                }
            ;

expr_null   :expr
                {
                    $$ = $1;
                }
            |
                {
                    $$ = ccmmc_ast_new(CCMMC_AST_NODE_NUL, state->line_number);
                }
            ;

block       : decl_list stmt_list
                {
                    $$ = ccmmc_ast_new(CCMMC_AST_NODE_BLOCK, state->line_number);
                    ccmmc_ast_append_children($$, 2,
                        ccmmc_ast_append_child(
                            ccmmc_ast_new(CCMMC_AST_NODE_VARIABLE_DECL_LIST,
                                state->line_number), $1),
                        ccmmc_ast_append_child(
                            ccmmc_ast_new(CCMMC_AST_NODE_STMT_LIST,
                                state->line_number), $2));
                }
            | stmt_list
                {
                    $$ = ccmmc_ast_new(CCMMC_AST_NODE_BLOCK, state->line_number);
                    ccmmc_ast_append_child($$,
                        ccmmc_ast_append_child(
                            ccmmc_ast_new(CCMMC_AST_NODE_STMT_LIST,
                                state->line_number), $1));
                }
            | decl_list
                {
                    $$ = ccmmc_ast_new(CCMMC_AST_NODE_BLOCK, state->line_number);
                    ccmmc_ast_append_child($$,
                        ccmmc_ast_append_child(
                            ccmmc_ast_new(CCMMC_AST_NODE_VARIABLE_DECL_LIST,
                                state->line_number), $1));
                }
            |   {
                    $$ = ccmmc_ast_new(CCMMC_AST_NODE_BLOCK, state->line_number);
                }
            ;

decl_list   : decl_list decl
                {
                    $$ = ccmmc_ast_append_sibling($1, $2);
                }
            | decl
                {
                    $$ = $1;
                }
            ;

decl        : type_decl
                {
                    $$ = $1;
                }
            | var_decl
                {
                    $$ = $1;
                }
            ;

type_decl   : TYPEDEF type id_list DL_SEMICOL
                {
                    $$ = ccmmc_ast_new_decl(
                        CCMMC_KIND_DECL_TYPE, state->line_number);
                    ccmmc_ast_append_children($$, 2, $2, $3);
                }
            | TYPEDEF VOID id_list DL_SEMICOL
                {
                    $$ = ccmmc_ast_new_decl(
                        CCMMC_KIND_DECL_TYPE, state->line_number);
                    ccmmc_ast_append_children($$, 2,
                        ccmmc_ast_new_id("void",
                            CCMMC_KIND_ID_NORMAL, state->line_number), $3);
                }
            ;

var_decl    : type init_id_list DL_SEMICOL
                {
                    $$ = ccmmc_ast_new_decl(
                        CCMMC_KIND_DECL_VARIABLE, state->line_number);
                    ccmmc_ast_append_children($$, 2, $1, $2);
                }
            | ID id_list DL_SEMICOL
                {
                    $$ = ccmmc_ast_new_decl(
                        CCMMC_KIND_DECL_VARIABLE, state->line_number);
                    ccmmc_ast_append_children($$, 2,
                        ccmmc_ast_new_id($1,
                            CCMMC_KIND_ID_NORMAL, state->line_number), $2);
                }
            ;

type        : INT
                {
                    $$ = ccmmc_ast_new_id("int",
                        CCMMC_KIND_ID_NORMAL, state->line_number);
                }
            | FLOAT
                {
                    $$ = ccmmc_ast_new_id("float",
                        CCMMC_KIND_ID_NORMAL, state->line_number);
                }
            ;

id_list     : ID
                {
                    $$ = ccmmc_ast_new_id($1,
                        CCMMC_KIND_ID_NORMAL, state->line_number);
                }
            | id_list DL_COMMA ID
                {
                    $$ = ccmmc_ast_append_sibling($1,
                        ccmmc_ast_new_id($3,
                            CCMMC_KIND_ID_NORMAL, state->line_number));
                }
            | id_list DL_COMMA ID dim_decl
                {
                    $$ = ccmmc_ast_append_sibling($1,
                        ccmmc_ast_append_child(
                            ccmmc_ast_new_id($3,
                                CCMMC_KIND_ID_ARRAY, state->line_number), $4));
                }
            | ID dim_decl
                {
                    $$ = ccmmc_ast_append_child(
                        ccmmc_ast_new_id($1,
                            CCMMC_KIND_ID_ARRAY, state->line_number), $2);
                }
            ;

dim_decl    : DL_LBRACK cexpr DL_RBRACK
                {
                    $$ = $2;
                }
            | dim_decl DL_LBRACK cexpr DL_RBRACK
                {
                    $$ = ccmmc_ast_append_sibling($1, $3);
                }
            ;

cexpr       : cexpr OP_ADD mcexpr
                {
                    $$ = ccmmc_ast_new_expr(CCMMC_KIND_EXPR_BINARY_OP,
                        CCMMC_KIND_OP_BINARY_ADD, state->line_number);
                    ccmmc_ast_append_children($$, 2, $1, $3);
                } /* This is for array declarations */
            | cexpr OP_SUB mcexpr
                {
                    $$ = ccmmc_ast_new_expr(CCMMC_KIND_EXPR_BINARY_OP,
                        CCMMC_KIND_OP_BINARY_SUB, state->line_number);
                    ccmmc_ast_append_children($$, 2, $1, $3);
                }
            | mcexpr
                {
                    $$ = $1;
                }
            ;

mcexpr      : mcexpr OP_MUL cfactor
                {
                    $$ = ccmmc_ast_new_expr(CCMMC_KIND_EXPR_BINARY_OP,
                        CCMMC_KIND_OP_BINARY_MUL, state->line_number);
                    ccmmc_ast_append_children($$, 2, $1, $3);
                }
            | mcexpr OP_DIV cfactor
                {
                    $$ = ccmmc_ast_new_expr(CCMMC_KIND_EXPR_BINARY_OP,
                        CCMMC_KIND_OP_BINARY_DIV, state->line_number);
                    ccmmc_ast_append_children($$, 2, $1, $3);
                }
            | cfactor
                {
                    $$ = $1;
                }
            ;

cfactor:    CONST
                {
                    $$ = ccmmc_ast_new(
                        CCMMC_AST_NODE_CONST_VALUE, state->line_number);
                    $$->value_const = $1;
                }
            | DL_LPAREN cexpr DL_RPAREN
                {
                    $$ = $2;
                }
            ;

init_id_list: init_id
                {
                    $$ = $1;
                }
            | init_id_list DL_COMMA init_id
                {
                    $$ = ccmmc_ast_append_sibling($1, $3);
                }
            ;

init_id     : ID
                {
                    $$ = ccmmc_ast_new_id($1,
                        CCMMC_KIND_ID_NORMAL, state->line_number);
                }
            | ID dim_decl
                {
                    $$ = ccmmc_ast_append_child(
                        ccmmc_ast_new_id($1,
                            CCMMC_KIND_ID_ARRAY, state->line_number), $2);
                }
            | ID OP_ASSIGN relop_expr
                {
                    $$ = ccmmc_ast_new_id($1,
                        CCMMC_KIND_ID_WITH_INIT, state->line_number);
                    ccmmc_ast_append_child($$, $3);
                }
            ;

stmt_list   : stmt_list stmt
                {
                    $$ = ccmmc_ast_append_sibling($1, $2);
                }
            | stmt
                {
                    $$ = $1;
                }
            ;

stmt        : DL_LBRACE block DL_RBRACE
                {
                    $$ = $2;
                }
            | WHILE DL_LPAREN relop_expr DL_RPAREN stmt
                {
                    $$ = ccmmc_ast_new_stmt(CCMMC_KIND_STMT_WHILE, state->line_number);
                    ccmmc_ast_append_children($$, 2, $3, $5);
                }
            | FOR DL_LPAREN assign_expr_list DL_SEMICOL relop_expr_list DL_SEMICOL assign_expr_list DL_RPAREN stmt
                {
                    $$ = ccmmc_ast_new_stmt(CCMMC_KIND_STMT_FOR, state->line_number);
                    ccmmc_ast_append_children($$, 4, $3, $5, $7, $9);
                }
            | var_ref OP_ASSIGN relop_expr DL_SEMICOL
                {
                    $$ = ccmmc_ast_new_stmt(CCMMC_KIND_STMT_ASSIGN, state->line_number);
                    ccmmc_ast_append_children($$, 2, $1, $3);
                }
            | IF DL_LPAREN relop_expr DL_RPAREN stmt
                {
                    $$ = ccmmc_ast_new_stmt(CCMMC_KIND_STMT_IF, state->line_number);
                    ccmmc_ast_append_children($$, 3, $3, $5,
                        ccmmc_ast_new(CCMMC_AST_NODE_NUL, state->line_number));
                }
            | IF DL_LPAREN relop_expr DL_RPAREN stmt ELSE stmt
                {
                    $$ = ccmmc_ast_new_stmt(CCMMC_KIND_STMT_IF, state->line_number);
                    ccmmc_ast_append_children($$, 3, $3, $5, $7);
                }
            | ID DL_LPAREN relop_expr_list DL_RPAREN DL_SEMICOL
                {
                    $$ = ccmmc_ast_new_stmt(CCMMC_KIND_STMT_FUNCTION_CALL, state->line_number);
                    ccmmc_ast_append_children($$, 2,
                        ccmmc_ast_new_id($1, CCMMC_KIND_ID_NORMAL, state->line_number), $3);
                }
            | DL_SEMICOL
                {
                    $$ = ccmmc_ast_new(CCMMC_AST_NODE_NUL, state->line_number);
                }
            | RETURN DL_SEMICOL
                {
                    $$ = ccmmc_ast_new_stmt(CCMMC_KIND_STMT_RETURN, state->line_number);
                }
            | RETURN relop_expr DL_SEMICOL
                {
                    $$ = ccmmc_ast_new_stmt(CCMMC_KIND_STMT_RETURN, state->line_number);
                    ccmmc_ast_append_child($$, $2);
                }
            ;

assign_expr_list: nonempty_assign_expr_list
                    {
                        $$ = ccmmc_ast_new(
                            CCMMC_AST_NODE_NONEMPTY_ASSIGN_EXPR_LIST, state->line_number);
                        ccmmc_ast_append_child($$, $1);
                    }
                |
                    {
                        $$ = ccmmc_ast_new(CCMMC_AST_NODE_NUL, state->line_number);
                    }
                ;

nonempty_assign_expr_list   : nonempty_assign_expr_list DL_COMMA assign_expr
                               {
                                   $$ = ccmmc_ast_append_sibling($1, $3);
                               }
                            | assign_expr
                               {
                                   $$ = $1;
                               }
                            ;

assign_expr     : var_ref OP_ASSIGN relop_expr
                    {
                        $$ = ccmmc_ast_new_stmt(
                            CCMMC_KIND_STMT_ASSIGN, state->line_number);
                        ccmmc_ast_append_children($$, 2, $1, $3);
                    }
                | relop_expr
                    {
                        $$ = $1;
                    }
                ;

relop_expr      : relop_term
                    {
                        $$ = $1;
                    }
                | relop_expr OP_OR relop_term
                    {
                        $$ = ccmmc_ast_new_expr(CCMMC_KIND_EXPR_BINARY_OP,
                            CCMMC_KIND_OP_BINARY_OR, state->line_number);
                        ccmmc_ast_append_children($$, 2, $1, $3);
                    }
                ;

relop_term      : relop_factor
                    {
                        $$ = $1;
                    }
                | relop_term OP_AND relop_factor
                    {
                        $$ = ccmmc_ast_new_expr(CCMMC_KIND_EXPR_BINARY_OP,
                            CCMMC_KIND_OP_BINARY_AND, state->line_number);
                        ccmmc_ast_append_children($$, 2, $1, $3);
                    }
                ;

relop_factor    : expr
                    {
                        $$ = $1;
                    }
                | expr rel_op expr
                    {
                        $$ = $2;
                        ccmmc_ast_append_children($$, 2, $1, $3);
                    }
                ;

rel_op          : OP_EQ
                    {
                        $$ = ccmmc_ast_new_expr(CCMMC_KIND_EXPR_BINARY_OP,
                            CCMMC_KIND_OP_BINARY_EQ, state->line_number);
                    }
                | OP_GE
                    {
                        $$ = ccmmc_ast_new_expr(CCMMC_KIND_EXPR_BINARY_OP,
                            CCMMC_KIND_OP_BINARY_GE, state->line_number);
                    }
                | OP_LE
                    {
                        $$ = ccmmc_ast_new_expr(CCMMC_KIND_EXPR_BINARY_OP,
                            CCMMC_KIND_OP_BINARY_LE, state->line_number);
                    }
                | OP_NE
                    {
                        $$ = ccmmc_ast_new_expr(CCMMC_KIND_EXPR_BINARY_OP,
                            CCMMC_KIND_OP_BINARY_NE, state->line_number);
                    }
                | OP_GT
                    {
                        $$ = ccmmc_ast_new_expr(CCMMC_KIND_EXPR_BINARY_OP,
                            CCMMC_KIND_OP_BINARY_GT, state->line_number);
                    }
                | OP_LT
                    {
                        $$ = ccmmc_ast_new_expr(CCMMC_KIND_EXPR_BINARY_OP,
                            CCMMC_KIND_OP_BINARY_LT, state->line_number);
                    }
                ;


relop_expr_list : nonempty_relop_expr_list
                    {
                        $$ = ccmmc_ast_new(
                            CCMMC_AST_NODE_NONEMPTY_RELOP_EXPR_LIST, state->line_number);
                        ccmmc_ast_append_child($$, $1);
                    }
                |
                    {
                        $$ = ccmmc_ast_new(CCMMC_AST_NODE_NUL, state->line_number);
                    }
                ;

nonempty_relop_expr_list: nonempty_relop_expr_list DL_COMMA relop_expr
                            {
                                $$ = ccmmc_ast_append_sibling($1, $3);
                            }
                        | relop_expr
                            {
                                $$ = $1;
                            }
                        ;

expr        : expr add_op term
                {
                    $$ = $2;
                    ccmmc_ast_append_children($$, 2, $1, $3);
                }
            | term
                {
                    $$ = $1;
                }
            ;

add_op      : OP_ADD
                {
                    $$ = ccmmc_ast_new_expr(CCMMC_KIND_EXPR_BINARY_OP,
                        CCMMC_KIND_OP_BINARY_ADD, state->line_number);
                }
            | OP_SUB
                {
                    $$ = ccmmc_ast_new_expr(CCMMC_KIND_EXPR_BINARY_OP,
                        CCMMC_KIND_OP_BINARY_SUB, state->line_number);
                }
            ;

term        : term mul_op factor
                {
                    $$ = $2;
                    ccmmc_ast_append_children($$, 2, $1, $3);
                }
            | factor
                {
                    $$ = $1;
                }
            ;

mul_op      : OP_MUL
                {
                    $$ = ccmmc_ast_new_expr(CCMMC_KIND_EXPR_BINARY_OP,
                        CCMMC_KIND_OP_BINARY_MUL, state->line_number);
                }
            | OP_DIV
                {
                    $$ = ccmmc_ast_new_expr(CCMMC_KIND_EXPR_BINARY_OP,
                        CCMMC_KIND_OP_BINARY_DIV, state->line_number);
                }
            ;

factor      : DL_LPAREN relop_expr DL_RPAREN
                {
                    $$ = $2;
                }
            | OP_ADD DL_LPAREN relop_expr DL_RPAREN
                {
                    $$ = ccmmc_ast_new_expr(CCMMC_KIND_EXPR_UNARY_OP,
                        CCMMC_KIND_OP_UNARY_POSITIVE, state->line_number);
                    ccmmc_ast_append_child($$, $3);
                }
            | OP_SUB DL_LPAREN relop_expr DL_RPAREN
                {
                    $$ = ccmmc_ast_new_expr(CCMMC_KIND_EXPR_UNARY_OP,
                        CCMMC_KIND_OP_UNARY_NEGATIVE, state->line_number);
                    ccmmc_ast_append_child($$, $3);
                }
            | OP_NOT DL_LPAREN relop_expr DL_RPAREN
                {
                    $$ = ccmmc_ast_new_expr(CCMMC_KIND_EXPR_UNARY_OP,
                        CCMMC_KIND_OP_UNARY_LOGICAL_NEGATION, state->line_number);
                    ccmmc_ast_append_child($$, $3);
                }
            | CONST
                {
                    $$ = ccmmc_ast_new(CCMMC_AST_NODE_CONST_VALUE, state->line_number);
                    $$->value_const = $1;
                }
            | OP_ADD CONST
                {
                    $$ = ccmmc_ast_new_expr(CCMMC_KIND_EXPR_UNARY_OP,
                        CCMMC_KIND_OP_UNARY_POSITIVE, state->line_number);
                    CcmmcAst *const_node = ccmmc_ast_new(
                        CCMMC_AST_NODE_CONST_VALUE, state->line_number);
                    const_node->value_const = $2;
                    ccmmc_ast_append_child($$, const_node);
                }
            | OP_SUB CONST
                {
                    $$ = ccmmc_ast_new_expr(CCMMC_KIND_EXPR_UNARY_OP,
                        CCMMC_KIND_OP_UNARY_NEGATIVE, state->line_number);
                    CcmmcAst *const_node = ccmmc_ast_new(
                        CCMMC_AST_NODE_CONST_VALUE, state->line_number);
                    const_node->value_const = $2;
                    ccmmc_ast_append_child($$, const_node);
                }
            | OP_NOT CONST
                {
                    $$ = ccmmc_ast_new_expr(CCMMC_KIND_EXPR_UNARY_OP,
                        CCMMC_KIND_OP_UNARY_LOGICAL_NEGATION, state->line_number);
                    CcmmcAst *const_node = ccmmc_ast_new(
                        CCMMC_AST_NODE_CONST_VALUE, state->line_number);
                    const_node->value_const = $2;
                    ccmmc_ast_append_child($$, const_node);
                }
            | ID DL_LPAREN relop_expr_list DL_RPAREN
                {
                    $$ = ccmmc_ast_new_stmt(
                        CCMMC_KIND_STMT_FUNCTION_CALL, state->line_number);
                    ccmmc_ast_append_children($$, 2,
                        ccmmc_ast_new_id($1,
                            CCMMC_KIND_ID_NORMAL, state->line_number), $3);
                }
            | OP_ADD ID DL_LPAREN relop_expr_list DL_RPAREN
                {
                    $$ = ccmmc_ast_new_expr(CCMMC_KIND_EXPR_UNARY_OP,
                        CCMMC_KIND_OP_UNARY_POSITIVE, state->line_number);
                    CcmmcAst *func_node = ccmmc_ast_new_stmt(
                        CCMMC_KIND_STMT_FUNCTION_CALL, state->line_number);
                    ccmmc_ast_append_children(func_node, 2,
                        ccmmc_ast_new_id($2,
                            CCMMC_KIND_ID_NORMAL, state->line_number), $4);
                    ccmmc_ast_append_child($$, func_node);
                }
            | OP_SUB ID DL_LPAREN relop_expr_list DL_RPAREN
                {
                    $$ = ccmmc_ast_new_expr(CCMMC_KIND_EXPR_UNARY_OP,
                        CCMMC_KIND_OP_UNARY_NEGATIVE, state->line_number);
                    CcmmcAst *func_node = ccmmc_ast_new_stmt(
                        CCMMC_KIND_STMT_FUNCTION_CALL, state->line_number);
                    ccmmc_ast_append_children(func_node, 2,
                        ccmmc_ast_new_id($2,
                            CCMMC_KIND_ID_NORMAL, state->line_number), $4);
                    ccmmc_ast_append_child($$, func_node);
                }
            | OP_NOT ID DL_LPAREN relop_expr_list DL_RPAREN
                {
                    $$ = ccmmc_ast_new_expr(CCMMC_KIND_EXPR_UNARY_OP,
                        CCMMC_KIND_OP_UNARY_LOGICAL_NEGATION, state->line_number);
                    CcmmcAst *func_node = ccmmc_ast_new_stmt(
                        CCMMC_KIND_STMT_FUNCTION_CALL, state->line_number);
                    ccmmc_ast_append_children(func_node, 2,
                        ccmmc_ast_new_id($2,
                            CCMMC_KIND_ID_NORMAL, state->line_number), $4);
                    ccmmc_ast_append_child($$, func_node);
                }
            | var_ref
                {
                    $$ = $1;
                }
            | OP_ADD var_ref
                {
                    $$ = ccmmc_ast_new_expr(CCMMC_KIND_EXPR_UNARY_OP,
                        CCMMC_KIND_OP_UNARY_POSITIVE, state->line_number);
                    ccmmc_ast_append_child($$, $2);
                }
            | OP_SUB var_ref
                {
                    $$ = ccmmc_ast_new_expr(CCMMC_KIND_EXPR_UNARY_OP,
                        CCMMC_KIND_OP_UNARY_NEGATIVE, state->line_number);
                    ccmmc_ast_append_child($$, $2);
                }
            | OP_NOT var_ref
                {
                    $$ = ccmmc_ast_new_expr(CCMMC_KIND_EXPR_UNARY_OP,
                        CCMMC_KIND_OP_UNARY_LOGICAL_NEGATION, state->line_number);
                    ccmmc_ast_append_child($$, $2);
                }
            ;

var_ref     : ID
                {
                    $$ = ccmmc_ast_new_id($1,
                        CCMMC_KIND_ID_NORMAL, state->line_number);
                }
            | ID dim_list
                {
                    $$ = ccmmc_ast_new_id($1,
                        CCMMC_KIND_ID_ARRAY, state->line_number);
                    ccmmc_ast_append_child($$, $2);
                }
            ;


dim_list    : dim_list DL_LBRACK expr DL_RBRACK
                {
                    $$ = ccmmc_ast_append_sibling($1, $3);
                }
            | DL_LBRACK expr DL_RBRACK
                {
                    $$ = $2;
                }
            ;

%%

static void ccmmc_parser_error(yyscan_t scanner, CcmmcState *state, const char *mesg)
{
    fprintf(stderr, "Error found in Line \t%zu\tnext token: \t%s\n",
        state->line_number, ccmmc_parser_get_text(scanner));
    exit(1);
}

// vim: set sw=4 ts=4 sts=4 et: