package ppdz;
import java_cup.runtime.*;
import java.io.*;


parser code {:
        
    // glavni program, kao metod klase parser
    public static void main(String args[]) throws Exception {
        FileReader r = new FileReader(args[0]);
        Yylex skener = new Yylex(r);
        parser p = new parser(skener);
        Symbol s = p.parse();  //pocetak parsiranja
    }
  
    /***********************************************************************
    * slede redefinisani metodi za prijavu gresaka radi izmene teksta poruke
    ***********************************************************************/ 
    public void report_fatal_error(String message, Object   info) throws java.lang.Exception {
      done_parsing();
      report_error(message, info);
    }
  
    public void syntax_error(Symbol cur_token) {
        report_error("\nSintaksna greska", cur_token);
    }
  
    public void unrecovered_syntax_error(Symbol cur_token) throws java.lang.Exception {
        report_fatal_error("Fatalna greska, parsiranje se ne moze nastaviti", cur_token);
    }

  public void report_error(String message, Object info)
    {
      System.err.print(message);
      System.err.flush();
      if (info instanceof Symbol)
          System.err.println(" na liniji " + ((Symbol)info).left);
      else System.err.println("");
    }

:}

terminal PLUS, MINUS, TIMES, DIV;
terminal EQUAL, SEMI, COMMA, LPAREN;
terminal RPAREN, LSQUARE, RSQUARE, LBRACE, RBRACE, CLASS;
terminal PRINT, RETURN, VOID, FINAL;
terminal Integer NUMBER;
terminal Character CHARCONST;
terminal String IDENT;

non terminal program, declaration_list, method_declaration_list;
non terminal var_dec, rhs, var_list, var_part, const_dec;
non terminal method_dec, form_pars, stmt_list, parameter;
non terminal statement, designator, expr, act_pars, local_var_list;
non terminal addop, mulop, expr_list, term_list, term;
non terminal factor, factor_list, parameter_list, declaration_part;
non terminal type;
non terminal ident_expr_list, prog_id, return_type_ident;

program ::= CLASS prog_id declaration_list LBRACE method_declaration_list RBRACE;

prog_id ::= IDENT:id {: System.out.println("Pronadjena glavna klasa: "+id+" na liniji "+idleft); :};

declaration_list ::= declaration_list declaration_part
         |
         /* epsilon */;

declaration_part ::= const_dec 
                 |
                 var_dec;
      
const_dec ::= FINAL type IDENT EQUAL rhs SEMI;

type ::= IDENT;

rhs ::= NUMBER 
    | 
    CHARCONST; 

var_dec ::= type var_list SEMI;

var_list ::= var_list COMMA var_part 
     | 
     var_part;

var_part ::= IDENT  
     |
     IDENT: id LSQUARE RSQUARE;

local_var_list ::= local_var_list var_dec
               |
               /* epsilon */;

method_declaration_list ::= method_declaration_list method_dec
                |
                /* epsilon */;

return_type_ident ::= type IDENT 
            | 
            VOID IDENT;

method_dec ::= return_type_ident LPAREN form_pars RPAREN local_var_list LBRACE stmt_list RBRACE;
           
form_pars ::= parameter_list
          |
          /* epsilon */;
    
parameter_list ::= parameter_list COMMA parameter
               |
               parameter;

parameter ::= type IDENT
        | 
      type IDENT LSQUARE RSQUARE;


stmt_list ::= stmt_list statement
          |
          /* epsilon */;

statement ::= designator EQUAL:l expr SEMI 
                 {: System.out.println("Pronadjen izraz dodele na liniji "+lleft); :}
          |
          designator LPAREN:l RPAREN SEMI      
                 {: System.out.println("Pronadjen poziv metode bez argumenata na liniji "+lleft); :} 
          |
          designator LPAREN:l act_pars RPAREN SEMI
                 {: System.out.println("Pronadjen poziv metode sa argumentima na liniji "+lleft); :}
          |
          RETURN:l SEMI
                 {: System.out.println("Pronadjen prazan return iskaz na liniji "+lleft); :}
          |
          RETURN:l expr SEMI
                 {: System.out.println("Pronadjen return iskaz na liniji "+lleft); :}
          |
          PRINT:l LPAREN expr RPAREN SEMI
                 {: System.out.println("Pronadjen poziv metode print na liniji "+lleft); :};

designator ::= ident_expr_list;

ident_expr_list ::= ident_expr_list  LSQUARE expr RSQUARE
                |
                IDENT;

addop ::= PLUS 
      | 
      MINUS;

mulop ::= TIMES 
      | 
       DIV;

act_pars ::= expr_list;

expr_list ::= expr_list COMMA expr 
          |
          expr;

expr ::= term_list;
    
term_list ::= term_list addop term
          |
          term;

term ::= factor_list;

factor_list ::= factor_list mulop factor
            |
            factor
            |
            MINUS factor;

factor ::= designator LPAREN act_pars RPAREN   
           |                                                                              
           designator                           
           |
           designator LPAREN RPAREN      
           |
           NUMBER             
           |
           CHARCONST     
           |
           LPAREN expr RPAREN; 
