gt: 						tree = (Nonterminal)stack.get(last_stack_tree_index-1);
context: package com.coducation.smallbasic;
  
  import java.io.BufferedReader;
  import java.io.FileNotFoundException;
  import java.io.FileReader;
  import java.io.IOException;
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Stack;
  
  public class Parser 
  {
  	public Parser(LexerAnalyzer Lexer) throws IOException
  	{
  		stack = new Stack<Stkelem>();
  		Lexing_result = Lexer.Lexing();
  		final_line = Lexer.get_size();
  		String temp_str;
  		
  		Tokens = new ArrayList<Terminal>();
  		Parsing_Table = new ArrayList<String>();
  		State_trans_table = new ArrayList<String>();
  		Grammer_rule = new HashMap<Integer, String>();
  		
  		// initalize Grammer rule and Parsing Table and State trans table...
  		FileReader Gr_fr = new FileReader("sb_grammer_rule.txt");
  		FileReader Pt_fr = new FileReader("sb_parsing_table.txt");
  		FileReader St_fr = new FileReader("sb_state_trans.txt");
  		BufferedReader Gr_br = new BufferedReader(Gr_fr);
  		BufferedReader Pt_br = new BufferedReader(Pt_fr);	
  		BufferedReader St_br = new BufferedReader(St_fr);
  		
  		while((temp_str = Gr_br.readLine()) != null)
  		{
  			String GrlineStr = "";
  			int GrlineNumber = 0;
  			
  			for(int i = 0; i < temp_str.length(); i++)
  				if(temp_str.charAt(i) == ':')
  				{
  					GrlineNumber = atoi(GrlineStr);
  					Grammer_rule.put(GrlineNumber, temp_str.substring(i+1).trim());
  					break;
  				}
  				else
  					GrlineStr = GrlineStr + temp_str.charAt(i);
  		}
  		while((temp_str = Pt_br.readLine()) != null)
  			Parsing_Table.add(temp_str);
  		
  		while((temp_str = St_br.readLine()) != null)
  			State_trans_table.add(temp_str);
  	}
  	
  	@SuppressWarnings("unchecked")
  	public Nonterminal Parsing() throws FileNotFoundException
  	{	
  		// Initialize stack
  		stack.clear();
  		stack.push(new ParseState("[0]"));
  		
  		Object tree = null;
  		int line_index = 0;
  		int tok_index = 0;
  		
  		while(line_index < final_line)
  		{
  			tok_index = 0;
  			while(tok_index < Lexing_result.get(line_index).size())
  			{
  					Tokens.add(Lexing_result.get(line_index).get(tok_index++));
  			}
  			line_index++;
  		}
  		//System.out.println("==================================");
  		
  		// Main Parsing Routine.
  		while(true)
  		{
  			ParseState current_state = (ParseState) stack.lastElement(); // set current_state [0]
  			Terminal a = new Terminal();
  			if(!Tokens.isEmpty())
  				a = Tokens.get(0); // get first SyntaxPair (Only if Tokens isn't empty)
  			
  			if(a.getTokenInfo() == Token.END_OF_TOKENS) // if firstToken is END_OF_TOKENS, File Parsing Success.
  			{
  				// System.out.println("Parsing Success." + " " + (line_index-1) + " lines.");
  				return (Nonterminal)stack.get(1);
  			}
  			
  			String data = Check_state(current_state, a, Tokens);
  			String[] data_arr = data.split(" ");		
  			String order = data_arr[0];
  			String state = "";
  			
  
  			if(!order.equals("LALRAccept"))
  				state = data_arr[1];	
  			
  			switch(order)
  			{
  				case "LALRShift":
  					//System.out.println(order + " " + state);
  					stack.push(a);
  					stack.push(new ParseState(state));
  					Tokens.remove(0);
  					break;
  				case "LALRReduce":
  				{	
  					//System.out.println(order + " " + state);
  					int state_num = atoi(state);
  
  					String[] reduce_arr = Grammer_rule.get(state_num).split("->"); // lhs, rhs split.
  					String lhs = reduce_arr[0].trim();
  					String rhs;
  					int count;
  					
  					if(!(reduce_arr.length == 1)) // -> "empty"
  					{
  						rhs = reduce_arr[1].trim();
  						count = rhs.split(" ").length; 	// *2 => pop count.
  					}
  					else
  					{
  						rhs = "";
  						count = 0;
  					}
  					
  					int last_stack_tree_index = stack.size()-1; // This value indicate last "Tree" Position at the stack.
  					
  					if(Grammer_rule.get(state_num).equals("Prog -> MoreThanOneStmt"))
  					{
  						
  					}
  					else if(Grammer_rule.get(state_num).equals("Stmt -> ExprStatement"))
  					{	
  						tree = stack.get(last_stack_tree_index-1);
  						
  						if(tree instanceof Nonterminal)
  							tree = ((Nonterminal) tree).getTree();
  					}
  					else if(Grammer_rule.get(state_num).equals("Stmt -> While Expr CRStmtCRs EndWhile")) // case While
  					{
  						Nonterminal sub_tree1 = (Nonterminal)stack.get(last_stack_tree_index-3); // Block
  						Nonterminal sub_tree2 = (Nonterminal)stack.get(last_stack_tree_index-5); // CondExpr
  						
  						WhileStmt whileStmt = new WhileStmt((Expr)sub_tree2.getTree(), (Stmt)sub_tree1.getTree());
  						Terminal whileKeyword = (Terminal)stack.get(last_stack_tree_index-7);
  						whileStmt.at(whileKeyword.getLine_index(), whileKeyword.getCh_index());
  						tree = whileStmt;
  			
  					}
  					else if(Grammer_rule.get(state_num).equals("Stmt -> ID :")) // case Label
  					{
  						Terminal sub_tree1 = (Terminal)stack.get(last_stack_tree_index-3);
  						Label label = new Label(sub_tree1.getSyntax().toUpperCase());
  						label.at(sub_tree1.getLine_index(), sub_tree1.getCh_index());
  						tree = label;
  						
  					}
  					else if(Grammer_rule.get(state_num).equals("Stmt -> Goto ID")) // case Goto
  					{
  						Terminal sub_tree1 = (Terminal)stack.get(last_stack_tree_index-1);
  						GotoStmt gotostmt = new GotoStmt(sub_tree1.getSyntax().toUpperCase());
  						gotostmt.at(sub_tree1.getLine_index(), sub_tree1.getCh_index());
  						tree = gotostmt;
  					}
  					else if(Grammer_rule.get(state_num).equals("Stmt -> For ID = Expr To Expr OptStep CRStmtCRs EndFor")) // case For
  					{
  						Nonterminal sub_tree1 = (Nonterminal)stack.get(last_stack_tree_index-3);
  						Nonterminal sub_tree2 = (Nonterminal)stack.get(last_stack_tree_index-5);
  						Nonterminal sub_tree3 = (Nonterminal)stack.get(last_stack_tree_index-7);
  						Nonterminal sub_tree4 = (Nonterminal)stack.get(last_stack_tree_index-11);
  						Terminal sub_tree5 = (Terminal)stack.get(last_stack_tree_index-15);
  						
  						Terminal sub_tree6 = (Terminal)stack.get(last_stack_tree_index-17);
  						
  						Var var = new Var(sub_tree5.getSyntax().toUpperCase()); 
  						var.at(sub_tree5.getLine_index(), sub_tree5.getCh_index());
  						ForStmt forstmt = new ForStmt(
  												var, 
  												(Expr)sub_tree4.getTree(), 
  												(Expr)sub_tree3.getTree(), 
  												(Expr)sub_tree2.getTree(), 
  												(Stmt)sub_tree1.getTree());
  						
  						forstmt.at(sub_tree6.getLine_index(), sub_tree6.getCh_index());
  						
  						tree = forstmt;
  					}
  					else if(Grammer_rule.get(state_num).equals("Stmt -> Sub ID CRStmtCRs EndSub")) // case SubRoutine Definition.
  					{
  						Nonterminal sub_tree1 = (Nonterminal)stack.get(last_stack_tree_index-3);
  						Terminal sub_tree2 = (Terminal)stack.get(last_stack_tree_index-5);
  						Terminal sub_tree3 = (Terminal)stack.get(last_stack_tree_index-7);
  						
  						SubDef subdef = new SubDef(sub_tree2.getSyntax().toUpperCase(), (Stmt)sub_tree1.getTree());
  						subdef.at(sub_tree3.getLine_index(), sub_tree3.getCh_index());
  						tree = subdef;
  					}
  					else if(Grammer_rule.get(state_num).equals("Stmt -> If Expr Then CRStmtCRs MoreThanZeroElseIf")) // case If
  					{
  						Nonterminal sub_tree1 = (Nonterminal)stack.get(last_stack_tree_index-1);
  						Nonterminal sub_tree2 = (Nonterminal)stack.get(last_stack_tree_index-3);
  						Nonterminal sub_tree3 = (Nonterminal)stack.get(last_stack_tree_index-7);
  						Terminal ifKeyword = (Terminal)stack.get(last_stack_tree_index-9);
  						
  						IfStmt ifStmt = new IfStmt((Expr)sub_tree3.getTree(), (Stmt)sub_tree2.getTree(), (Stmt)sub_tree1.getTree());
  						ifStmt.at(ifKeyword.getLine_index(), ifKeyword.getCh_index());
  						tree = ifStmt; 
  					}
  					else if(Grammer_rule.get(state_num).equals("MoreThanZeroElseIf -> OptionalElse")) // Else, or not.
  					{
  						tree = stack.get(last_stack_tree_index-1);
  						
  						if(tree instanceof Nonterminal)
  							tree = ((Nonterminal) tree).getTree();
  					}
  					else if(Grammer_rule.get(state_num).equals("MoreThanZeroElseIf -> ElseIf Expr Then CRStmtCRs MoreThanZeroElseIf")) // case ElseIf
  					{
  						Nonterminal sub_tree1 = (Nonterminal)stack.get(last_stack_tree_index-1);
  						Nonterminal sub_tree2 = (Nonterminal)stack.get(last_stack_tree_index-3);
  						Nonterminal sub_tree3 = (Nonterminal)stack.get(last_stack_tree_index-7);
  						Terminal sub_tree4 = (Terminal)stack.get(last_stack_tree_index-9);
  						
  						IfStmt ifstmt = new IfStmt((Expr)sub_tree3.getTree(), (Stmt)sub_tree2.getTree(), (Stmt)sub_tree1.getTree());
  						ifstmt.at(sub_tree4.getLine_index(), sub_tree4.getCh_index());
  						tree = ifstmt;
  					}
  					else if(Grammer_rule.get(state_num).equals("OptionalElse -> EndIf")) // not Else
  					{
  						tree = null;
  					}
  					else if(Grammer_rule.get(state_num).equals("OptionalElse -> Else CRStmtCRs EndIf")) // Else
  					{
  						Nonterminal sub_tree1 = (Nonterminal)stack.get(last_stack_tree_index-3);
  						
  						tree = (Stmt)sub_tree1.getTree();
  					}
  					else if(Grammer_rule.get(state_num).equals("ExprStatement -> ID = Expr")) // Assign
  					{
  						Nonterminal sub_tree1 = (Nonterminal)stack.get(last_stack_tree_index-1);
  						Terminal sub_tree2 = (Terminal)stack.get(last_stack_tree_index-5);
  						
  						Var var = new Var(sub_tree2.getSyntax().toUpperCase());
  						var.at(sub_tree2.getLine_index(), sub_tree2.getCh_index());
  						Assign assign = new Assign(var, (Expr)sub_tree1.getTree());	
  						assign.at(sub_tree2.getLine_index(), sub_tree2.getCh_index());
  						tree = assign;
  					}
  					else if(Grammer_rule.get(state_num).equals("ExprStatement -> ID . ID = Expr")) // Property Assign
  					{
  						Nonterminal sub_tree1 = (Nonterminal)stack.get(last_stack_tree_index-1);
  						Terminal sub_tree2 = (Terminal)stack.get(last_stack_tree_index-5);
  						Terminal sub_tree3 = (Terminal)stack.get(last_stack_tree_index-9);
  						
  						PropertyExpr propertyExpr = new PropertyExpr(sub_tree3.getSyntax(), sub_tree2.getSyntax()); 
  						propertyExpr.at(sub_tree3.getLine_index(), sub_tree3.getCh_index());
  						Assign assign = new Assign(propertyExpr, (Expr)sub_tree1.getTree());
  						assign.at(sub_tree3.getLine_index(), sub_tree3.getCh_index());
  						tree = assign;
  					}
  					else if(Grammer_rule.get(state_num).equals("ExprStatement -> ID . ID ( Exprs )")) // MethodCallExprStmt
  					{
  						Nonterminal sub_tree1 = (Nonterminal)stack.get(last_stack_tree_index-3);
  						Terminal sub_tree2 = (Terminal)stack.get(last_stack_tree_index-7);
  						Terminal sub_tree3 = (Terminal)stack.get(last_stack_tree_index-11);
  		
  						MethodCallExpr methodCallExpr = new MethodCallExpr(sub_tree3.getSyntax(), sub_tree2.getSyntax(),(ArrayList<Expr>)sub_tree1.getTree());
  						methodCallExpr.at(sub_tree3.getLine_index(), sub_tree3.getCh_index());
  						ExprStmt exprstmt = new ExprStmt(methodCallExpr);
  						exprstmt.at(sub_tree3.getLine_index(), sub_tree3.getCh_index());
  						tree = exprstmt;
  					}
  					else if(Grammer_rule.get(state_num).equals("ExprStatement -> ID ( )")) // SubRoutineCallExprStmt
  					{
  						Terminal sub_tree1 = (Terminal)stack.get(last_stack_tree_index-5);
  						SubCallExpr subcallexpr = new SubCallExpr(sub_tree1.getSyntax().toUpperCase());
  						subcallexpr.at(sub_tree1.getLine_index(), sub_tree1.getCh_index());
  						tree = subcallexpr;
  					}
  					else if(Grammer_rule.get(state_num).equals("ExprStatement -> ID Idxs = Expr")) // Array Assign
  					{
  						Nonterminal sub_tree1 = (Nonterminal)stack.get(last_stack_tree_index-1);
  						Terminal sub_tree2 = (Terminal)stack.get(last_stack_tree_index-7);
  						
  						Nonterminal sub_tree_idxs = (Nonterminal)stack.get(last_stack_tree_index-5);
  						
  						//Array array = new Array( sub_tree2.getSyntax(), index_list);
  						Array array = (Array)sub_tree_idxs.getTree();
  						array.setVar( sub_tree2.getSyntax().toUpperCase() );
  						
  						Assign assign =  new Assign((Expr)array, (Expr)sub_tree1.getTree());
  						assign.at(sub_tree2.getLine_index(), sub_tree2.getCh_index());
  						tree = assign;
  					}
  					else if(Grammer_rule.get(state_num).equals("CRStmtCRs -> CR TheRest")) // CRStmt => blockStmt
  					{
  						Nonterminal sub_tree1 = (Nonterminal)stack.get(last_stack_tree_index-1);
  						
  						ArrayList<Stmt> ALStmt = (ArrayList<Stmt>)sub_tree1.getTree();
  						if (ALStmt == null) {
  							ALStmt = new ArrayList<Stmt>();
  							tree = new BlockStmt(ALStmt);  // No line no & char pos because of the empty block
  						}
  						else {
  							BlockStmt blockstmt = new BlockStmt(ALStmt);
  							Stmt fststmt = ALStmt.get(0);
  							blockstmt.at(fststmt.lineno(), fststmt.charat());
  							tree = blockstmt;
  						}
  					}
  					else if(Grammer_rule.get(state_num).equals("TheRest ->")) // empty
  					{
  						tree = null;				
  					}
  					else if(Grammer_rule.get(state_num).equals("TheRest -> Stmt CR TheRest")) // At least One Stmt
  					{
  						Nonterminal sub_tree1 = (Nonterminal)stack.get(last_stack_tree_index-1);
  						Nonterminal sub_tree2 = (Nonterminal)stack.get(last_stack_tree_index-5);
  						
  						ArrayList<Stmt> ALStmt = new ArrayList<Stmt>();
  						
  						if(sub_tree1.getTree() != null)
  							ALStmt = (ArrayList<Stmt>)sub_tree1.getTree();
  						
  						ALStmt.add(0, (Stmt)sub_tree2.getTree());
  						tree = ALStmt;							
  					}
  					else if(Grammer_rule.get(state_num).equals("MoreThanOneStmt -> Stmt"))
  					{
  						tree = (Nonterminal)stack.get(last_stack_tree_index-1);
  						
  						Nonterminal sub_tree1 = (Nonterminal)stack.get(last_stack_tree_index-1);
  							
  						
  						ArrayList<Stmt> ALStmt = new ArrayList<Stmt>();
  						Stmt fststmt = (Stmt)sub_tree1.getTree();
  						ALStmt.add(fststmt);
  						BlockStmt blockstmt = new BlockStmt(ALStmt);
  						blockstmt.at(fststmt.lineno(), fststmt.charat());
  						tree = blockstmt;
  					}
  					else if(Grammer_rule.get(state_num).equals("MoreThanOneStmt -> Stmt CR MoreThanOneStmt"))
  					{
  						Nonterminal sub_tree1 = (Nonterminal)stack.get(last_stack_tree_index-1);
  						Nonterminal sub_tree2 = (Nonterminal)stack.get(last_stack_tree_index-5);
  						
  						BlockStmt block = (BlockStmt)sub_tree1.getTree();
  						ArrayList<Stmt> ALStmt = block.getAL();
  						Stmt fststmt = (Stmt)sub_tree2.getTree();
  						ALStmt.add(0, fststmt);
  
  						BlockStmt blockstmt = new BlockStmt(ALStmt);
  						blockstmt.at(fststmt.lineno(), fststmt.charat());
  						tree = blockstmt;
  					}
  					else if(Grammer_rule.get(state_num).equals("OptStep ->"))
  					{
  						tree = new Lit(1);
  					}
  					else if(Grammer_rule.get(state_num).equals("OptStep -> Step Expr"))
  					{
  						tree = stack.get(last_stack_tree_index-1);
  						
  						if(tree instanceof Nonterminal)
  						{
  							tree = ((Nonterminal) tree).getTree();
  						}
  					}
  					else if(Grammer_rule.get(state_num).equals("Expr -> CondExpr"))
  					{
  						tree = stack.get(last_stack_tree_index-1);
  						
  						if(tree instanceof Nonterminal)
  							tree = ((Nonterminal) tree).getTree();
  					}
  					else if(Grammer_rule.get(state_num).equals("Exprs ->"))
  					{
  						tree = null;
  					}
  					else if(Grammer_rule.get(state_num).equals("Exprs -> MoreThanOneExpr"))
  					{
  						tree = stack.get(last_stack_tree_index-1);
  						
  						if(tree instanceof Nonterminal)
  							tree = ((Nonterminal) tree).getTree();
  					}
  					else if(Grammer_rule.get(state_num).equals("MoreThanOneExpr -> Expr"))
  					{
  