context: using System;
  using System.IO;
  using LanguageGrammar;
  using System.Collections.Generic;
  
  namespace Compiler
  {
  	public class Parser
  	{
  		Lexer lexer;
  		Grammar g;
  		Stack <int> stackStates;
  		Stack <Symbol> stackSymbols;
  		public SymbolTable symTableTree;
  
  		public Parser ()
  		{
  			string grammar = File.ReadAllText ("./../../language");
  			g = new Grammar (grammar);
  			g.items ();
  			g.createActionTable ();
  			g.createGoToTable ();
  
  			//g.displayStates ();
  			lexer = new Lexer ();
  			stackStates = new Stack<int> ();
  			stackSymbols = new Stack<Symbol> ();
  			stackStates.Push (0);
  
  			symTableTree = new SymbolTable (null);
  		}
  
  		public void startParsing2 ()
  		{
  			char c = (char)Console.Read ();
  			string sym_str = c.ToString ();
  
  			while (true)
  			{
  				ActionTable.Action action = g.actionTable.getAction (sym_str, stackStates.Peek ());
  				if (action.type == ActionTable.Action.ActionType.Shift)
  				{
  					stackStates.Push (action.toState);
  					c = (char)Console.Read ();
  					sym_str = c.ToString ();
  				}
  
  				else if (action.type == ActionTable.Action.ActionType.Reduce)
  				{
  					Production p = action.reduceTo;
  					for (int i = 0; i < p.body.Count; i++)
  					{
  						stackStates.Pop ();
  					}
  
  					stackStates.Push (g.gotoTable.getState (p.head.ToString (), stackStates.Peek ()));
  					stackSymbols.Push (p.head);
  				}
  
  				else if (action.type == ActionTable.Action.ActionType.Accept)
  				{
  					Console.WriteLine ("Accepted");
  					break;
  
  				}
  			}
  		}
  
  		public void startParsing3 ()
  		{
  			while (true)
  			{
  				Token t = lexer.scan ();
  				Console.WriteLine (t.ToString ());
  			}
  		}
  		private ASTNode getNode (Production p, SymbolTable symTable)
  		{
  			if (p.head.ToString () == "type-specifier")
  				return new TypeNode ();
  			if (p.head.ToString () == "arg-list")
  				return new FunctionCallArgument ();
  			if (p.body.Count == 1 && !(p.body [0] is Terminal))
  				return null;
  			if (p.head.ToString () == "param-id")
  				return new IDArrayNode ();
  			if (p.head.ToString () == "var-declaration")
  				return new VariableDeclarationNode ();
  			if (p.head.ToString () == "declarationList")
  				return new DeclarationsListNode ();
  			if (p.head.ToString () == "param-type-list")
  				return new FunctionParamsNode ();
  			if (p.head.ToString () == "param-list")
  				return new FunctionParamsList ();
  			if (p.head.ToString () == "fun-declaration")
  				return new FunctionDeclarationNode ();
  			if (p.head.ToString () == "fun-definition")
  				return new FunctionNode ();
  			if (p.head.ToString () == "compound-stmt")
  				return new CompoundStatementNode ();
  			if (p.head.ToString () == "local-declarations")
  				return new LocalDeclarationsNode ();
  			if (p.head.ToString () == "statement-list")
  				return new StatementListNode ();
  			if (p.head.ToString () == "selection-stmt")
  				return new IfThenNode ();
  			if (p.head.ToString () == "iteration-stmt")
  				return new WhileNode ();
  			if (p.head.ToString () == "return-stmt")
  				return new ReturnNode ();
  			if (p.head.ToString () == "break-stmt")
  				return new BreakNode ();
  			if (p.head.ToString () == "continue-stmt")
  				return new ContinueNode ();
  			if (p.head.ToString () == "expression-stmt")
  				return new ExpressionStmtNode ();
  			if (p.head.ToString () == "expression" ||
  			    p.head.ToString () == "term" ||
  			    p.head.ToString () == "simple-expression" ||
  			    p.head.ToString () == "and-expression" ||
  			    p.head.ToString () == "sum-expression" ||
  			    p.head.ToString () == "unary-expression" ||
  			    p.head.ToString () == "immutable")
  				return new BinaryOperatorNode ();
  
  			if (p.head.ToString () == "unary-rel-expression")
  				return new UnaryOperatorNode ();
  
  			if (p.head.ToString () == "call")
  				return new FunctionCall ();
  
  			if (((p.head.ToString () == "var-decl-id" ||
  			    p.head.ToString () == "mutable")) &&
  			    p.body.Count > 1)
  				return new IDArrayNode ();
  
  			return null;
  		}
  
  		public ASTNode startParsing ()
  		{
  			Token t = lexer.scan ();
  			string sym_str = "";
  			sym_str = t.ToString ();
  			Stack <string> symbolsStack = new Stack<string> ();
  			SymbolTable currentSymTable = symTableTree;
  			Stack <ASTNode> nodeStack = new Stack<ASTNode> ();
  			SymbolTable paramTable = new SymbolTable ();
  
  			if (t!= null && t.tag == Tag.ID)
  			{
  				sym_str = "ID";
  				nodeStack.Push (new IDNode (t.ToString ()));
  			}
  			else if (t != null && t.tag == Tag.Character)
  			{
  				sym_str = "character";
  				nodeStack.Push (new CharacterNode (t.ToString () [0]));
  			}
  			else if (t != null && t.tag == Tag.Number)
  			{
  				sym_str = "num";
  				nodeStack.Push (new NumExprNode (t.ToString ()));
  			}
  
  			else if (t!= null)
  			{
  				sym_str = t.ToString ();
  				nodeStack.Push (new TokenNode (t));
  			}
  
  			while (true)
  			{
  				ActionTable.Action action = null;	
  				action = g.actionTable.getAction (sym_str, stackStates.Peek ());
  
  				if (action == null)
  				{
  					if (t!= null)
  						Console.WriteLine ("Error with action " + sym_str + " " + t.ToString () + " " + stackStates.Peek ());
  					else
  						Console.WriteLine ("Error with action " + sym_str + " " + stackStates.Peek ());
  
  					return null;
  				}
  
  				if (action.type == ActionTable.Action.ActionType.Shift)
  				{
  					stackStates.Push (action.toState);
  					t = lexer.scan ();
  
  					if (t!= null && t.tag == Tag.ID)
  					{
  						sym_str = "ID";
  						nodeStack.Push (new IDNode (t.ToString ()));
  					}
  					else if (t != null && t.tag == Tag.Character)
  					{
  						sym_str = "character";
  						nodeStack.Push (new CharacterNode (t.ToString () [0]));
  					}
  					else if (t != null && t.tag == Tag.String)
  					{
  						sym_str = "string";
  						nodeStack.Push (new StringNode (t.ToString ()));
  					}
  					else if (t != null && (t.tag == Tag.Number || t.tag == Tag.Real))
  					{
  						sym_str = "num";
  						nodeStack.Push (new NumExprNode (t.ToString ()));
  					}
  
  					else if (t!= null)
  					{
  						sym_str = t.ToString ();
  
gt: 						if (t.ToString () != "$")