Exemple #1
0
        /// <summary>
        /// Constructor. iScope is the scope level, 0 being the lowest. symFirst is the first symbol
        /// in the Scope.
        /// </summary>
        /// <param name="iScope"></param>
        /// <param name="symFirst"></param>
        public Scope(int iScope, Symbol symFirst)
        {
            m_iScope = iScope;
            m_llSymbols = new LinkedList<Symbol>();
            m_llCurNode = new LinkedListNode<Symbol>(symFirst);

            m_llSymbols.AddFirst(m_llCurNode);
        }
Exemple #2
0
 /// <summary>
 /// symbol has been added to the internal list. 
 /// </summary>
 /// <param name="symbol"></param>
 public void AddSymbol(Symbol symbol)
 {
     // Check if first in list
     if (m_llSymbols.Count == 0)
         m_llSymbols.AddFirst(symbol);
     else
         m_llSymbols.AddAfter(m_llCurNode, symbol);
     // Update active node
     m_llCurNode = m_llSymbols.Last;
 }
Exemple #3
0
        /// <summary>
        /// Add symbol to given scope
        /// </summary>
        /// <param name="symbol"></param>
        /// <param name="scope"></param>
        public void AddSymbol(Symbol symbol, int scope)
        {
            if (scope < 0) return;
            if (c_iCurScope == scope)
            {
                AddSymbol(symbol);
                return;
            }
            // stack to hold popped scopes
            Stack<Scope> stkTemp = new Stack<Scope>();

            // get scope requested
            Scope scp = c_stkScope.Pop();
            while (scp.CurrentScope != scope)
            {
                stkTemp.Push(scp);
                scp = c_stkScope.Pop();
            }

            // push proper scope back on
            c_stkScope.Push(scp);

            // Add symbol to now current scope
            AddSymbol(symbol);

            // restore stack
            while (stkTemp.Count > 0)
                c_stkScope.Push(stkTemp.Pop());
        }
Exemple #4
0
        /// <summary>
        /// Add Symbol to active scope
        /// </summary>
        /// <param name="symbol"></param>
        public void AddSymbol(Symbol symbol)
        {
            // check if any scope exists
            if (c_stkScope.Count == 0)
                AddScope(); // add first scope

            // get last scope
            Scope scope = c_stkScope.Pop();

            // check if symbol is in scope
            if (scope.Contains(symbol.Name)) // remove symbol
                scope.RemoveSymbol(symbol);

            // update symbol scope level
            symbol.Scope = c_iCurScope;
            // add symbol
            scope.AddSymbol(symbol);
            // push back
            c_stkScope.Push(scope);
        }
Exemple #5
0
 /// <summary>
 /// true has been returned if symbol exists in class list, false if not.
 /// </summary>
 /// <param name="symbol"></param>
 /// <returns></returns>
 public bool Contains(Symbol symbol)
 {
     return m_llSymbols.Contains(symbol);
 }
Exemple #6
0
 /// <summary>
 /// symbol has been removed from the internal list if it exists in the list.
 /// </summary>
 /// <param name="symbol"></param>
 public void RemoveSymbol(Symbol symbol)
 {
     if (m_llSymbols.Contains(symbol))
         m_llSymbols.Remove(symbol);
 }
Exemple #7
0
        /// <summary>
        /// Puts the proper address for int symbol in EAX. offset is the symbol offset,
        /// and Param_Type is the parameter type.
        /// </summary>
        /// <param name="offset"></param>
        /// <param name="Param_Type"></param>
        public void CalcIntAddress(string offset, Symbol.PARAMETER_TYPE Param_Type)
        {
            asm("  movzx EDI, BP");
            switch (Param_Type)
            {
                case Symbol.PARAMETER_TYPE.LOCAL_VAR:
                    Sub("EDI", offset);
                    break;
                case Symbol.PARAMETER_TYPE.REF_PARM:
                    //Add("EDI", offset);
                    movReg("EAX", "[EDI+" + offset + "]");
                    return;
                case Symbol.PARAMETER_TYPE.VAL_PARM:
                    Add("EDI", offset);
                    break;
            }

            movReg("EAX", "EDI");
        }
Exemple #8
0
        /// <summary>
        /// Puts the proper address for array[index] in EAX. Value of index must be in
        /// EAX. end is the end of the array, offset is the symbol offset. local
        /// determines if array is a reference or local var. Base offset is the base (so Arr[2..5] 
        /// it would be 2 ]
        /// </summary>
        public void CalcArrayAddress(string end, string offset, Symbol.PARAMETER_TYPE Param_Type, string comment = "")
        {
            // (BP~offset) - ((ArrayEnd - Index) * 4)
            movReg("EBX", "EAX");
            movReg("EAX", end);
            Sub("EAX", "EBX");
            iMul("EAX", "4");

            asm("  movzx EDI, BP");

            // Get offset
            switch (Param_Type)
            {
                case Symbol.PARAMETER_TYPE.LOCAL_VAR:
                    Sub("EDI", offset);
                    movReg("EBX", "EDI");
                    break;
                case Symbol.PARAMETER_TYPE.REF_PARM:
                    // Get address of whole array
                    movReg("EBX", "[EDI+" + offset + "]");
                    break;
                case Symbol.PARAMETER_TYPE.VAL_PARM:
                default:
                    break;
            }
            // Calculate final offset from BP
            Sub("EBX", "EAX");
            movReg("EAX", "EBX");

            //WRSTR(comment);
            //WRINT();
            //WRLN();
        }
Exemple #9
0
        /// <summary>
        /// Parse array on left side of :=. Address is pushed onto the stack
        /// </summary>
        /// <param name="sym"></param>
        private void ArrayID(Symbol sym)
        {
            // ***** ARRAY  ID() ***** //
            if (c_bParserASMDebug) m_Em.asm(";;;; ARRAY Assignment ;;;;");
            m_tok = m_Tknzr.NextToken();
            List<Token> lsIndex = new List<Token>();

            // get index expression (contents between [ ] )
            for (; m_tok.m_tokType != Token.TOKENTYPE.RIGHT_BRACK; m_tok = m_Tknzr.NextToken())
                lsIndex.Add(m_tok);

            // get index value
            EvalPostFix(InFixToPostFix(lsIndex));

            // calculate address
            m_Em.CalcArrayAddress(sym.ArrayEnd.ToString(), sym.Offset.ToString(), sym.ParamType, "ID() ADDRESS: ");

            // push for assignment
            m_Em.pushReg("EAX");

            Match(Token.TOKENTYPE.RIGHT_BRACK);
        }
Exemple #10
0
        /// <summary>
        /// Parses:
        /// ID : TYPE
        /// and adds the appropriate symbols to the table at scope.
        /// NOTE: m_tok is now the token after TYPE
        /// </summary>
        /// <param name="scope"></param>
        private void VarDef(int scope = 0, int baseoffset = -1, Symbol.PARAMETER_TYPE Paramater_Type = Symbol.PARAMETER_TYPE.LOCAL_VAR)
        {
            List<string> lsIDs = new List<string>();

            // stack offset to access variable
            // check if using local or global offset
            int iOffset = (baseoffset < 0) ? m_iOff : baseoffset;

            // loop through all var definitions (ex. i, k, j : INTEGER)
            while (m_tok.m_tokType != Token.TOKENTYPE.COLON)
            {
                // check for identifier
                if (m_tok.m_tokType == Token.TOKENTYPE.ID)
                {
                    // check if it exists
                    if (lsIDs.Contains(m_tok.m_strName))
                    {
                        ErrorHandler.Error(ERROR_CODE.VAR_REDECLARATION, m_tok.m_iLineNum, "VAR ID already exists");
                        break;
                    }
                    // store ID in temp string
                    lsIDs.Add(m_tok.m_strName);
                } // If ID

                // consume ID token
                Match(Token.TOKENTYPE.ID);

                // check if last VAR to be declared
                if (m_tok.m_tokType == Token.TOKENTYPE.COMMA)
                    // consume token
                    m_tok = m_Tknzr.NextToken();
            } // while not COLON

            Match(Token.TOKENTYPE.COLON);
            // add symbol for each var to symbol table
            // - probably not the best way to implement the loop and switch
            foreach (string s in lsIDs)
            {
                switch (m_tok.m_tokType)
                {
                    case Token.TOKENTYPE.INTEGER:
                        // Add symbol
                        m_SymTable.AddSymbol(new Symbol(s, scope, Symbol.SYMBOL_TYPE.TYPE_SIMPLE, Symbol.STORAGE_TYPE.TYPE_INT,
                      Paramater_Type, iOffset));
                        iOffset += 4; // inc offset by 32bits
                        break;
                    case Token.TOKENTYPE.CARDINAL:
                        // not implemented
                        break;
                    case Token.TOKENTYPE.REAL:
                        // not implemented
                        break;
                    default:
                        // Look for user defined type in symbol type
                        Symbol sym = m_SymTable.FindSymbol(m_tok.m_strName);
                        if (sym == null)
                            ErrorHandler.Error(ERROR_CODE.TOKEN_INVALID, m_tok.m_iLineNum,
                                "Expecting INTEGER, CARDINAL, or REAL token");
                        else
                            // ARRAY
                            m_SymTable.AddSymbol(new Symbol(s, scope, Symbol.SYMBOL_TYPE.TYPE_ARRAY, Symbol.STORAGE_TYPE.TYPE_INT,
                                Paramater_Type, iOffset, 0, sym.BaseOffset, sym.ArrayEnd));
                        iOffset += (sym.ArrayEnd - sym.BaseOffset) * 4; // memory offset of array-> sizeof(int)*(EndIndex - BeginIndex)
                        break;
                } // switch
            } // foreach

            // update m_iOff if using global scope
            if (baseoffset < 0) m_iOff = iOffset;

            // consume token
            m_tok = m_Tknzr.NextToken();
        }
Exemple #11
0
        /// <summary>
        /// Parse/emit procedure call
        /// </summary>
        /// <param name="sym"></param>
        private void ProcID(Symbol sym)
        {
            // ***** PROCEDURE ***** //
            // Parse argument list, pushing each value onto the stack
            // little ( k ) ;
            int iArgCount = 0;
            m_tok = m_Tknzr.NextToken();
            Match(Token.TOKENTYPE.LEFT_PAREN);

            // Parse arguments into list of token lists
            //  each list in the token list is an argument for the function being parsed
            List<List<Token>> lslsArgs = new List<List<Token>>(); // hold the arguments, list of token (expression) lists
            for (; m_tok.m_tokType != Token.TOKENTYPE.SEMI_COLON; m_tok = m_Tknzr.NextToken())
            {
                // parse argument into EAX
                List<Token> lsArg = new List<Token>();
                for (; m_tok.m_tokType != Token.TOKENTYPE.COMMA && m_tok.m_tokType != Token.TOKENTYPE.RIGHT_PAREN;
                    m_tok = m_Tknzr.NextToken())
                    lsArg.Add(m_tok);
                lslsArgs.Add(lsArg); // add argument expression to list of arg expressions
                ++iArgCount; // used when restoring the stack
            } // Get arguments

            // Must push arguments in reverse order
            for (int i = iArgCount; i > 0; --i)
            {
                // if proc is reference then push pointer to variable
                if (sym.SymType == Symbol.SYMBOL_TYPE.TYPE_REFPROC)
                {
                    Symbol symRefArg = m_SymTable.FindSymbol(lslsArgs[i - 1][0].m_strName);

                    m_Em.asm(";// Push REF addresses for: " + symRefArg.Name + " in PROCEDURE: " + sym.Name);
                    m_Em.asm(";// PARAM: " + symRefArg.ParamType.ToString());
                    // int
                    if (lslsArgs[i - 1].Count == 1)
                        m_Em.CalcIntAddress(symRefArg.Offset.ToString(), symRefArg.ParamType);
                    // array
                    else
                    {
                        // Evaluate index
                        List<Token> ltIndex = lslsArgs[i - 1].GetRange(2, lslsArgs[i - 1].Count - 3);

                        EvalPostFix(InFixToPostFix(ltIndex));

                        m_Em.CalcArrayAddress(symRefArg.BaseOffset.ToString(), symRefArg.Offset.ToString(),
                            symRefArg.ParamType, ";///ProcID Offset: ");
                    }

                    m_Em.pushReg("EAX");
                    continue;
                }
                // Get value into EAX then push onto stack
                EvalPostFix(InFixToPostFix(lslsArgs[i - 1]));
                m_Em.pushReg("EAX");
            } // Push parameters for function

            Match(Token.TOKENTYPE.SEMI_COLON);

            // Call function
            m_Em.asm(string.Format("call     {0}     ; PROCEDURE {0}", sym.Name));

            m_Em.Add("SP", (lslsArgs.Count * 4).ToString());
        }