void Parser:: Statement() {
 
 switch(lookahead) {
 int tempVal;
        case T_M:
        	match(T_M);
        	match(T_OPENBRACKET);
        	Expression();
        	if( evaluate == true) {
        		tempVal= value;
        		}
        	match(T_CLOSEBRACKET);
        	match(T_EQUALS);
        	Expression();
        	if( evaluate == true) {
        		if( (tempVal<0) || (tempVal>99) ) indexError(scanner.lineNumber(), tempVal);
        		m[tempVal] = value;
        		}
        	break;
   		
   		case T_PRINT:
   			match(T_PRINT);
    		Expression();
    		if( evaluate == true ) {
    			std::cout << value << std::endl;
    			}
    		break;
    	
    	default:
    		parseError(scanner.lineNumber(), lookahead);
    		break;  
    	}

}
//  Factor_Tail-> "*" power Factor_Tail |  "/"" power Factor_Tail | Epsolon
void Parser::Factor_Tail()
{
    switch (scanner.nextToken()) {
        case T_MULTIPLY:        // *
        {
            scanner.eatToken(T_MULTIPLY);
            Power();
            if (scanner.nextToken() == T_MULTIPLY || scanner.nextToken() == T_DIVIDE)
                Factor_Tail();
            break;
        }
        case T_DIVIDE:          // /
        {
            scanner.eatToken(T_DIVIDE);
            Power();
            if (scanner.nextToken() == T_MULTIPLY || scanner.nextToken() == T_DIVIDE)
                Factor_Tail();
            break;
        }
        case T_EOF:
            break;  
        default:
        {
            parseError(scanner.lineNumber(), scanner.nextToken());
            break;
        }
    }

}
//Exp_Tail -> "+" Factor Exp_Tail | "-" Factor Exp_Tail | EPSOLON
void Parser::Exp_Tail()
{
    switch (scanner.nextToken())
    {
        case T_PLUS:            // +
        {
            scanner.eatToken(T_PLUS);
            Factor();
            if (scanner.nextToken() == T_PLUS || scanner.nextToken() == T_MINUS)
                Exp_Tail();
            break;
        }
        case T_MINUS:           // -
        {
            scanner.eatToken(T_MINUS);
            Factor();
            if (scanner.nextToken() == T_PLUS || scanner.nextToken() == T_MINUS)
                Exp_Tail();
            break;
        }
        case T_EOF:
            break;  
        default:
        {
            parseError(scanner.lineNumber(), scanner.nextToken());
            break;
        }
    }

}
//  final -> Num | "(" Expression ")" | m [ Expression ]
void Parser:: Final()
{
    switch (scanner.nextToken())
    {
        case T_OPENPAREN:       // (
        {
            scanner.eatToken(T_OPENPAREN);
            
            switch(scanner.nextToken())
            {
                case T_M:
                case T_NUMBER:
                case T_OPENPAREN:
                    Expression();
                case T_EOF:
                    break;
            }



            scanner.eatToken(T_CLOSEPAREN);
            break;
        }
        case T_M:               // m
        {
            scanner.eatToken(T_M);
            scanner.eatToken(T_OPENBRACKET);
            

            switch(scanner.nextToken())
            {
                case T_M:
                case T_NUMBER:
                case T_OPENPAREN:
                    Expression();
                case T_EOF:
                    break;
            }



            scanner.eatToken(T_CLOSEBRACKET);
            break;
        }
        case T_NUMBER:          // num
        {
            scanner.eatToken(T_NUMBER);
            num_parser = scanner.getNumberValue(); 
            break;
        }
        case T_EOF:
            break;  
        default:
        {
            parseError(scanner.lineNumber(), scanner.nextToken());
            break;
        }
    }
}
void Parser::match(token current_token) {
    if(current_token == lookahead) {
      scanner.eatToken(current_token);
      lookahead = scanner.nextToken();
     }
     else {
       mismatchError(scanner.lineNumber(),current_token , lookahead);
       
     }       
}
void Parser::MultDiv_1() {
switch(lookahead) {
int tempVal;
  case T_MULTIPLY:
        	match(T_MULTIPLY);
        	if( evaluate == true) {
        		tempVal = value;
        		}
        	Exp();
        	if( evaluate == true) {
        		value = tempVal * value;
        		}
        	MultDiv_1();
        	break;
   		
   		case T_DIVIDE:
   			match(T_DIVIDE);
   			if( evaluate == true) {
   				tempVal = value;
   				}
    		Exp();
    		if( evaluate == true) {
    			if (value == 0 ) divideError(scanner.lineNumber());
    			value = tempVal / value;
    			}
        	MultDiv_1();
        	break;
    	
    	case T_SEMICOLON:
    	case T_EOF:
    	case T_PLUS:
    	case T_MINUS:
    	case T_CLOSEPAREN:
    	case T_CLOSEBRACKET:
    	  //epsilon
    		break; 
    		
    	default:
    		parseError(scanner.lineNumber(), lookahead);
    		break;
    }
}
//  power_Tail -> "**" final power_Tail | Epsilon
void Parser::Power_Tail()
{
    switch (scanner.nextToken()) {
        case T_POWER:           // **
        {
            scanner.eatToken(T_POWER);
            Final();
            if (scanner.nextToken() == T_POWER)
                Power_Tail();
            break;
        }
        case T_EOF:
            break;  
        default:
        {
            parseError(scanner.lineNumber(), scanner.nextToken());
            break;
        }
    }
}
void Parser::SubAdd_1() {
	
  switch(lookahead) {
  int tempVal;
  int tempVal_2;
        case T_PLUS:
        	match(T_PLUS);
        	if( evaluate == true) {
        		tempVal = value;
        	    }
        	MultDiv();
        	if( evaluate == true) {
        		value = tempVal + value;
        		}
        	SubAdd_1();
        	break;
   		
   		case T_MINUS:
   			match(T_MINUS);
   			if( evaluate == true) {
   				tempVal_2 = value;
   				}
    		MultDiv();
    		if( evaluate == true) {
    			value = tempVal_2 - value;
    			}
        	SubAdd_1();
        	break;
    	
    	case T_SEMICOLON:
    	case T_EOF:
    	case T_CLOSEPAREN:
    	case T_CLOSEBRACKET:
    	  //epsilon
    		break; 
    		
    	default:
    		parseError(scanner.lineNumber(), lookahead);
    		break;
    }
}
void Parser::Exp_1(int *p) {
int tempVal;
int q;
int base;
  if(lookahead == T_POWER) {
    match(T_POWER);
    Paren();
    if (evaluate == true) {
    base = value;
    }
    Exp_1(&q); 
    if(evaluate == true) {
    	*p = pow(base,q);
    }
 }
 else {
   //do nothing
   switch(lookahead) {
   		case T_SEMICOLON:
    	case T_EOF:
    	case T_PLUS:
    	case T_MINUS:
    	case T_MULTIPLY:
    	case T_DIVIDE:
    	case T_CLOSEPAREN:
    	case T_CLOSEBRACKET:
    	  //epsilon
    	break; 
    		
    	default:
    		parseError(scanner.lineNumber(), lookahead);
    		break;
    	}
    	
   if(evaluate == true) {
   	*p = 1; //default power is set to 1
   	
   }
 }
}
//  Term -> ; Statement Term | Epsolon
void Parser::Term()
{
    //cout<< tokenToString(scanner.nextToken()) <<endl;
    switch (scanner.nextToken()) {
        case T_SEMICOLON:       //;
        {
            scanner.eatToken(T_SEMICOLON);
            Statement();
            if (scanner.nextToken() == T_SEMICOLON)
                Term();
            //Term();
            break;
        }
        case T_EOF:
            break;
        default:
        {
            parseError(scanner.lineNumber(), scanner.nextToken());
            break;
        }
    }
}
// Statement  -> "m" "[" Expression "]" "=" Expression | print Expression
void Parser::Statement()
{
    switch(scanner.nextToken())
    {
        case T_M:
        {

            scanner.eatToken(T_M);
            scanner.eatToken(T_OPENBRACKET);


            switch(scanner.nextToken())
            {
                case T_M:
                case T_NUMBER:
                case T_OPENPAREN:
                    Expression();
                case T_EOF:
                    break;
            }

            scanner.eatToken(T_CLOSEBRACKET);
            scanner.eatToken(T_EQUALS);
            

            switch(scanner.nextToken())
            {
                case T_M:
                case T_NUMBER:
                case T_OPENPAREN:
                    Expression();
                case T_EOF:
                    break;
            }


            break;
        }


        case T_PRINT:
        {
            scanner.eatToken(T_PRINT);
            switch(scanner.nextToken())
            {
                case T_M:
                case T_NUMBER:
                case T_OPENPAREN:
                    Expression();
                case T_EOF:
                    break;
            }
            break;
        }
        case T_EOF:
            break;
        default:
        {
            parseError(scanner.lineNumber(), scanner.nextToken());
            break;
        }
  }
}