/*
 * JParser.java
 *
 * Created on December 28, 2004, 6:19 PM
 */

package compiler;

import compiler.JLex;
import compiler.Token;
import java.io.IOException;

/**
 *
 * @author  Sarangan Rajamanickam
 */
public class JParser implements compiler.TokenConstants{
    private JLex jlex;
    private Token token;
    
    /** Creates a new instance of JParser */
    public JParser(String filename) {
        jlex=new JLex(filename);
    }
    
    private void error(String errormessage){
        System.out.println("Error!Error!Error!");
        System.out.println(errormessage);
        System.out.println("Error at location: "+(token.position/1000)+"-"+(token.position%1000));
        System.exit(1);
    }
    
    /**
     * Actual Function that starts the parsing
     */
    public AST parse()throws IOException{
        AST tree = null ;
        token=jlex.getToken();
        tree = compilationunit();
        if(token.kind != EOF){
            error("Problem Exists");
        }
        return tree ;
    }
    
    /**
     * Rule 1: <compilationunit> ::= <classdeclaration> | e
     */
    private  CompilationUnit compilationunit()throws IOException{
        CompilationUnit cu = null ;
        ClassDeclaration cd = null ;
        if(token.kind!=EOF){
            cd = classdeclaration();
        }
        else{
            return null ;
        }
        cu = new CompilationUnit(cd);
        System.out.println("The File is parsed.");
        return cu ;
    }
    
    /**
     * Rule 2: <classdeclaration> ::= <public> class identifier <classbody>
     */
    private ClassDeclaration classdeclaration()throws IOException{
        ClassDeclaration cd = null ;
        Terminal pd = null ;
        Terminal cn = null ;
        ClassBody cb = null ;
        
        pd = publicdec();
        if(token.kind==CLASS){
            token=jlex.getToken();
            if(token.kind==IDENTIFIER){
                cn = new Terminal(token.word) ;
                token=jlex.getToken();
                cb = classbody();
            }else{
                error("Mistake in the Name of the Class");
            }
        }else{
            error("No Class in the Program");
        }
        cd = new ClassDeclaration(pd,cn,cb);
        return cd ;
    }
    
    /**
     * Rule 3: <public> ::= public | e
     */
    private Terminal publicdec()throws IOException{
        Terminal pd = null ;
        if(token.kind == PUBLIC){
            pd = new Terminal("public");
            token=jlex.getToken();            
        }
        return pd ;
    }
    
    /**
     * Rule 4: <classbody> ::= { <classbodydeclaration>* }
     */
    private ClassBody classbody()throws IOException{
        ClassBody cb = null ;
        Declarations ds1 = null ;
        Declarations ds2 = null ;
        if(token.kind==LEFTSETBRACKET){
            token=jlex.getToken();
            while(token.kind==PUBLIC || token.kind==PRIVATE || token.kind==PROTECTED){
                ds2 = classbodydeclaration();
                if(ds1 == null){
                    ds1 = ds2 ;
                }else{
                    Declarations temp = ds1 ;
                    ds1 = new SequenceDeclarations(temp,ds2) ;
                }
            }
            if(token.kind==RIGHTSETBRACKET){
                token=jlex.getToken();
            }else{
                error("No '}' End of the Class Body");
            }
        }else{
            error("No '{' Start of the Class Body");
        }
        cb = new ClassBody(ds1);
        return cb;
    }
    
    /**
     * Rule 5: <classbodydeclaration> ::= <modifier> <static> <final> <type> identifier ;
                            |  <modifier> <static> <final> <type> identifier ( <formalparamaterlist> ) <block>
                            |  <modifier> identifier ( <formalparamaterlist> ) <block>
     */
    
    private Declarations classbodydeclaration() throws IOException{
        Static st = null ;
        Type tp = null ;
        Terminal vn = null ;
        Declarations fv = null ;
        Block blk = null ;
        
        Modifier md = modifier();
        VariableDeclarations ds = null ;
        FunctionDeclarations fd = null ;
        if(token.kind!=IDENTIFIER){
            st = staticdec();
            //fn = finaldec();
            tp = type();
            if(token.kind==IDENTIFIER){
                vn = new Terminal(token.word);
                token=jlex.getToken();
                if(token.kind==SEMICOLON){
                    ds = new VariableDeclarations(md,st,tp,vn);
                    token=jlex.getToken();
                    return ds;
                }
                if(token.kind==LEFTBRACES){
                    token=jlex.getToken();
                    fv = formalparameterlist();
                    if(token.kind==RIGHTBRACES){
                        token=jlex.getToken();
                        blk = block();
                        fd = new FunctionDeclarations(md,st,tp,vn,fv,blk,"simplefunction") ;
                        return fd;
                    }else{
                        error("No ')' Closing Right Braces");
                    }
                }else{
                    error("No '(' Opening Left Braces");
                }
            }else{
                error("Requires Identifier as Variable Name");
            }
        }
        
        //This piece is for the 3rd part of the rule.
        if(token.kind==IDENTIFIER){
            vn = new Terminal(token.word);
            token=jlex.getToken();
            if(token.kind==LEFTBRACES){
                token=jlex.getToken();
                fv=formalparameterlist();
                if(token.kind==RIGHTBRACES){
                    token=jlex.getToken();
                    blk = block();
                    fd = new FunctionDeclarations(md,null,null,vn,fv,blk,"constructor");
                    return fd;
                }else{
                    error("No ')' Closing Right Braces");
                }
            }else{
                error("No '(' Opening Left Braces");
            }
        }
        
        //It does not match any of the rule.Automatically call error();
        error("Error After Modifier");
        Declarations temp = null ;
        return temp ;
    }
    
    /**
     * Rule 6: <modifier> ::=    public  |  private |  protected
     */
    private Modifier modifier()throws IOException{
        Modifier md = null ;
        if(token.kind==PUBLIC || token.kind==PRIVATE || token.kind==PROTECTED){
            md = new Modifier(token.word);
            token=jlex.getToken();            
        }else{
            error("Unrecogonised Modifier");
        }
        return md ;
    }
    
    /**
     * Rule 7: <static> ::= static | e
     */
    private Static staticdec()throws IOException{
        Static st = null ;
        if(token.kind==STATIC){
            st = new Static(token.word);
            token=jlex.getToken();            
        }
        return st ;
    }
    
    /**
     * Rule 8: <final> ::= final | e
     */
    /*private void finaldec()throws IOException{
        if(token.kind==FINAL){
            token=jlex.getToken();
            return;
        }else{
            return;
        }
    }*/
    
    /**
     * Rule 9: <formalparameterlist>  ::=    <vardecs> | e
     */
    private Declarations formalparameterlist()throws IOException{
        Declarations vd = null ;
        if(token.kind==RIGHTBRACES){//that means there is no formalparameters
            return vd ;
        }
        vd = vardecs();
        return vd ;
    }
    
    /**
     * Rule 10: <vardecs> ::=    <vardec> (, <vardec> )*
     */
    private Declarations vardecs()throws IOException{
        Declarations vd1 = null ;
        Declarations vd2 = null ;
        vd1 = vardec();
        while(token.kind==COMMA){
            token=jlex.getToken();
            vd2 = vardec();
            Declarations temp = vd1 ;
            vd1 = new SequenceDeclarations(temp,vd2);
        }
        return vd1;
    }
    
    /**
     * Rule 11: <vardec> ::=     <type> identifier
     */
    private VariableDeclarations vardec()throws IOException{
        VariableDeclarations vd = null ;
        
        Type tp = null ;
        Terminal vn = null ;
        tp = type();
        if(token.kind==IDENTIFIER){
            vn = new Terminal(token.word);
            vd = new VariableDeclarations(tp,vn);
            token=jlex.getToken();            
        }else{
            error("No Legal Name for the Identifier");
        }
        return vd;
    }
    
    /**
     * Rule 12: <block>  ::=    {   (<vardec> ; )* <statement> * } //TO BE NOTED
     */
    private Block block()throws IOException{
        Block blk = null ;
        
        Declarations vd1 = null ;
        Declarations vd2 = null ;
        
        Command cmd1 = null ;
        Command cmd2 = null ;
        
        if(token.kind==LEFTSETBRACKET){
            token=jlex.getToken();
            while(token.kind==INT || token.kind==BOOLEAN || token.kind==VOID || token.kind==LEFTBRACES){
                vd2 = vardec();
                if(token.kind==SEMICOLON){
                    token=jlex.getToken();
                }else{
                    error("No Semicolon for the Declaration Termination");
                }
                if(vd1 == null){
                    vd1 = vd2 ;
                }else{
                    Declarations temp=vd1;
                    vd1 = new SequenceDeclarations(temp,vd2);
                }
            }
            while(token.kind==IF || token.kind==WHILE || token.kind==THIS || token.kind==RETURN || token.kind==IDENTIFIER){
                cmd2 = statement();
                if(cmd1 == null ){
                    cmd1 = cmd2;
                }else{
                    Command tempC=cmd1;
                    cmd1=new SequenceCommand(tempC,cmd2);
                }
            }
            if(token.kind==RIGHTSETBRACKET){
                token=jlex.getToken();
                
            }else{
                error("No '}' Closing Bracket for the Block");
            }
        }else{
            error("No '{' Opening Bracket for the Block");
        }
        blk = new Block(vd1,cmd1);
        return blk ;
    }
    
    /**
     * Rule 13: <statement>  ::=   if  ( <expression> ) { <statement> * }
     *                       | if  ( <expression>  ) { <statement>* } else { <statement>* }   
     *                       | while ( <expression> ) { <statement> * }   
     *                       |  <statementwithouttrailingsubstatement>
     */
    private Command statement()throws IOException{
        Command cmd1 = null ;
        Command cmd2 = null ;        
        
        Expression exp = null ;
                
        Command cmd3 = null ;
        Command cmd4 = null ;

        //This piece of code is for first 2 parts of the rule.
        if(token.kind == IF){
            token=jlex.getToken();
            if(token.kind == LEFTBRACES){
                token=jlex.getToken();
                exp = expression();
                if(token.kind == RIGHTBRACES){
                    token=jlex.getToken();
                    if(token.kind == LEFTSETBRACKET){
                        token=jlex.getToken();
                        while(token.kind==IF || token.kind==WHILE || token.kind==IDENTIFIER || token.kind==THIS || token.kind==RETURN){
                            cmd2 = statement();
                            if(cmd1 == null){
                                cmd1=cmd2;
                            }else{
                                Command tempC=cmd1;
                                cmd1=new SequenceCommand(tempC,cmd2);
                            }
                        }
                        if(token.kind == RIGHTSETBRACKET){
                            token=jlex.getToken();
                            if(token.kind != ELSE){
                                IfElseCommand ifelsecommand = new IfElseCommand(exp,cmd1);
                                return ifelsecommand;
                            }
                            else{
                                token=jlex.getToken();
                                if(token.kind == LEFTSETBRACKET){
                                    token=jlex.getToken();
                                    while(token.kind==IF || token.kind==WHILE || token.kind==IDENTIFIER || token.kind==THIS || token.kind==RETURN){
                                        cmd4=statement();
                                        if(cmd3==null){
                                            cmd3=cmd4;
                                        }else{
                                            Command tempCo=cmd3;
                                            cmd3=new SequenceCommand(tempCo,cmd4);
                                        }
                                    }
                                    if(token.kind == RIGHTSETBRACKET){
                                        IfElseCommand ifelsecommand2=new IfElseCommand(exp,cmd1,cmd3);
                                        token=jlex.getToken();
                                        return ifelsecommand2;
                                    }else{
                                        error("No '}' Closing Bracket for the Else part of the loop");
                                    }
                                }else{
                                    error("No '{' Opening Bracket for the Else part of the loop");
                                }
                            }
                        }else{
                            error("No '}' closing Bracket");
                        }
                    }else{
                        error("No '{' opening Bracket for the Body of the loop");
                    }
                }else{
                    error("No ')' closing braces for the expression");
                }
            }else{
                error("No '(' opening braces for the expression");
            }
        }
        
        
        if(token.kind == WHILE){
            token=jlex.getToken();
            if(token.kind == LEFTBRACES){
                token=jlex.getToken();
                exp=expression();
                if(token.kind == RIGHTBRACES){
                    token=jlex.getToken();
                    if(token.kind == LEFTSETBRACKET){
                        token=jlex.getToken();
                        while(token.kind==IF || token.kind==WHILE || token.kind==IDENTIFIER || token.kind==THIS || token.kind==RETURN){
                            cmd2=statement();
                            if(cmd1==null){
                                cmd1=cmd2;
                            }else{
                                Command tempCo2=cmd1;
                                cmd1=new SequenceCommand(tempCo2,cmd2);
                            }
                        }
                        if(token.kind == RIGHTSETBRACKET){
                            WhileCommand whilecommand=new WhileCommand(exp,cmd1);
                            token=jlex.getToken();
                            return whilecommand;
                        }else{
                            error("No '}' right bracket for the loop");
                        }
                    }else{
                        error("No '{' left bracket for the loop");
                    }
                }else{
                    error("No ')' braces for the expression");
                }
            }else{
                error("No '(' braces for the expression");
            }
        }
        
        /* With the above we complete the third rule also. Now we just call the remaining fourth option.
         * If there is an error, say anyother token at this position (say 'public') it will be found at
         * later functions called by statementwithouttrailingsubstatement()
         */        
        cmd1 = statementwithouttrailingsubstatement();
        return cmd1 ;
    }
    
    /**
     * Rule 14: <statementwithouttrailingsubstatement>    ::=     <expressionstatement>
     *                                                      |      <returnstatement>
     */
    private Command statementwithouttrailingsubstatement()throws IOException{
        Command cmd = null ;
        if(token.kind == RETURN){
            cmd = returnstatement();
            return cmd ;
        }
        cmd = expressionstatement();
        return cmd ;
    }
    
    /**
     * Rule 15: <returnstatement>        ::=    return <returntail> ;
     */
    private ReturnCommand returnstatement()throws IOException{
        ReturnCommand rc = null ;
        Expression exp = null ;
        
        if(token.kind==RETURN){
            token=jlex.getToken();
            if(token.kind!=SEMICOLON){//This piece of code is added because if there is not semicolon it must be an expression or error. It helps us to simplify the code in returntail().
                exp = returntail();
            }
            if(token.kind == SEMICOLON){
                rc = new ReturnCommand(exp);
                token=jlex.getToken();                
            }else{
                error("No semicolon in the return statement");
            }
        }else{
            error("No return keyword");
        }
        return rc;
    }

    /**
     * Rule 16: <returntail>  ::= <expression> | e
     */
    private Expression returntail()throws IOException{
        /* Important: This section is executed only if there is an expression. Or else it will
         * not be executed. So it is enough to go directly for expression. It is not necessary
         * to check for 'e'
         */
        Expression exp = expression();
        return exp ;
    }
    
    /**
     * Rule 17: <expressionstatement>    ::=    <statementexpression>  ;
     */
    private Command expressionstatement()throws IOException{
        Command cmd = null ;
        cmd = statementexpression();
        if(token.kind == SEMICOLON){
            token=jlex.getToken();            
        }else{
            error("No semicolon at the end of the statement");
        }
        return cmd ;
    }
    
    /**
     * Rule 18: <statementexpression>    ::=  <statementexpr-prefix> <statementexpr-suffix>
     */
    private Command statementexpression()throws IOException{
        Command cmd = null ;
        String type = null ;
        ThisAndName tan = statementexpressionprefix();
        if(token.kind == EQUALS){
            type = "assign" ;
        }else{
            type="method" ;
        }
        Expression  exp  = statementexpressionsuffix();
        if(type.equals("assign")){
            cmd = new AssignmentCommand(tan,exp);
        }else{
            cmd = new MethodCallCommand(tan,exp) ;
        }
        return cmd;
    }
    
    /**
     * Rule 19: <statementexpr-prefix> ::= <this-and-name>
     */
    private ThisAndName statementexpressionprefix()throws IOException{
        return thisandname();        
    }
    
    /**
     * Rule 20: <statementexpr-suffix>    ::=  <assignment-suffix>
     *                                    |    <methodinvocation-suffix>
     */
    private Expression statementexpressionsuffix()throws IOException{
        Expression exp = null ;
        if(token.kind == LEFTBRACES){
            exp = methodinvocationsuffix();
            return exp;
        }
        exp = assignmentsuffix();
        return exp;
    }
    
    /**
     * Rule 21: <methodinvocation-suffix>    ::=    ( <argumentList> )
     */
    private Expression methodinvocationsuffix()throws IOException{
        Expression exp = null ;
        if(token.kind == LEFTBRACES){
            token=jlex.getToken();
            if(token.kind != RIGHTBRACES){
                exp = argumentlist();
            }
            if(token.kind == RIGHTBRACES){
                token=jlex.getToken();                
            }else{
                error("No ')' at methodinvocation");
            }
        }else{
            error("No '(' at methodinvocation");
        }
        return exp ;
    }
    
    /**
     * Rule 22: <assignment-suffix>        ::=        = <expression>
     */
    private Expression assignmentsuffix()throws IOException{
        Expression exp = null;
        if(token.kind == EQUALS){
            token=jlex.getToken();
            exp = expression();            
        }else{
            error("Missing '='");
        }
        return exp;
    }
    
    /**
     * Rule 23: <argumentlist>  ::=     <expression> ( , <expression> ) * | e
     */
    private Expression argumentlist()throws IOException{
        // Not necessary to check for 'e'. It is already checked at the calling side.
        Expression exp1 = null;
        Expression exp2 = null;
        
        exp1=expression();
        while(token.kind==COMMA){
            token=jlex.getToken();
            exp2 = expression();
            Expression tempE=exp1;
            exp1=new SequenceExpression(tempE,exp2);
        }
        return exp1;
    }
    
    /**
     * Rule 24: <name> ::=    identifier ( . identifier ) *
     */
    private Name name()throws IOException{
        Name nm = null ;
        String temp_ident = null ;
        if(token.kind == IDENTIFIER){
            temp_ident = token.word ;
            token=jlex.getToken();
            while(token.kind == DOT){
                token=jlex.getToken();
                if(token.kind == IDENTIFIER){
                    temp_ident=temp_ident+"."+token.word;
                    token=jlex.getToken();
                }
                else{
                    error("Need legal identifier");
                }
            }            
        }else{
            error("Need legal identifier");
        }
        nm = new Name(temp_ident);
        return nm ;
    }
    
    /**
     * Rule 25: <this-and-name>      ::=  <name> | this.<name>
     */
    private ThisAndName thisandname()throws IOException{
        ThisAndName tan = null ;
        Name nm = null ;
        boolean thisavailability = false ;
        if(token.kind == THIS){
            thisavailability = true ;
            token=jlex.getToken();
            if(token.kind == DOT){
                token=jlex.getToken();
                nm = name();
                tan = new ThisAndName(nm,true);
                return tan;
            }else{
                error("Need '.' after 'this'");
            }
        }
        nm = name();
        tan = new ThisAndName(nm,false);
        return tan;
    }
    
    /**
     * Rule 26: <expression> ::= <cond-or-expr> <cond-or-expr-tail>
     */
    private Expression expression()throws IOException{
        Expression exp1 = null ;
        exp1 = conditionalorexpression();
        return conditionalorexpressiontail(exp1);
    }
    
    /**
     * Rule 27: <cond-or-expr-tail> ::=    || <cond-or-expr> <cond-or-expr-tail> | e
     */
    private Expression conditionalorexpressiontail(Expression exp1)throws IOException{
        if(token.kind == OR){
            token=jlex.getToken();
            Expression exp2 = conditionalorexpression();
            BinaryOpExpression b = new BinaryOpExpression(exp1,new Terminal("||"),exp2);
            Expression ret = conditionalorexpressiontail(b);
            return ret;
        }else{
            return exp1;
        }
    }
    
    /**
     * Rule 28: <cond-or-expr>   ::=  <cond-and-expr> <cond-and-expr-tail>
     */
    private Expression conditionalorexpression()throws IOException{
        Expression exp1 = conditionalandexpression();
        return conditionalandexpressiontail(exp1);        
    }
    
    /**
     * Rule 29: <cond-and-expr-tail> ::= && <cond-and-expr>  <cond-and-expr-tail> | e
     */
    private Expression conditionalandexpressiontail(Expression exp1)throws IOException{
        if(token.kind == AND){
            token=jlex.getToken();
            Expression exp2 = conditionalandexpression();
            BinaryOpExpression b = new BinaryOpExpression(exp1,new Terminal("&&"),exp2);
            Expression ret = conditionalandexpressiontail(b);
            return ret;
        }else{
            return exp1;
        }
    }
    
    /**
     * Rule 30: <cond-and-expr> ::=    <equal-op> <equal-op-tail>
     */
    private Expression conditionalandexpression()throws IOException{
        Expression exp1 = equalop();
        return equaloptail(exp1);        
    }
    
    /**
     * Rule 31: <equal-op-tail> ::=     <equalityoperator> <equal-op> <equal-op-tail> | e
     */
    private Expression equaloptail(Expression exp1)throws IOException{
        if(token.kind == EQUIVALENT || token.kind == NOTEQUIVALENT){
            Terminal op = equalityoperator();
            Expression exp2 = equalop();
            BinaryOpExpression b = new BinaryOpExpression(exp1,op,exp2);
            Expression ret = equaloptail(b);
            return ret;
        }else{
            return exp1;
        }
    }
    
    /**
     * Rule 32: <equalityoperator>  ::=   == | !=
     */
    private Terminal equalityoperator()throws IOException{
        Terminal ter = null;
        if(token.kind == EQUIVALENT || token.kind == NOTEQUIVALENT){
            if(token.kind == EQUIVALENT)
                ter=new Terminal("==");
            else
                ter=new Terminal("!=");
            token=jlex.getToken();            
        }else{
            error("Not a valid equality operator");
        }
        return ter;
    }
    
    /**
     * Rule 33: <equal-op> ::=  <rel-op> <rel-op-tail>
     */
    private Expression equalop()throws IOException{
        Expression exp1 = relop();
        return reloptail(exp1);
    }
    
    /**
     * Rule 34: <rel-op-tail> ::= <relationaloperator>  <rel-op> <rel-op-tail> | e
     */
    private Expression reloptail(Expression exp1)throws IOException{
        if(token.kind == LESSTHAN || token.kind == GREATERTHAN || token.kind == LESSEQUALS || token.kind == GREATEREQUALS){
            Terminal op = relationaloperator() ;
            Expression exp2 = relop() ;
            BinaryOpExpression b = new BinaryOpExpression(exp1,op,exp2);
            Expression ret = reloptail(b);
            return ret;
        }else{
            return exp1;
        }

    }
    
    /**
     * Rule 35: <relationaloperaor> : =  < | > | >= | <=
     */
    private Terminal relationaloperator()throws IOException{
        Terminal ter = null ;
        if(token.kind == LESSTHAN || token.kind == GREATERTHAN || token.kind == LESSEQUALS || token.kind == GREATEREQUALS){
            if(token.kind == LESSTHAN)
                ter = new Terminal("<");
            if(token.kind == GREATERTHAN)
                ter = new Terminal(">");
            if(token.kind == LESSEQUALS)
                ter = new Terminal("<=");
            if(token.kind == GREATEREQUALS)
                ter = new Terminal(">=");
            token=jlex.getToken();            
        }else{
            error("Not a valid relational operator");
        }
        return ter ;
    }
    
    /**
     * Rule 36: <rel-op>   ::=  <add-op>  <add-op-tail>
     */
    private Expression relop()throws IOException{
        Expression exp1 = addop();
        return addoptail(exp1);
    }
    
    /**
     * Rule 37: <add-op-tail>  ::= <additionoperator>  <add-op>  <add-op-tail> | e
     */
    private Expression addoptail(Expression exp1)throws IOException{
        if(token.kind == PLUS || token.kind == MINUS){
            Terminal op = additionoperator() ;
            Expression exp2 = addop() ;
            BinaryOpExpression b = new BinaryOpExpression(exp1,op,exp2) ;
            Expression ret = addoptail(b) ;
            return ret ;
        }else{
            return exp1 ;
        }
    }
    
    /**
     * Rule 38: <additionoperator>  :=  + | -
     */
    private Terminal additionoperator()throws IOException{
        Terminal ter = null ;
        if(token.kind == PLUS || token.kind == MINUS){
            if(token.kind == PLUS)
                ter = new Terminal("+");
            else
                ter = new Terminal("-");
            token=jlex.getToken();
        }else{
            error("Not a valid addition operator");
        }
        return ter ;
    }
    
    /**
     * Rule 39: <add-op>    ::=  <mult-op> <mult-op-tail>
     */
    private Expression addop()throws IOException{
        Expression exp1 = multop();
        return multoptail(exp1);        
    }
    
    /**
     * Rule 40: <mult-op-tail>  ::= <multiplicationoperator> <mult-op> <mult-op-tail>  | e
     */
    private Expression multoptail(Expression exp1)throws IOException{
        if(token.kind == ASTRIEK || token.kind == DIVIDES || token.kind== MODULO){
            Terminal op = multiplicationoperator();
            Expression exp2 = multop();
            BinaryOpExpression b = new BinaryOpExpression(exp1,op,exp2);
            Expression ret = multoptail(b);
            return ret;
        }else{
            return exp1;
        }
    }
    
    /**
     * Rule 41: <multiplicationoperator> ::=  * | / | %
     */
    private Terminal multiplicationoperator()throws IOException{
        Terminal ter = null ;
        if(token.kind == ASTRIEK || token.kind == DIVIDES || token.kind== MODULO){
            if(token.kind == ASTRIEK)
                ter = new Terminal("*");
            if(token.kind == DIVIDES)
                ter = new Terminal("/");
            if(token.kind == MODULO)
                ter = new Terminal("%");
            token=jlex.getToken();            
        }else{
            error("Not a valid multiplication operator");
        }
        return ter;
    }
    
    /**
     * Rule 42: <mult-op> ::=     + <mult-op>
     *                          | -<mult-op>
     *                          | !<mult-op>
     *                          | <primary>
     */
    private Expression multop()throws IOException{
        if(token.kind == PLUS || token.kind == MINUS || token.kind == NOT){
            Terminal op = null ;
            if(token.kind == PLUS)
                op = new Terminal("+");
            if(token.kind == MINUS)
                op = new Terminal("-");
            if(token.kind == NOT)
                op = new Terminal("!");
            token=jlex.getToken();
            Expression exp1 = multop();
            UnaryOpExpression U = new UnaryOpExpression(op,exp1);
            return U;
        }
        return primary();
    }
    
    /**
     * Rule 43: <primary>        ::=         <primarywithliteral>
     *                             |         <primarywithoutliteral>
     */
    private Expression primary()throws IOException{
        Expression exp = null ;
        if(token.kind == INTEGERLITERAL || token.kind == BOOLEANLITERAL || token.kind == NULLLITERAL){
            exp = primarywithliteral();
            return exp;
        }else{
            exp = primarywithoutliteral();
            return exp;
        }
    }
    
    /**
     * Rule 44: <primarywithliteral>    :=    intliteral
     *                               |        boolliteral
     *                               |        nullliteral
     */
    private Expression primarywithliteral()throws IOException{
        Expression exp = null ;
        if(token.kind == INTEGERLITERAL || token.kind == BOOLEANLITERAL || token.kind == NULLLITERAL){
            if(token.kind == INTEGERLITERAL){
                exp = new IntegerLiteralExpression(new Integer(token.val).toString());
            }
            if(token.kind == BOOLEANLITERAL){
                exp = new BooleanLiteralExpression(token.word);
            }
            if(token.kind == NULLLITERAL){
                exp = new NullLiteralExpression(token.word);
            }
            token=jlex.getToken();            
        }else{
            error("Not a valid literal");
        }
        return exp ;
    }
    
    /**
     * Rule 45: <primarywithoutliteral>    :=       ( <expression> )
     *                                     |        <classinstancecreationexpression>
     *                                     |       <this-and-name>
     *                                     |       <this-and-name> ( <argumentList> )
     *                                     |        this
     */
    private Expression primarywithoutliteral()throws IOException{
        Expression temp = null ;
        //This piece is for the first part of the rule.
        if(token.kind == LEFTBRACES){
            token=jlex.getToken();
            Expression exp1 = expression();
            if(token.kind == RIGHTBRACES){
                SimplePWLExpression SPE = new SimplePWLExpression(exp1);
                token=jlex.getToken();
                return SPE;
            }else{
                error("No ')' closing braces");
            }
        }
        
        //This piece is for second part of the rule.
        if(token.kind == NEW){
            ClassInstanceCreationExpression exp1 = classinstancecreationexpression();
            return exp1;
        }
        
        if(token.kind == THIS){
            token=jlex.getToken();
            if(token.kind == DOT){
                token=jlex.getToken();
                Name nm = name();
                ThisAndName tan = new ThisAndName(nm,true);
                if(token.kind != LEFTBRACES){
                    ThisAndNameExpression exp2 = new ThisAndNameExpression(tan);
                    return exp2 ;
                }
                if(token.kind == LEFTBRACES){
                    token=jlex.getToken();
                    Expression exp3 = null ;
                    if(token.kind != RIGHTBRACES){
                       exp3 = argumentlist();
                    }
                    if(token.kind == RIGHTBRACES){
                        MethodCallExpression exp4 = new MethodCallExpression(tan,exp3);
                        token=jlex.getToken();
                        return exp4;//For the fourth part of the rule.
                    }else{
                        error("No ')' braces");
                    }
                }
            }else{
                return new JustThis("this");//For the last part of the rule.
            }
        }
            
            
            
        if(token.kind == IDENTIFIER){
            ThisAndName th = thisandname();
            if(token.kind==LEFTBRACES){
                token=jlex.getToken();
                Expression exp = null;
                if(token.kind != RIGHTBRACES)
                    exp = argumentlist();
                if(token.kind == RIGHTBRACES){
                    MethodCallExpression CT = new MethodCallExpression(th,exp);
                    token=jlex.getToken();
                    return CT;
                }else{
                    error("No ')' right braces");
                }
            }else{
                ThisAndNameExpression STA = new ThisAndNameExpression(th);
                return STA;//For the third part of the rule.
            }
        }

        
        //If the token does not match any it is automatically an error.
        error("Illegal start of the code");
        return temp ;
    }

    /**
     * Rule 46: <classInstancecreationexpression>    ::=    new <name> ( <argumentlist> )
     */
    private ClassInstanceCreationExpression classinstancecreationexpression()throws IOException{
        Name nm = null ;
        Expression exp = null ;
        if(token.kind == NEW){
            token=jlex.getToken();
            nm = name();
            if(token.kind == LEFTBRACES){
                token=jlex.getToken();
                if(token.kind != RIGHTBRACES){
                    exp = argumentlist();
                }
                if(token.kind == RIGHTBRACES){
                    token=jlex.getToken();                    
                }else{
                    error("No matching ')' braces");
                }
            }else{
                error("No starting '(' braces");
            }
        }else{
            error("Requires 'new' keyword");
        }
        return new ClassInstanceCreationExpression(nm,exp);
    }
    
    /**
     * Rule 47: <type>        ::=    <primitivetype>
     *                          |    ( <referencetype> )
     */
    private Type type()throws IOException{
        Type tp = null ;
        if(token.kind == INT || token.kind == BOOLEAN || token.kind ==VOID){
            tp = primitivetype();            
        }else{
            if(token.kind == LEFTBRACES){
                token=jlex.getToken();
                tp = referencetype();
                if(token.kind == RIGHTBRACES){
                    token=jlex.getToken();                    
                }else{
                    error("No matching ')' braces");
                }
            }else{
                error("No '(' left braces");
            }
        }
        return tp ;
    }
    
    /**
     * Rule 48: <primitivetype>    ::=    int
     *                               |    boolean
     *                               |    void
     */
    private PrimitiveType primitivetype()throws IOException{
        PrimitiveType PT = null ;
        Terminal tp = null ;
        
        if(token.kind == INT || token.kind == BOOLEAN || token.kind == VOID){
            tp = new Terminal(token.word);
            token=jlex.getToken();            
        }else{
            error("Illegal start of the code");
        }
        PT = new PrimitiveType(tp);
        return PT ;

    }
    
    /**
     * Rule 49: <referencetype>    ::=  <name>
     */
    private ReferenceType referencetype()throws IOException{
        ReferenceType RT = null ;
        Name nm = null ;
        nm = name();
        RT = new ReferenceType(nm);
        return RT;
    }
Hosted by www.Geocities.ws

1