Ejemplo n.º 1
0
        public double Calculate()
        {
            //изчиствам стека, защото ще го ползвам за пресмятането
            stack.Clear();
            IEnumerator <Lexemе> iter = lexemesRPN.GetEnumerator();

            while (iter.MoveNext())
            {
                Lexemе lexeme = iter.Current;
                //ако поредния символ е операнд го пишем в стека
                if (!expressions.ContainsKey(lexeme.id))
                {
                    stack.Push(lexeme);
                }
                else
                {
                    //това е оператор, може да е унарен или да работи с две стойности
                    processSingleOperation(lexeme);
                }
            }
            return(stack.Pop().value);
            //TODO: провери дали стека е празен, защото ако не е празен и
            //израза не е бил само с постфиксни оператори значи има грешка
            //Console.WriteLine("                                      stack size: " + stack.Count);
            //Console.WriteLine("CODE FOR STATEMENT: " + this.ToString() + "\n" + asmCode + "\n");
        }
Ejemplo n.º 2
0
        //генерира асмеблерен код за целия израз (statement)
        public void generateAssembler(StringBuilder asmCode)
        {
            //изчиствам стека, защото ще го ползвам за генериране на асемблерния код
            stack.Clear();
            IEnumerator <Lexemе> iter = lexemesRPN.GetEnumerator();

            while (iter.MoveNext())
            {
                Lexemе lexeme = iter.Current;
                //ако поредния символ е операнд го пишем в стека
                if (!expressions.ContainsKey(lexeme.id))
                {
                    stack.Push(lexeme);
                }

                //това е оператор, може да е унарен или да работи с две стойности
                Assembler.Result result = Assembler.processSingleOperation(lexeme, stack);
                if (result != null)
                {
                    asmCode.Append(result.code);
                    if (result.savedIn == Assembler.Result.IN_SAVE_PLACE)
                    {
                        //индикация, че на тази позиция има нещо,
                        //чиято стойност е вече сметната
                        //и трябва да се вземе например от програмния стек
                        stack.Push(new Lexemе(intermediateLexemeSymbol, 0, 0,
                                              Assembler.getLastAddress(), Lexemе.NO_VALUE));
                    }
                }
            }
            //TODO: провери дали стека е празен, защото ако не е празен и
            //израза не е бил само с постфиксни оператори значи има грешка
            //Console.WriteLine("                                                              stack size: " + stack.Count);
            Console.WriteLine("CODE FOR STATEMENT: " + this.ToString() + "\n" + asmCode + "\n");
        }
Ejemplo n.º 3
0
 //Парсерът приема всеки знак '-' за аритметична операция, затова тук се проверява
 //дали всъщност знакът е бил унарен оператор.
 //Замяната на знака се налага заради операциите със стека на ОПЗ, да се знае дали
 //да се прилага операцията върху един или два операнда.
 private void checkUnaryMinus(LexemеSequence input, Lexemе lexeme)
 {
     if (lexeme.id == Lexemе.MINUS)
     {
         bool unary_sign = false;
         if (input.GetPosition() > 1)
         {
             char symbol = input.getLexemе(input.GetPosition() - 2).id;
             if ((symbol == Lexemе.ASSIGNMENT) ||
                 (symbol == Lexemе.OPEN_BRACE) ||
                 (symbol == Lexemе.SEMICOLON) ||
                 (symbol == Lexemе.BITWISE_AND) ||
                 (symbol == Lexemе.BITWISE_OR) ||
                 (symbol == Lexemе.PLUS) ||
                 (symbol == Lexemе.MINUS) ||
                 (symbol == Lexemе.MULTUPLICATION) ||
                 (symbol == Lexemе.DIVISION) ||
                 (symbol == Lexemе.MODUL) ||
                 (symbol == Lexemе.BITWISE_INVERSION) ||
                 (symbol == Lexemе.BOOLEAN_INVERSION))
             {
                 unary_sign = true;
             }
         }
         else
         {
             unary_sign = true;
         }
         if (unary_sign)
         {
             lexeme.id = Lexemе.UNARY_MINUS;
         }
     }
 }
Ejemplo n.º 4
0
 private void changeSymbol(LexemеSequence input, Lexemе lexeme, char search_symbol,
                           char replace_symbol)
 {
     if (lexeme.id == search_symbol)
     {
         //проверка дали предходната лексема е идентификатор
         if (input.GetPosition() > 1)
         {
             if (input.getLexemе(input.GetPosition() - 2).id == Lexemе.IDENTIFIER)
             {
                 lexeme.id = replace_symbol;
                 return;
             }
         }
         //проверка дали следващата лексема е идентификатор
         if (input.GetPosition() < input.size())
         {
             char symb = input.peekLexemе().id;
             if (input.peekLexemе().id == Lexemе.IDENTIFIER)
             {
                 return;
             }
             else
             {
                 throw new TranslatorException("Error 1: Expression " + search_symbol +
                                               " can be applyed only to identifier.");
             }
         }
         throw new TranslatorException("Error 2: Expression " + search_symbol +
                                       " can be applyed only to identifier.");
     }
 }
Ejemplo n.º 5
0
        //Обработва Statement по Statement и генерира асемблерен код.
        public bool parseStatements(LexemеSequence input)
        {
            //входната поредица ще се обработва израз по израз (разделени са с ';')
            Lexemе lexemе = null;

            try
            {
                asmCode.Append(Assembler.asmHeader);
                input.rewind();
                int       input_size = input.size();
                Statement stmt       = new Statement();
                //съдържа идентификаторите с постфиксни ++ и --
                Statement postfixOperations = new Statement();
                for (int i = 0; i < input_size; i++)
                {
                    lexemе = input.getLexemе();
                    if (lexemе.id != Lexemе.SEMICOLON)
                    {
                        incAndDecOperatorDeal(input, lexemе);
                        checkUnaryMinus(input, lexemе);
                        checkUnaryPlus(input, lexemе);
                        stmt.convertIntoRPN(lexemе, postfixOperations);
                    }
                    else
                    {
                        //прехвърля всичко от стека на изходната редица
                        stmt.completeRPN();
                        //израза се преобразува в асемблерен код
                        stmt.generateAssembler(asmCode);
                        postfixOperations.generateAssembler(asmCode);
                        stmt = new Statement();
                        postfixOperations = new Statement();
                    }
                }
                asmCode.Append(Assembler.returnDOS);
                asmCode.Append(Assembler.getIncludedProcsCode());
                asmCode.Append(Assembler.asmFooter);
                Console.WriteLine("\nASSEMBLER CODE:\n" + asmCode);
            }
            catch (TranslatorException e)
            {
                if (lexemе != null)
                {
                    Console.WriteLine(String.Format("Error at line {0}, position {1}: {2}",
                                                    lexemе.row, lexemе.positionAtRow, e.Message));
                }
                if (Startup.DEBUG)
                {
                    Console.WriteLine(e.StackTrace);
                }
                return(false);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
                return(false);
            }
            return(true);
        }
Ejemplo n.º 6
0
        //Обработва Statement по Statement
        public bool parseStatements(LexemеSequence input)
        {
            //входната поредица ще се обработва израз по израз (разделени са с ';')
            Lexemе lexemе = null;

            try
            {
                input.Rewind();
                int       input_size = input.Size();
                Statement stmt       = new Statement();
                //съдържа идентификаторите с постфиксни ++ и --
                for (int i = 0; i < input_size; i++)
                {
                    lexemе = input.GetLexemе();
                    if (lexemе.id != Lexemе.SEMICOLON)
                    {
                        checkUnaryMinus(input, lexemе);
                        checkUnaryPlus(input, lexemе);
                        stmt.convertIntoRPN(lexemе);
                    }
                    else
                    {
                        //вече е създаден ОПЗ, ще смятам резултата
                        //прехвърля всичко от стека на изходната редица
                        stmt.completeRPN();
                        //смятам резултата
                        result = stmt.Calculate();
                        stmt   = new Statement();
                    }
                }
            }
            catch (CalculatorException e)
            {
                if (lexemе != null)
                {
                    Console.WriteLine(String.Format("Error at line {0}, position {1}: {2}",
                                                    lexemе.row, lexemе.positionAtRow, e.Message));
                }
                if (Startup.DEBUG)
                {
                    Console.WriteLine(e.StackTrace);
                }
                return(false);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
                return(false);
            }
            return(true);
        }
Ejemplo n.º 7
0
 private static String getAddressOrValue(Lexemе lexeme)
 {
     if (lexeme.id == Statement.intermediateLexemeSymbol)
     {
         //това е on-the-fly стойност
         return(String.Format(savePlace, lexeme.address));
     }
     else if (lexeme.id == Lexemе.IDENTIFIER)
     {
         return(String.Format("dword ptr [ebp+{0}]", lexeme.address));
     }
     else if (lexeme.id == Lexemе.NUMBER)
     {
         return(lexeme.value.ToString());
     }
     else
     {
         throw new TranslatorException("Error 1005: no match found for symbol: " +
                                       lexeme.id);
     }
 }
Ejemplo n.º 8
0
        private void assignmentOperatorDeal()
        {
            //претърсват се символите от изходната редица и ако има различни
            //от идентификатор или знак '=' значи има семантична грешка
            //По този начин е възможен следния израз:
            //A = B = (C) = scanf();
            //но не и например:
            //A = B + 2 = (C) = scanf();
            IEnumerator <Lexemе> iter = lexemesRPN.GetEnumerator();

            while (iter.MoveNext())
            {
                Lexemе lexeme = iter.Current;
                if (lexeme.id != Lexemе.ASSIGNMENT &&
                    lexeme.id != Lexemе.IDENTIFIER &&
                    lexeme.id != Lexemе.OPEN_BRACE &&
                    lexeme.id != Lexemе.CLOSE_BRACE)
                {
                    throw new CalculatorException("Left of assigment sign '=' can be only identifier.");
                }
            }
        }
Ejemplo n.º 9
0
        public void convertIntoRPN(Lexemе lexeme)
        {
            Expression expression_sign = null;

            //ако поредния символ е операнд или константа го пишем направо на изходната редица
            if (expressions.TryGetValue(lexeme.id, out expression_sign) == false)
            {
                lexemesRPN.Add(lexeme);
            }
            else
            {
                //това е оператор
                if (expression_sign.id == Lexemе.CLOSE_BRACE)
                {
                    //проверка дали има други оператори в стека
                    if (stack.Count > 0)
                    {
                        //затварящата скоба предизвиква изхвърляне на символи от стека
                        //докато се срещне отваряща скоба. Двете се унищожават.
                        //взима се лексемата от върха на стека
                        Lexemе TOS_lexeme = stack.Peek();
                        //стекът не е празен
                        Expression TOS_expression_sign = expressions[TOS_lexeme.id];
                        while (TOS_expression_sign.id != Lexemе.OPEN_BRACE)
                        {
                            //предизвиква се изхвърляне на символи от стека към изходната редица
                            TOS_lexeme = stack.Pop();
                            lexemesRPN.Add(TOS_lexeme);
                            //поглежда се какъв е следващия символ от стека
                            if (stack.Count > 0)
                            {
                                TOS_lexeme          = stack.Peek();
                                TOS_expression_sign = expressions[TOS_lexeme.id];
                            }
                            else
                            {
                                //стекът вече е празен
                                throw new CalculatorException(
                                          "Error 1: Closing brace encountered with no corresponding open brace while converting to RPN.");
                            }
                        }
                        //премахва се отварящата скоба от стека
                        stack.Pop();
                    }
                    else
                    {
                        throw new CalculatorException(
                                  "Error 2: Closing brace encountered with no corresponding open brace while converting to RPN.");
                    }
                }
                else
                {
                    //проверка за празен стек
                    if (stack.Count > 0)
                    {
                        //обработват се останалите лексеми
                        //взима се лексемата от върха на стека
                        Lexemе TOS_lexeme = stack.Peek();
                        //стекът не е празен
                        Expression TOS_expression_sign = expressions[TOS_lexeme.id];
                        while (expression_sign.outOfStackPriority <= TOS_expression_sign.inStackPriority)
                        {
                            //текущият символ е с по-нисък или равен приоритет и ще
                            //предизвика изхвърляне на символи от стека към изходната редица
                            TOS_lexeme = stack.Pop();
                            lexemesRPN.Add(TOS_lexeme);
                            //поглежда се какъв е следващия символ от стека
                            if (stack.Count > 0)
                            {
                                TOS_lexeme          = stack.Peek();
                                TOS_expression_sign = expressions[TOS_lexeme.id];
                            }
                            else
                            {
                                break;                                  //стекът вече е празен
                            }
                        }
                    }
                    stack.Push(lexeme);
                }
                if (expression_sign.id == Lexemе.ASSIGNMENT)
                {
                    assignmentOperatorDeal();
                }
            }
        }
Ejemplo n.º 10
0
        public void processSingleOperation(Lexemе lexeme)
        {
            switch (lexeme.id)
            {
            case Lexemе.PLUS:
            {
                Lexemе right_side_lexeme = stack.Pop();
                Lexemе left_side_lexeme  = stack.Pop();
                stack.Push(new Lexemе(Lexemе.NUMBER,
                                      right_side_lexeme.value + left_side_lexeme.value));
                break;
            }

            case Lexemе.ASSIGNMENT:
            {
                Lexemе right_side_lexeme = stack.Pop();
                Lexemе left_side_lexeme  = stack.Peek();
                left_side_lexeme.value = right_side_lexeme.value;
                break;
            }

            case Lexemе.MINUS:
            {
                Lexemе right_side_lexeme = stack.Pop();
                Lexemе left_side_lexeme  = stack.Pop();
                stack.Push(new Lexemе(Lexemе.NUMBER,
                                      left_side_lexeme.value - right_side_lexeme.value));
                break;
            }

            case Lexemе.UNARY_MINUS:
            {
                Lexemе only_side_lexeme = stack.Pop();
                stack.Push(new Lexemе(Lexemе.NUMBER,
                                      -only_side_lexeme.value));
                break;
            }

            case Lexemе.MULTUPLICATION:
            {
                Lexemе right_side_lexeme = stack.Pop();
                Lexemе left_side_lexeme  = stack.Pop();
                stack.Push(new Lexemе(Lexemе.NUMBER,
                                      right_side_lexeme.value * left_side_lexeme.value));
                break;
            }

            case Lexemе.DIVISION:
            {
                Lexemе right_side_lexeme = stack.Pop();
                Lexemе left_side_lexeme  = stack.Pop();
                stack.Push(new Lexemе(Lexemе.NUMBER,
                                      left_side_lexeme.value / right_side_lexeme.value));
                break;
            }

            case Lexemе.MODUL:
            {
                Lexemе right_side_lexeme = stack.Pop();
                Lexemе left_side_lexeme  = stack.Pop();
                stack.Push(new Lexemе(Lexemе.NUMBER,
                                      left_side_lexeme.value % right_side_lexeme.value));
                break;
            }
            }
        }
Ejemplo n.º 11
0
        //генерира асемблерен код за единичен оператор
        public static Result processSingleOperation(Lexemе lexeme, Stack <Lexemе> stack)
        {
            switch (lexeme.id)
            {
            case Lexemе.PLUS:
            {
                Lexemе right_side_lexeme = stack.Pop();
                Lexemе left_side_lexeme  = stack.Pop();
                return(new Result(doPlus(getAddressOrValue(right_side_lexeme),
                                         getAddressOrValue(left_side_lexeme)), Result.IN_SAVE_PLACE));
            }

            case Lexemе.ASSIGNMENT:
            {
                Lexemе right_side_lexeme = stack.Pop();
                Lexemе left_side_lexeme  = stack.Peek();
                return(new Result(doAssignment(getAddressOrValue(right_side_lexeme),
                                               getAddressOrValue(left_side_lexeme)), Result.IN_MEMORY));
            }

            case Lexemе.MINUS:
            {
                Lexemе right_side_lexeme = stack.Pop();
                Lexemе left_side_lexeme  = stack.Pop();
                return(new Result(doMinus(getAddressOrValue(right_side_lexeme),
                                          getAddressOrValue(left_side_lexeme)), Result.IN_SAVE_PLACE));
            }

            case Lexemе.PREFIX_INCREMENT:
            case Lexemе.POSTFIX_INCREMENT:
            {
                Lexemе only_side_lexeme = stack.Peek();
                return(new Result(doIncrement(getAddressOrValue(only_side_lexeme)),
                                  Result.IN_MEMORY));
            }

            case Lexemе.PREFIX_DECREMENT:
            case Lexemе.POSTFIX_DECREMENT:
            {
                Lexemе only_side_lexeme = stack.Peek();
                return(new Result(doDecrement(getAddressOrValue(only_side_lexeme)),
                                  Result.IN_MEMORY));
            }

            case Lexemе.BITWISE_INVERSION:
            {
                Lexemе only_side_lexeme = stack.Pop();
                return(new Result(doBitwiseInversion(getAddressOrValue(only_side_lexeme)),
                                  Result.IN_SAVE_PLACE));
            }

            case Lexemе.BITWISE_AND:
            {
                Lexemе right_side_lexeme = stack.Pop();
                Lexemе left_side_lexeme  = stack.Pop();
                return(new Result(doBitwiseAnd(getAddressOrValue(right_side_lexeme),
                                               getAddressOrValue(left_side_lexeme)), Result.IN_SAVE_PLACE));
            }

            case Lexemе.BITWISE_OR:
            {
                Lexemе right_side_lexeme = stack.Pop();
                Lexemе left_side_lexeme  = stack.Pop();
                return(new Result(doBitwiseOr(getAddressOrValue(right_side_lexeme),
                                              getAddressOrValue(left_side_lexeme)), Result.IN_SAVE_PLACE));
            }

            case Lexemе.BOOLEAN_INVERSION:
            {
                Lexemе only_side_lexeme = stack.Pop();
                return(new Result(doBooleanInversion(getAddressOrValue(only_side_lexeme)),
                                  Result.IN_SAVE_PLACE));
            }

            case Lexemе.UNARY_MINUS:
            {
                Lexemе only_side_lexeme = stack.Pop();
                return(new Result(doUnaryMinus(getAddressOrValue(only_side_lexeme)),
                                  Result.IN_SAVE_PLACE));
            }

            case Lexemе.MULTUPLICATION:
            {
                Lexemе right_side_lexeme = stack.Pop();
                Lexemе left_side_lexeme  = stack.Pop();
                return(new Result(doMultiplication(getAddressOrValue(right_side_lexeme),
                                                   getAddressOrValue(left_side_lexeme)), Result.IN_SAVE_PLACE));
            }

            case Lexemе.DIVISION:
            {
                Lexemе right_side_lexeme = stack.Pop();
                Lexemе left_side_lexeme  = stack.Pop();
                return(new Result(doDivision(getAddressOrValue(right_side_lexeme),
                                             getAddressOrValue(left_side_lexeme)), Result.IN_SAVE_PLACE));
            }

            case Lexemе.MODUL:
            {
                Lexemе right_side_lexeme = stack.Pop();
                Lexemе left_side_lexeme  = stack.Pop();
                return(new Result(doModul(getAddressOrValue(right_side_lexeme),
                                          getAddressOrValue(left_side_lexeme)), Result.IN_SAVE_PLACE));
            }

            case Lexemе.PRINTF:
            {
                Lexemе only_side_lexeme = stack.Pop();
                return(new Result(doPrintf(getAddressOrValue(only_side_lexeme)),
                                  Result.IN_MEMORY));
            }

            case Lexemе.SCANF:
            {
                stack.Pop();
                return(new Result(doScanf(),
                                  Result.IN_SAVE_PLACE));
            }
            }
            return(null);
        }
Ejemplo n.º 12
0
 //Открива и заменя постфиксни ++ и -- с префиксни при необходимост.
 //Парсерът приема тези оператори винаги за префиксни, затова тук се прави проверката дали
 //всъщност са суфиксни, при което идентификатора на лексемата ще се смени със съответния й.
 private void incAndDecOperatorDeal(LexemеSequence input, Lexemе lexeme)
 {
     changeSymbol(input, lexeme, Lexemе.PREFIX_INCREMENT, Lexemе.POSTFIX_INCREMENT);
     changeSymbol(input, lexeme, Lexemе.PREFIX_DECREMENT, Lexemе.POSTFIX_DECREMENT);
 }