Beispiel #1
0
        /// <summary>
        /// Parse Loop statement
        /// </summary>
        private void LOOP()
        {
            if (c_bParserASMDebug) m_Em.asm(";;;;;; LOOP statement begin ;;;;;;");
            // Labels
            string sBeginLabel = m_LABEL_BASE + m_iLabelLevel++;
            string sEndLabel = m_LABEL_BASE + m_iLabelLevel++;

            // consume LOOP token
            m_tok = m_Tknzr.NextToken();

            // Beginning of loop
            m_Em.Label(sBeginLabel);

            // Parse until IF
            ParseLoop(Token.TOKENTYPE.IF);

            // IF
            Match(Token.TOKENTYPE.IF);

            List<Token> inFix = new List<Token>();
            for (; m_tok.m_tokType != Token.TOKENTYPE.THEN; m_tok = m_Tknzr.NextToken())
                inFix.Add(m_tok);

            //// LOOP instantiation
            // Match tokens
            Match(Token.TOKENTYPE.THEN);

            // parse after condition
            ParseLoop();

            Match(Token.TOKENTYPE.SEMI_COLON);
            Match(Token.TOKENTYPE.END);
            Match(Token.TOKENTYPE.SEMI_COLON);

            // eval conditional expression
            EvalPostFix(InFixToPostFix(inFix));
            // if EAX is one then statement is true and jump to IF
            m_Em.Compare("EAX", "1");
            m_Em.Jump("jge", sEndLabel);

            //// evaluate inside loop
            ParseLoop();

            //m_Em.RDINT(); // trace

            // jump to top of loop
            m_Em.Jump("jmp", sBeginLabel);

            // label if condition fails jump over
            m_Em.Label(sEndLabel);

            // consume remaining "END;"
            Match(Token.TOKENTYPE.END);
            Match(Token.TOKENTYPE.SEMI_COLON);

            if (c_bParserASMDebug) m_Em.asm(";;;;;; end LOOP statement ;;;;;;");
        }
Beispiel #2
0
 /// <summary>
 /// Returns true if type is one of: (, AND, OR, =, !=, >, >=, <, <=
 /// </summary>
 /// <param name="type"></param>
 /// <returns></returns>
 private bool InfixPlusMinusCondition(Token.TOKENTYPE type)
 {
     return (type == Token.TOKENTYPE.AND || type == Token.TOKENTYPE.OR
         || type == Token.TOKENTYPE.EQUAL || type == Token.TOKENTYPE.NOT_EQ
         || type == Token.TOKENTYPE.GRTR_THAN || type == Token.TOKENTYPE.GRTR_THAN_EQ
         || type == Token.TOKENTYPE.LESS_THAN || type == Token.TOKENTYPE.LESS_THAN_EQ);
 }
Beispiel #3
0
        /// <summary>
        /// Parse tokens from infix to postfix, including conditionals and logical operators
        /// </summary>
        private List<Token> InFixToPostFix(List<Token> tokList = null)
        {
            // InFix to PostFix
            Stack<Token> stkInToPost = new Stack<Token>(); // infix to postfix stack
            List<Token> lsExpression = new List<Token>();  // get the whole expression as seperate list
            List<Token> lsPostFix = new List<Token>();     // postfix statement
            Token tok; // temp

            // get expression into list
            // Use passed in list if possible
            if (tokList == null)
                for (; m_tok.m_tokType != Token.TOKENTYPE.SEMI_COLON; m_tok = m_Tknzr.NextToken())
                    lsExpression.Add(m_tok);
            else
                lsExpression = tokList;

            // loop through expression
            for (int j = 0; j < lsExpression.Count; ++j)
            {
                switch (lsExpression[j].m_tokType)
                {
                    case Token.TOKENTYPE.RIGHT_PAREN:
                        // Pop elements until '(' is found
                        if (stkInToPost.Count > 0)
                        {
                            tok = stkInToPost.Pop();
                            while (stkInToPost.Count > 0 && tok.m_tokType != Token.TOKENTYPE.LEFT_PAREN)
                            {
                                lsPostFix.Add(tok);
                                tok = stkInToPost.Pop();
                            } // while not '('
                        } // if stack no empty
                        break;
                    //** HIGHEST PRECEDENCE
                    case Token.TOKENTYPE.MOD:
                    case Token.TOKENTYPE.MULT:
                    case Token.TOKENTYPE.DIV:
                    case Token.TOKENTYPE.LEFT_PAREN:
                        // Highest precedence, push onto stack
                        if (!checkNeg(ref lsPostFix, ref lsExpression, ref j))
                            stkInToPost.Push(lsExpression[j]); // push onto stack
                        break;
                    //** MIDDLE PRECEDENCE
                    case Token.TOKENTYPE.AND:
                    case Token.TOKENTYPE.OR:
                    case Token.TOKENTYPE.NOT:
                    case Token.TOKENTYPE.EQUAL:
                    case Token.TOKENTYPE.NOT_EQ:
                    case Token.TOKENTYPE.GRTR_THAN:
                    case Token.TOKENTYPE.GRTR_THAN_EQ:
                    case Token.TOKENTYPE.LESS_THAN:
                    case Token.TOKENTYPE.LESS_THAN_EQ:
                        // if previous token was operator then check if number should be negative
                        if (!checkNeg(ref lsPostFix, ref lsExpression, ref j))
                        {
                            if (stkInToPost.Count > 0)
                            {
                                tok = stkInToPost.Peek();
                                // check top of stack and compare precedence
                                while (true)
                                {
                                    // left paren on top is like having an empty stack
                                    if (tok.m_tokType == Token.TOKENTYPE.LEFT_PAREN)
                                    {
                                        stkInToPost.Push(lsExpression[j]); // push onto stack
                                        break;
                                    } // if '('
                                    // Current lower / top higher
                                    if (tok.m_tokType == Token.TOKENTYPE.MULT || tok.m_tokType == Token.TOKENTYPE.DIV
                                        || tok.m_tokType == Token.TOKENTYPE.MOD)
                                    {
                                        tok = stkInToPost.Pop();
                                        lsPostFix.Add(tok);
                                        if (stkInToPost.Count > 0)
                                            tok = stkInToPost.Peek();
                                        else // stack empty push
                                        {
                                            stkInToPost.Push(lsExpression[j]); // push onto stack
                                            break;
                                        } // else
                                        continue; // not needed, but kept for readability
                                    } // Higher
                                    // equal
                                    if (InfixPlusMinusCondition(tok.m_tokType))
                                    {
                                        tok = stkInToPost.Pop();
                                        lsPostFix.Add(tok);
                                        stkInToPost.Push(lsExpression[j]); // push onto stack
                                        break;
                                    } // Equal
                                    // Current higher /  top lower
                                    if (tok.m_tokType == Token.TOKENTYPE.PLUS || tok.m_tokType == Token.TOKENTYPE.MINUS)
                                    {
                                        stkInToPost.Push(lsExpression[j]); // push onto stack
                                        break;
                                    } // Lower
                                } // while
                            } // if stack not empty
                            else // stack empty
                                stkInToPost.Push(lsExpression[j]); // push onto stack
                        } // if not neg
                        break;
                    //** LOWEST PRECEDENCE
                    case Token.TOKENTYPE.PLUS:
                    case Token.TOKENTYPE.MINUS:
                        // if previous token was operator then check if number should be negative
                        if (!checkNeg(ref lsPostFix, ref lsExpression, ref j))
                        {
                            if (stkInToPost.Count > 0)
                            {
                                tok = stkInToPost.Peek();
                                // check top of stack and compare precedence
                                while (true)
                                {
                                    // left paren on top is like having an empty stack
                                    if (tok.m_tokType == Token.TOKENTYPE.LEFT_PAREN)
                                    {
                                        stkInToPost.Push(lsExpression[j]); // push onto stack
                                        break;
                                    }
                                    // Current lower / top higher
                                    if (InfixPlusMinusCondition(tok.m_tokType) || tok.m_tokType == Token.TOKENTYPE.MULT
                                        || tok.m_tokType == Token.TOKENTYPE.DIV || tok.m_tokType == Token.TOKENTYPE.MOD)
                                    {
                                        tok = stkInToPost.Pop();
                                        lsPostFix.Add(tok);
                                        // check stack
                                        if (stkInToPost.Count > 0)
                                            tok = stkInToPost.Peek();
                                        else // stack empty push
                                        {
                                            stkInToPost.Push(lsExpression[j]); // push onto stack
                                            break;
                                        } // else
                                        continue; // not needed, but kept for readability
                                    } // Top higher
                                    // equal
                                    if (tok.m_tokType == Token.TOKENTYPE.PLUS || tok.m_tokType == Token.TOKENTYPE.MINUS)
                                    {
                                        tok = stkInToPost.Pop();
                                        lsPostFix.Add(tok);
                                        stkInToPost.Push(lsExpression[j]); // push onto stack
                                        break;
                                    } // Equal / Lower
                                } // while
                            } // if stack not empty
                            else // stack empty
                                stkInToPost.Push(lsExpression[j]); // push onto stack
                        } // if not neg
                        break;
                    case Token.TOKENTYPE.ID:

                        // Check if ARRAY
                        if (j + 1 < lsExpression.Count && lsExpression[j + 1].m_tokType /*m_Tknzr.PeekToken().m_tokType*/
                            == Token.TOKENTYPE.LEFT_BRACK)
                        {
                            lsPostFix.Add(lsExpression[j]);          // add ID
                            ++j;                                     // only skip over ID, [ is current token
                            lsPostFix.Add(lsExpression[j]);          // add [
                            ++j;                                     // move to next

                            // Add array as ID [ postfix index exp ]
                            // ex:          list[23*]
                            List<Token> ltTemp = new List<Token>();
                            // Add everything in brackets and convert to postfix
                            for (; lsExpression[j].m_tokType != Token.TOKENTYPE.RIGHT_BRACK; ++j)
                                ltTemp.Add(lsExpression[j]);
                            lsPostFix.AddRange(InFixToPostFix(ltTemp)); // add post fix expression
                            lsPostFix.Add(lsExpression[j]);             // add ]
                            break;
                        }
                        goto case Token.TOKENTYPE.INT_NUM;
                    case Token.TOKENTYPE.INT_NUM:
                        lsPostFix.Add(lsExpression[j]);
                        break;
                    default:
                        ErrorHandler.Error(ERROR_CODE.TOKEN_INVALID, lsExpression[j].m_iLineNum,
                            "Expected (,),+,-,*,/,MOD,INT_NUM, or ID token");
                        break;
                } // switch
            } // for all tokens in lsExpression
            while (stkInToPost.Count > 0)
                lsPostFix.Add(stkInToPost.Pop()); // get last element out
            return lsPostFix;
        }
Beispiel #4
0
        /// <summary>
        /// Parse Assignment function
        /// ex. ID := Expression ;
        /// </summary>
        private void ID()
        {
            // lookup in symbol table
            Symbol sym = FindSymbol(m_tok.m_strName);

            switch (sym.SymType)
            {
                case Symbol.SYMBOL_TYPE.TYPE_CONST:
                    ErrorHandler.Error(ERROR_CODE.CONST_REDEFINITION, m_tok.m_iLineNum, "Cannot redefine a CONST value");
                    return; // get out of function
                case Symbol.SYMBOL_TYPE.TYPE_REFPROC:
                case Symbol.SYMBOL_TYPE.TYPE_PROC:
                    ProcID(sym);
                    return;
                default:
                    break;
            } // SymType

            // consume token
            m_tok = m_Tknzr.NextToken(); // ID

            // Check if ARRAY, get proper offset
            if (m_tok.m_tokType == Token.TOKENTYPE.LEFT_BRACK)
                ArrayID(sym);
            else // type INT
            {
                m_Em.CalcIntAddress(sym.Offset.ToString(), sym.ParamType);
                m_Em.pushReg("EAX");
            }

            Match(Token.TOKENTYPE.ASSIGN); // :=

            // Get value to be stored
            if (m_tok.m_tokType == Token.TOKENTYPE.RDINT)
            {
                m_Em.RDINT();
                m_tok = m_Tknzr.NextToken();
                Match(Token.TOKENTYPE.LEFT_PAREN);
                Match(Token.TOKENTYPE.RIGHT_PAREN);
            } // RDINT
            else
                EvalPostFix(InFixToPostFix()); // evaluate expression, emit asm in process

            // Value to be stored should be in EAX
            //  store the value at proper place:
            m_Em.popReg("EDI");

            m_Em.movReg("[EDI]", "EAX");
            Match(Token.TOKENTYPE.SEMI_COLON);
        }
Beispiel #5
0
        /// <summary>
        /// Parse IF statement
        /// </summary>
        private void IF()
        {
            if (c_bParserASMDebug) m_Em.asm(";;;;;; IF statement begin ;;;;;;");
            // labels
            string sIfLabel = m_LABEL_BASE + m_iLabelLevel++;
            string sElseLabel = m_LABEL_BASE + m_iLabelLevel++;
            string sEndLabel = m_LABEL_BASE + m_iLabelLevel++;

            // consume token (IF)
            m_tok = m_Tknzr.NextToken();

            List<Token> inFix = new List<Token>();
            for (; m_tok.m_tokType != Token.TOKENTYPE.THEN; m_tok = m_Tknzr.NextToken())
                inFix.Add(m_tok);

            // eval conditional expression
            EvalPostFix(InFixToPostFix(inFix));

            // if EAX is one then statement is true and jump to IF
            m_Em.Compare("EAX", "1");
            m_Em.Jump("je", sIfLabel);

            // Force jump to else
            m_Em.Jump("jmp", sElseLabel);

            // consume token (THEN)
            m_tok = m_Tknzr.NextToken();

            ///// run code in IF section
            if (c_bParserASMDebug) m_Em.asm(";;; IF");
            m_Em.Label(sIfLabel);            // IF Label
            ParseLoop(); // Parse inside of IF until ELSE or END is reached
            m_Em.Jump("jmp", sEndLabel);     // jump around else code

            // Else label, put even if no ELSE token
            m_Em.Label(sElseLabel);          // ELSE Label
            if (m_tok.m_tokType == Token.TOKENTYPE.ELSE) // if END then there is no ELSE section
            {
                // consume token (ELSE)
                m_tok = m_Tknzr.NextToken();

                //// else code
                if (c_bParserASMDebug) m_Em.asm(";;; ELSE");
                ParseLoop(Token.TOKENTYPE.ELSE); // Parse inside of ELSE until END token
            } // ELSE
            m_Em.Label(sEndLabel);          // END Label
            // consume remaining "END;"
            Match(Token.TOKENTYPE.END);
            Match(Token.TOKENTYPE.SEMI_COLON);

            if (c_bParserASMDebug) m_Em.asm(";;;;;; end IF statement ;;;;;;");
        }
Beispiel #6
0
        /// <summary>
        /// Parses a modula-2 file. File must be open.
        /// </summary>
        public void ParseFile()
        {
            // make sure tokenizer is reset
            m_Tknzr.Reset();

            // reset emitter
            m_Em.Reset();

            // reset symbol table
            m_SymTable.Reset();

            // reset offset and label count
            m_iOff = 4;
            m_iLabelLevel = 0;
            m_iArithmeticLevel = 0;

            m_tok = m_Tknzr.NextToken();

            // Force jump to main when first run
            m_Em.Jump("jmp", "__MAIN");

            // Loop through file
            while (m_tok.m_tokType != Token.TOKENTYPE.EOF || m_tok == null)
            {
                Module();
                while (m_tok.m_tokType != Token.TOKENTYPE.BEGIN)
                {
                    switch (m_tok.m_tokType)
                    {
                        case Token.TOKENTYPE.CONST:
                            Const();
                            break;
                        case Token.TOKENTYPE.TYPE:
                            Type();
                            break;
                        case Token.TOKENTYPE.VAR:
                            Vars();
                            break;
                        case Token.TOKENTYPE.PROCEDURE:
                            Procedure();
                            break;
                        default:
                            //error
                            break;
                    }
                }
                // print symbol table
                Function();
            } // while
        }
Beispiel #7
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);
        }
Beispiel #8
0
        /// <summary>
        /// Parse and emit WRINT module keyword
        /// ex. WRINT(42);
        /// </summary>
        private void WRINT()
        {
            // consume token
            m_tok = m_Tknzr.NextToken();
            // eat '('
            Match(Token.TOKENTYPE.LEFT_PAREN);

            // evaluate expression
            //  consumes RIGHT_PAREN and SEMICOLON tokens
            List<Token> exp = new List<Token>();
            for (; m_tok.m_tokType != Token.TOKENTYPE.SEMI_COLON; m_tok = m_Tknzr.NextToken())
                exp.Add(m_tok);
            exp.RemoveAt(exp.Count - 1); // remove ')' in WRINT(exp)

            // Get value of INT
            EvalPostFix(InFixToPostFix(exp));

            // write to console
            // - int to print should be in EAX
            m_Em.WRINT(); // prints what is in EAX

            Match(Token.TOKENTYPE.SEMI_COLON);

            // consume token
            //m_tok = m_Tknzr.NextToken();
        }
Beispiel #9
0
 /// <summary>
 /// Parse and emit WRLN modula keyword
 /// ex. WRLN;
 /// </summary>
 private void WRLN()
 {
     // consume token
     m_tok = m_Tknzr.NextToken();
     m_Em.WRLN();
     Match(Token.TOKENTYPE.SEMI_COLON);
 }
Beispiel #10
0
        /// <summary>
        /// Parses the TYPE section
        /// </summary>
        private void Type()
        {
            Match(Token.TOKENTYPE.TYPE);
            List<int> intList = new List<int>();        // type values
            List<string> lsIDs = new List<string>();    // type IDs

            // ID, Equal, ARRAY, LEFT_BRACK, INT, .., INT, RIGHT_BRACK, OF, INTEGER, ;
            //     prListType = ARRAY [11 .. 30] OF INTEGER ;

            while (m_tok.m_tokType != Token.TOKENTYPE.CONST && m_tok.m_tokType != Token.TOKENTYPE.VAR)
            {

                // ID = ARRAY
                if (m_tok.m_tokType == Token.TOKENTYPE.ID)
                {
                    // check if it exists already
                    if (lsIDs.Contains(m_tok.m_strName))
                    {
                        ErrorHandler.Error(ERROR_CODE.TYPE_REDECLARATION, m_tok.m_iLineNum, "TYPE ID already exists");
                        break;
                    }
                    // store ID in temp string
                    lsIDs.Add(m_tok.m_strName);

                    Match(Token.TOKENTYPE.ID);
                    Match(Token.TOKENTYPE.EQUAL);

                    // Determine which type being defined (Eventually refactor cases into separate functions)
                    switch (m_tok.m_tokType)
                    {
                        case Token.TOKENTYPE.ARRAY:
                            m_tok = m_Tknzr.NextToken();                // eat ARRAY
                            if (m_tok.m_tokType == Token.TOKENTYPE.LEFT_BRACK)
                            {
                                m_tok = m_Tknzr.NextToken();            // eat '['
                                // Add ARRAY bounds to intlist ->  [INT .. INT]
                                intList.Add(int.Parse(m_tok.m_strName));
                                m_tok = m_Tknzr.NextToken();
                                Match(Token.TOKENTYPE.DOT_DOT);         // ..
                                intList.Add(int.Parse(m_tok.m_strName));
                                m_tok = m_Tknzr.NextToken();

                                Match(Token.TOKENTYPE.RIGHT_BRACK);     // ]

                                Match(Token.TOKENTYPE.OF);
                                // Match type
                                switch (m_tok.m_tokType)
                                {
                                    case Token.TOKENTYPE.INTEGER:
                                        m_tok = m_Tknzr.NextToken(); // eat token
                                        break;
                                    default:
                                        ErrorHandler.Error(ERROR_CODE.INVALID_TYPE, m_tok.m_iLineNum,
                                            string.Format("Invalid type:{0}, should be INTEGER", m_tok.m_tokType));
                                        break;

                                } // ARRAY data type
                                Match(Token.TOKENTYPE.SEMI_COLON);
                            } // If LEFT_BRACK
                            // Add "template" to symbol table
                            foreach (string id in lsIDs)
                                m_SymTable.AddSymbol(new Symbol(id, 0, Symbol.SYMBOL_TYPE.TYPE_ARRAY, Symbol.STORAGE_TYPE.TYPE_INT,
                                    Symbol.PARAMETER_TYPE.LOCAL_VAR, 0, 0, intList[intList.Count - 2], intList[intList.Count - 1]));
                            break;
                        default:
                            ErrorHandler.Error(ERROR_CODE.INVALID_TYPE, m_tok.m_iLineNum, string.Format("Invalid type:{0}, should be ARRAY",
                                m_tok.m_tokType));
                            break;
                    } // switch TYPE
                } // ID =
            } // != CONST
        }
Beispiel #11
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();
        }
Beispiel #12
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());
        }
Beispiel #13
0
        private void ProcFunction(int callingscope, string procname)
        {
            // *********************
            // ***** PROCEDURE *****
            // skip BEGIN
            m_tok = m_Tknzr.NextToken();

            // Find PROCEDURE symbol in one below top scope
            Scope scpActive = m_SymTable.GetCurrentScope();
            Scope scpCalling = m_SymTable.GetScope(callingscope);
            Symbol symProc = null;
            foreach (Symbol sym in scpCalling.Symbols)
                if (sym.Name == procname)
                {
                    symProc = sym;
                    break;
                } // get procedure symbol
            // error
            if (symProc == null)
                ErrorHandler.Error(ERROR_CODE.SYMBOL_UNDEFINED, m_tok.m_iLineNum,
                    "Expecting PROCEDURE name");

            // procedure header
            if (c_bParserASMDebug) m_Em.asm(string.Format(";======= PROCEDURE: {0} =======", symProc.Name));

            // Print jump label
            m_Em.Label(symProc.Name);

            // Prep procedure stack, save old stack info
            m_Em.pushReg("BP");         // save old stack base
            m_Em.movReg("BP", "SP");    // stack pointer now points to "bottom" of procedure stack

            // Make room for local variables
            // Get number of local variables
            if (c_bParserASMDebug) m_Em.asm("; Make room for local variables ;;;;;;;;");
            int iArg = 0, iLocalVarSpace = 0;
            foreach (Symbol sym in scpActive.Symbols)
                if (sym.ParamType == Symbol.PARAMETER_TYPE.LOCAL_VAR
                    && sym.SymType == Symbol.SYMBOL_TYPE.TYPE_SIMPLE) ++iArg;
            iLocalVarSpace = 4 + (4 * (iArg)); // integer variables

            List<int> liArraySizes = new List<int>();
            List<Symbol> lsArrays = new List<Symbol>();

            /////
            // If array is REF_PARM only needs 4 bytes of space
            // Just the address of the lowest is passed
            // if VAL_PARM

            // WOOH LAMBDAS!
            // Get all Array symbols into a list
            lsArrays.AddRange(scpActive.Symbols.ToList().FindAll(sym => sym.SymType.Equals(Symbol.SYMBOL_TYPE.TYPE_ARRAY)));
            // Get all offsets
            lsArrays.ForEach(sym =>
            {
                if (sym.ParamType == Symbol.PARAMETER_TYPE.LOCAL_VAR)
                    iLocalVarSpace += (sym.ArrayEnd - sym.BaseOffset) * 4; ;
            });

            // space for local variables
            m_Em.Sub("SP", iLocalVarSpace.ToString());

            if (c_bParserASMDebug) m_Em.asm("; Function Body ;;;;;;;;");
            // Parse/Emit until END
            ParseLoop();

            if (c_bParserASMDebug) m_Em.asm("; Epilogue  ;;;;;;;;");

            // Deallocate variables (readjust stack)
            //m_Em.movReg("SP", "BP");

            m_Em.Add("SP", (iLocalVarSpace).ToString());

            // Restore old basepointer
            m_Em.popReg("BP");

            //// restore calling stack
            //int iOffset = 0;
            //scpActive.Symbols.ToList().ForEach(s =>
            //{
            //    if (s.ParamType != Symbol.PARAMETER_TYPE.LOCAL_VAR)
            //        iOffset += 4;//(s.ArrayEnd - s.BaseOffset) * 4;
            //    //else
            //    //    iOffset += 4;
            //});
            //m_Em.Add("SP", (iLocalVarSpace).ToString());

            // Print return instruction
            m_Em.asm("ret     ; Return to calling code");

            // procedure footer
            if (c_bParserASMDebug) m_Em.asm(string.Format(";======= END PROCEDURE: {0} =======", symProc.Name));

            // match end
            Match(Token.TOKENTYPE.END);
            Match(Token.TOKENTYPE.ID);
            Match(Token.TOKENTYPE.SEMI_COLON);

            // remove active scope, set next active
            m_SymTable.RemoveScope();
        }
Beispiel #14
0
        /// <summary>
        /// Parses the PROCEDURE header of a modula-2 file
        /// EX: 
        /// PROCEDURE ID ( ID : TYPE ) ;
        /// </summary>
        private void Procedure()
        {
            // PROCEDURE little
            //( i : INTEGER ) ;
            // store calling scope
            int iCallScope = m_SymTable.ActiveScope;

            // consume PROCEDURE token
            m_tok = m_Tknzr.NextToken();

            // look up proc ID, check for redeclaration
            Symbol procSym = m_SymTable.FindSymbol(m_tok.m_strName);
            if (procSym != null)
                ErrorHandler.Error(ERROR_CODE.PROC_REDECLARATION, m_tok.m_iLineNum, "PROCEDURE already declared");

            Token tkProcID = m_tok; // save proc ID

            // Consume ID token
            m_tok = m_Tknzr.NextToken();

            // Parse arguments if any
            if (m_tok.m_tokType == Token.TOKENTYPE.LEFT_PAREN)
            {
                m_tok = m_Tknzr.NextToken();

                // check for passed by reference
                //  if VAR token exists then parameters are reference types
                if (m_tok.m_tokType == Token.TOKENTYPE.VAR)
                {
                    // Add PROC to symbol table to calling scope
                    m_SymTable.AddSymbol(new Symbol(tkProcID.m_strName, iCallScope, Symbol.SYMBOL_TYPE.TYPE_REFPROC,
                        Symbol.STORAGE_TYPE.STORE_NONE, Symbol.PARAMETER_TYPE.LOCAL_VAR, 0));

                    // Create new scope for procedure
                    m_SymTable.AddScope();

                    m_tok = m_Tknzr.NextToken(); // consume VAR token
                    while (m_tok.m_tokType != Token.TOKENTYPE.RIGHT_PAREN)
                        VarDef(m_SymTable.ActiveScope, 4, Symbol.PARAMETER_TYPE.REF_PARM);

                    // Add Proc sym with TYPE_REFPROC so that we know the parameters are of reference type
                    //  in the ID() function. Do so by overwriting the symbol
                }
                // Pass by value
                else
                {
                    // Add PROC to symbol table to calling scope
                    m_SymTable.AddSymbol(new Symbol(tkProcID.m_strName, iCallScope, Symbol.SYMBOL_TYPE.TYPE_PROC,
                        Symbol.STORAGE_TYPE.STORE_NONE, Symbol.PARAMETER_TYPE.LOCAL_VAR, 0));

                    // Create new scope for procedure
                    m_SymTable.AddScope();

                    // Parse procedure paramaters (arguments)
                    while (m_tok.m_tokType != Token.TOKENTYPE.RIGHT_PAREN)          // while not )
                        VarDef(m_SymTable.ActiveScope, 4, Symbol.PARAMETER_TYPE.VAL_PARM);   // baseoffset for scope starts at 4
                }
                m_tok = m_Tknzr.NextToken();     // Consume )
            }
            Match(Token.TOKENTYPE.SEMI_COLON);

            while (m_tok.m_tokType != Token.TOKENTYPE.BEGIN)
            {
                switch (m_tok.m_tokType)
                {
                    // CONST
                    case Token.TOKENTYPE.CONST:
                        Const(m_SymTable.ActiveScope);
                        break;
                    // VAR  Parse PROCEDURE's local vars
                    case Token.TOKENTYPE.VAR:
                        Vars(m_SymTable.ActiveScope, 4);
                        break;
                }
            }

            // Parse PROCEDURE's contents
            m_Em.asm(string.Format("\r\n\r\n;// START Procedure: {0}", tkProcID.m_strName));
            ProcFunction(iCallScope, tkProcID.m_strName);
            m_Em.asm(string.Format(";// END   Procedure: {0}\r\n\r\n", tkProcID.m_strName));
        }
Beispiel #15
0
 /// <summary>
 /// True has been returned if tokType matches the current token, false if not.
 /// One token has been consumed.
 /// </summary>
 /// <param name="tokType"></param>
 /// <returns></returns>
 private bool Match(Token.TOKENTYPE tokType)
 {
     bool b = (m_tok.m_tokType == tokType);
     // Throw error if not expected token
     if (!b) ErrorHandler.Error(ERROR_CODE.TOKEN_INVALID, m_tok.m_iLineNum,
         string.Format("Expected token: {0}", tokType.ToString()));
     m_tok = m_Tknzr.NextToken();
     return b;
 }
Beispiel #16
0
 // *********************************************************************************
 // *********************************************************************************
 //              K E Y W O R D     H E L P E R    F U N C T I O N S
 // *********************************************************************************
 /// <summary>
 /// Parse and emit WRSTR modula keyword
 /// ex. WRSTR("string contents");
 /// </summary>
 private void WRSTR()
 {
     // consume token
     m_tok = m_Tknzr.NextToken();
     Match(Token.TOKENTYPE.LEFT_PAREN);
     // Check for parse error
     if (m_tok.m_tokType != Token.TOKENTYPE.STRING) ErrorHandler.Error(ERROR_CODE.TOKEN_INVALID,
         m_tok.m_iLineNum, "Expected STRING token");
     m_Em.WRSTR(m_tok.m_strName);
     Match(Token.TOKENTYPE.STRING);
     Match(Token.TOKENTYPE.RIGHT_PAREN);
     Match(Token.TOKENTYPE.SEMI_COLON);
 }
Beispiel #17
0
 /// <summary>
 /// Loops and parses keywords of functions
 /// </summary>
 private void ParseLoop(Token.TOKENTYPE endType = Token.TOKENTYPE.END)
 {
     bool runloop = true;
     // While not endType and no error
     while (m_tok.m_tokType != endType && ErrorHandler.LastError == (ERROR_CODE)0
         && runloop)
     {
         switch (m_tok.m_tokType)
         {
             case Token.TOKENTYPE.WRSTR:
                 WRSTR();
                 break;
             case Token.TOKENTYPE.WRLN:
                 WRLN();
                 break;
             case Token.TOKENTYPE.WRINT:
                 WRINT();
                 break;
             case Token.TOKENTYPE.ID:
                 ID();
                 break;
             case Token.TOKENTYPE.IF:
                 IF();
                 break;
             case Token.TOKENTYPE.LOOP:
                 LOOP();
                 break;
             case Token.TOKENTYPE.EXIT:
                 m_tok = m_Tknzr.NextToken(); // consume token
                 goto case Token.TOKENTYPE.END;
             case Token.TOKENTYPE.ELSE:
             case Token.TOKENTYPE.END:
                 runloop = false;
                 break;   // exit
             default:
                 // Invalid token
                 ErrorHandler.Error(ERROR_CODE.TOKEN_INVALID, m_tok.m_iLineNum,
                     string.Format("Token {0} invalid\r\nExpected a proper keyword",
                     m_tok.m_tokType));
                 break;
         } // switch
     } // while
 }
Beispiel #18
0
 /// <summary>
 /// normal constructor with tokentype, lexeme and line number
 /// </summary>
 /// <param name="tok"></param>
 /// <param name="inName"></param>
 /// <param name="inLine"></param>
 public Token(Token.TOKENTYPE tok, string inName, int inLine)
 {
     m_tokType = tok;
     m_strName = inName;
     m_iLineNum = inLine;
 }