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


parser code {:

public java_cup.runtime.Symbol scan() throws java.lang.Exception {

		Symbol simbol=getScanner().next_token();
		if (simbol!=null) {
			while (simbol.sym==sym.INVALID) { 
				System.out.println("LEKSICKA GRESKA: "+simbol.value+"  !!!");
                        simbol=getScanner().next_token(); 
			}
			return (simbol!=null) ? simbol: new Symbol (EOF_sym());
		} else return new Symbol(EOF_sym());

}

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();
}

  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("Parsiranje se ne moze nastaviti", cur_token);
    }

:}


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, declaration_part, const_dec;
non terminal var_dec, type, rhs, var_list, var_part, prog_id;
non terminal method_dec, return_type, form_pars, stmt_list, parameter, parameter_list;
non terminal statement, designator, expr, act_pars, local_field_list;
non terminal ident_expr_list, addop, mulop, expr_list, term_list, term, factor_list;
non terminal factor;



program ::= CLASS prog_id declaration_list LBRACE method_declaration_list RBRACE
	   	| CLASS prog_id LBRACE method_declaration_list RBRACE
	   	| CLASS prog_id LBRACE RBRACE
	   	| CLASS prog_id declaration_list LBRACE RBRACE;
	

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

declaration_list ::= declaration_list declaration_part
			   |
			   declaration_part;


declaration_part ::= const_dec SEMI
	               |
	               var_dec SEMI;

			
const_dec ::= FINAL type IDENT EQUAL rhs;

			
type ::= IDENT;


rhs ::= NUMBER 
	  | 
	  CHARCONST;


var_dec ::=	type var_list;


var_list ::= var_list COMMA var_part 
		 | 
 		 var_part;

		
var_part ::= IDENT 
		 |
		 IDENT LSQUARE RSQUARE;


local_field_list ::= local_field_list var_dec SEMI
	         	   |
	               var_dec SEMI;


method_declaration_list ::= method_declaration_list method_dec
		      	    |
		      	    method_dec;


return_type	::= type 
		    | 
		    VOID;

 
method_dec ::= return_type IDENT LPAREN form_pars RPAREN local_field_list LBRACE stmt_list RBRACE
	         |
	         return_type IDENT LPAREN form_pars RPAREN LBRACE stmt_list RBRACE  
               |
	         return_type IDENT LPAREN form_pars RPAREN local_field_list LBRACE RBRACE
	         |
	         return_type IDENT LPAREN form_pars RPAREN LBRACE RBRACE
	         |
	         return_type IDENT LPAREN RPAREN local_field_list LBRACE stmt_list RBRACE
	         |
	         return_type IDENT LPAREN RPAREN LBRACE stmt_list RBRACE
	         |
	         return_type IDENT LPAREN RPAREN local_field_list LBRACE RBRACE
	         |
	         return_type IDENT LPAREN RPAREN LBRACE RBRACE;

 
form_pars ::= parameter parameter_list
	        |
	        parameter;

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


parameter_list ::= parameter_list COMMA parameter
	             |
	             COMMA parameter;


stmt_list ::= stmt_list statement
	        |
	        statement;

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

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;       







 



