/// <summary>
 /// Process Parameters
 /// </summary>
 /// <param name="identifierRecord"></param>
 /// <param name="procedureRecord"></param>
 /// <param name="parameterList"></param>
 internal void processParameters(IdentifierRecord identifierRecord, ref MethodRecord procedureRecord, 
     ref List<Parameter> parameterList)
 {
     if (identifierRecord.symbol is ProcedureSymbol)
     {
         ProcedureSymbol pSymbol = identifierRecord.symbol as ProcedureSymbol;
         procedureRecord.parameterList = pSymbol.paramList;
         parameterList = new List<Parameter>(procedureRecord.parameterList);
     }
 }
        /// <summary>
        /// Generates code for loading a delegate
        /// </summary>
        /// <param name="methodRecord"></param>
        internal void GenerateLoadDelegate(MethodRecord methodRecord)
        {
            SymbolTable table = symbolTableStack.Peek();

            cilOutput.WriteLine("  ldloc.0");
            cilOutput.WriteLine("  ldfld\tclass Program/" + methodRecord.name +
                "Delegate " + table.cilScope + "/c__" + table.name + "::d__" +
                methodRecord.name + Environment.NewLine);
        }
 /// <summary>
 /// Process a method
 /// </summary>
 /// <param name="identifierRecord"></param>
 /// <param name="methodRecord"></param>
 internal void ProcessMethod(IdentifierRecord identifierRecord,ref MethodRecord methodRecord)
 {
     if (identifierRecord.symbol.symbolType == SymbolType.FunctionSymbol ||
         identifierRecord.symbol.symbolType == SymbolType.ProcedureSymbol)
     {
         methodRecord.name = identifierRecord.lexeme;
         methodRecord.returnType = identifierRecord.symbol.variableType;
         methodRecord.symbolType = identifierRecord.symbol.symbolType;
     }
 }
        /// <summary>
        /// inserts symbols into the symboltable
        /// </summary>
        /// <param name="idRecordList"></param>
        /// <param name="typeRecord"></param>
        public void SymbolTableInsert(MethodRecord methodRecord)
        {
            delegateList.Add(methodRecord);

            Symbol symbol = null;
            switch (methodRecord.symbolType)
            {
                case SymbolType.ProcedureSymbol:
                    symbol = new ProcedureSymbol(methodRecord.name, SymbolType.ProcedureSymbol,
                        nextLabel, methodRecord.parameterList);
                    break;
                case SymbolType.FunctionSymbol:
                    symbol = new FunctionSymbol(methodRecord.name,SymbolType.FunctionSymbol,
                        nextLabel,methodRecord.parameterList,methodRecord.returnType);
                    break;
            }

            symbolTableStack.Peek().Insert(symbol);
        }
        /// <summary>
        /// Generates code for calling a method
        /// </summary>
        internal void GenerateCallMethod(MethodRecord methodRecord)
        {
            string parameterString = string.Empty;
            if (methodRecord.symbolType == SymbolType.FunctionSymbol ||
                methodRecord.symbolType == SymbolType.ProcedureSymbol)
            {
                parameterString = GenerateParameterString(methodRecord.parameterList, false);

                cilOutput.WriteLine("  callvirt\tinstance " + Enumerations.GetDescription<VariableType>
                    (methodRecord.returnType) + " Program/" + methodRecord.name +
                "Delegate::Invoke(" + parameterString + ")" + Environment.NewLine);
            }
        }
        /// <summary>
        /// Parse FunctionHeading
        /// </summary>
        /// <param name="functionRecord"></param>
        private void FunctionHeading(MethodRecord functionRecord, ref IdentifierRecord
            identifierRecord)
        {
            TypeRecord typeRecord = new TypeRecord(SymbolType.FunctionSymbol, VariableType.Void);
            functionRecord.parameterList = new List<Parameter>();

            switch (lookAheadToken.tag)
            {
                case Tags.MP_FUNCTION:
                    UsedRules.WriteLine("18");
                    Match((int)Tags.MP_FUNCTION);
                    Identifier(ref functionRecord);
                    identifierRecord.lexeme = functionRecord.name;
                    functionRecord.parameterList = OptionalFormalParameterList(
                        functionRecord.parameterList);
                    Type(ref typeRecord);
                    functionRecord.returnType = typeRecord.variableType;
                    analyzer.SymbolTableInsert(functionRecord);
                    analyzer.ProcessId(ref identifierRecord);
                    analyzer.CreateSymbolTable(functionRecord.name);
                    //analyzer.ProcessMethod(identifierRecord, ref functionRecord);
                    analyzer.SymbolTableInsert(functionRecord.parameterList);
                    break;
                default:
                    Error("Expecting FunctionHeading but found " + lookAheadToken.lexeme);
                    break;
            }
        }
 /// <summary>
 /// Parse Identifier
 /// </summary>
 /// <param name="programIdenentifierRecord"></param>
 private void Identifier(ref MethodRecord programIdenentifierRecord)
 {
     programIdenentifierRecord.name = lookAheadToken.lexeme;
     Match((int)Tags.MP_IDENTIFIER);
 }
 /// <summary>
 /// Parse FunctionDeclaration
 /// </summary>
 private void FunctionDeclaration()
 {
     IdentifierRecord identifierRecord = new IdentifierRecord();
     MethodRecord functionIdentifierRecord = new MethodRecord(SymbolType.FunctionSymbol);
     switch (lookAheadToken.tag)
     {
         case Tags.MP_FUNCTION:
             UsedRules.WriteLine("16");
             FunctionHeading(functionIdentifierRecord,ref identifierRecord);
             Match(';');
             Block(identifierRecord);
             analyzer.symbolTableStack.Pop();
             Match(';');
             break;
         default:
             Error("Expecting FunctionDeclaration but found " + lookAheadToken.lexeme);
             break;
     }
 }
        /// <summary>
        /// Parse Factor
        /// </summary>
        /// <param name="factorRecord"></param>
        private void Factor(ref VariableRecord factorRecord)
        {
            IdentifierRecord idRecord = new IdentifierRecord();
            LiteralRecord litRecord = new LiteralRecord();
            VariableType tempType = VariableType.Void;
            List<Parameter> parameterList = new List<Parameter>();
            MethodRecord methodRecord = new MethodRecord();
            methodRecord.parameterList = new List<Parameter>();
            string idRecName = null;

            switch (lookAheadToken.tag)
            {
                case Tags.MP_INTEGER_LIT:
                    UsedRules.WriteLine("94");
                    litRecord.lexeme = lookAheadToken.lexeme;
                    litRecord.type = VariableType.Integer;
                    Match((int)Tags.MP_INTEGER_LIT);
                    analyzer.GenerateLitPush(litRecord, ref tempType);
                    factorRecord.variableType = tempType;
                    break;
                case Tags.MP_NOT:
                    UsedRules.WriteLine("95");
                    Match((int)Tags.MP_NOT);
                    Factor(ref factorRecord);
                    break;
                case Tags.MP_LPAREN:
                    UsedRules.WriteLine("96");
                    Match((int)Tags.MP_LPAREN);
                    Expression(ref factorRecord);
                    Match((int)Tags.MP_RPAREN);
                    break;
                case Tags.MP_IDENTIFIER:
                    UsedRules.WriteLine("97");
                    Identifier(ref idRecName);
                    idRecord.lexeme = idRecName;
                    analyzer.ProcessId(ref idRecord);
                    analyzer.GenerateIdPush(idRecord, ref factorRecord);
                    analyzer.processParameters(idRecord,ref methodRecord,ref parameterList);
                   OptionalActualParameterList(parameterList);
                    analyzer.ProcessMethod(idRecord,ref methodRecord);
                    analyzer.GenerateCallMethod(methodRecord);
                    break;
                default:
                    Error("Expecting Factor but found " + lookAheadToken.lexeme);
                    break;
            }
        }
 /// <summary>
 /// Parse ProcedureStatement
 /// </summary>
 private void ProcedureStatement()
 {
     MethodRecord procedureRecord = new MethodRecord(SymbolType.ProcedureSymbol);
     IdentifierRecord identifierRecord = new IdentifierRecord();
     List<Parameter> parameterList = new List<Parameter>();
     procedureRecord.parameterList = new List<Parameter>();
     switch (lookAheadToken.tag)
     {
         case Tags.MP_IDENTIFIER:
             UsedRules.WriteLine("63");
             Identifier(ref procedureRecord);
             identifierRecord.lexeme = procedureRecord.name;
             analyzer.ProcessId(ref identifierRecord);
             analyzer.GenerateLoadDelegate(procedureRecord);
             analyzer.processParameters(identifierRecord, ref procedureRecord,
                 ref parameterList);
             OptionalActualParameterList(parameterList);
             analyzer.GenerateCallMethod(procedureRecord);
             break;
         default:
             Error("Expecting ProcedureStatement but found " + lookAheadToken.lexeme);
             break;
     }
 }
 /// <summary>
 /// Parse ProcedureHeading
 /// </summary>
 /// <param name="procedureRecord"></param>
 private void ProcedureHeading(MethodRecord procedureRecord,ref IdentifierRecord identifierRecord)
 {
     procedureRecord.parameterList = new List<Parameter>();
     switch(lookAheadToken.tag)
     {
         case Tags.MP_PROCEDURE:
             UsedRules.WriteLine("17");
             Match((int)Tags.MP_PROCEDURE);
             Identifier(ref procedureRecord);
             identifierRecord.lexeme = procedureRecord.name;
             procedureRecord.parameterList = OptionalFormalParameterList(
                 procedureRecord.parameterList);
             analyzer.SymbolTableInsert(procedureRecord);
             analyzer.ProcessId(ref identifierRecord);
             analyzer.CreateSymbolTable(procedureRecord.name);
             analyzer.ProcessMethod(identifierRecord, ref procedureRecord);
             analyzer.SymbolTableInsert(procedureRecord.parameterList);
             break;
         default:
             Error("Expecting ProcedureHeading but found " + lookAheadToken.lexeme);
             break;
     }
 }
        /// <summary>
        /// Parse ProcedureDeclaration
        /// </summary>
        private void ProcedureDeclaration()
        {
            MethodRecord procedureIdentifierRecord = new MethodRecord(SymbolType.ProcedureSymbol);
            IdentifierRecord identifierRecord = new IdentifierRecord();
            switch(lookAheadToken.tag)
            {
                case Tags.MP_PROCEDURE:
                    UsedRules.WriteLine("15");
                    ProcedureHeading(procedureIdentifierRecord,ref identifierRecord);
                    Match(';');
                    Block(identifierRecord);
                    analyzer.symbolTableStack.Pop();
                    Match(';');
                    break;
                default:
                    Error("Expecting ProcedureDeclaration but found " + lookAheadToken.lexeme);
                    break;

            }
        }