예제 #1
0
 private Expression BinaryExpressionCreate(BinaryOperationExpression exp, ref Stack <Token> sTokens)
 {
     if (sTokens.Peek().Name == "-" || sTokens.Peek().Name == "+")
     {
         exp.Operator = sTokens.Pop().Name;
     }
     else
     {
         throw new SyntaxErrorException("Operator '+' or '-' expected", sTokens.Pop());
     }
     if (sTokens.Peek().Name == "(")
     {
         sTokens.Pop();
         exp.Operand1 = BinaryExpressionCreate(new BinaryOperationExpression(), ref sTokens);
         if (sTokens.Pop().Name != ")")
         {
             throw new SyntaxErrorException("Missing ')' symbol", sTokens.Pop());
         }
     }
     else
     {
         if (Char.IsDigit(sTokens.Peek().Name, 0))
         {
             bool success          = false;
             NumericExpression num = new NumericExpression();
             success = Int32.TryParse(sTokens.Pop().Name, out num.Value);
             if (!success)
             {
                 throw new SyntaxErrorException("Invalid number", sTokens.Pop());
             }
             exp.Operand1 = num;
         }
         else if (Char.IsLetter(sTokens.Peek().Name, 0))
         {
             VariableExpression var2 = new VariableExpression();
             var2.Name    = sTokens.Pop().Name;
             exp.Operand1 = var2;
         }
         else
         {
             throw new SyntaxErrorException("Invalid variable or const", sTokens.Pop());
         }
     }
     if (sTokens.Peek().Name == "(")
     {
         sTokens.Pop();
         exp.Operand2 = BinaryExpressionCreate(new BinaryOperationExpression(), ref sTokens);
         if (sTokens.Pop().Name != ")")
         {
             throw new SyntaxErrorException("Missing ')' symbol", sTokens.Pop());
         }
     }
     else
     {
         if (Char.IsDigit(sTokens.Peek().Name, 0))
         {
             bool success          = false;
             NumericExpression num = new NumericExpression();
             success = Int32.TryParse(sTokens.Pop().Name, out num.Value);
             if (!success)
             {
                 throw new SyntaxErrorException("Invalid number", sTokens.Pop());
             }
             exp.Operand2 = num;
         }
         else if (Char.IsLetter(sTokens.Peek().Name, 0))
         {
             VariableExpression var2 = new VariableExpression();
             var2.Name    = sTokens.Pop().Name;
             exp.Operand2 = var2;
         }
         else
         {
             throw new SyntaxErrorException("Invalid variable or const", sTokens.Pop());
         }
     }
     return(exp);
 }
예제 #2
0
        //Generates assembly code for a simple assignment statement. Can accept only the following:
        //let <var> = <number>; e.g. let x = 5;
        //let <var> = <var>; e.g. let x = y;
        //let <var> = (<operator> <operand1> <operand2>); where operand1 and operand2 can only by either numbers or variables, but not nested expressions. e.g. let x = (- y 5);
        public List <string> GenerateCode(AssignmentStatement aSimple)
        {
            List <string> AssemblyList = new List <string>();

            if (aSimple.Value is NumericExpression)
            {
                AssemblyList = isNumaricAssigment(AssemblyList, aSimple);
            }
            else if (aSimple.Value is VariableExpression)
            {
                VariableExpression var = (VariableExpression)aSimple.Value;
                if (!symbolTable.ContainsKey(var.Name))
                {
                    throw new SyntaxErrorException("Undefined variable, please define the variable " + var.Name + " first.", new Token());
                }
                else
                {
                    AssemblyList = isVariableAssigment(AssemblyList, aSimple);
                }
            }
            else
            {
                BinaryOperationExpression temp = new BinaryOperationExpression();
                temp = (BinaryOperationExpression)aSimple.Value;
                if (temp.Operand1 is NumericExpression)
                {
                    AssemblyList.Add("@" + ((NumericExpression)temp.Operand1).Value);
                    AssemblyList.Add("D = A");
                    AssemblyList.Add("@OPERAND1");
                    AssemblyList.Add(" M = D");
                }
                else
                {
                    AssemblyList.Add("@" + symbolTable[((VariableExpression)temp.Operand1).Name]);
                    AssemblyList.Add("D = A");
                    AssemblyList.Add("@LOCAL");
                    AssemblyList.Add("D = D + M");
                    AssemblyList.Add("A = D");
                    AssemblyList.Add("D = M");
                    AssemblyList.Add("@OPERAND1");
                    AssemblyList.Add("M = D");
                }
                if (temp.Operand2 is NumericExpression)
                {
                    AssemblyList.Add("@" + ((NumericExpression)temp.Operand2).Value);
                    AssemblyList.Add("D = A");
                    AssemblyList.Add("@OPERAND2");
                    AssemblyList.Add("M = D");
                }
                else
                {
                    AssemblyList.Add("@" + symbolTable[((VariableExpression)temp.Operand2).Name]);
                    AssemblyList.Add("D = A");
                    AssemblyList.Add("@LOCAL");
                    AssemblyList.Add("D = D + M");
                    AssemblyList.Add("A = D");
                    AssemblyList.Add("D = M");
                    AssemblyList.Add("@OPERAND2");
                    AssemblyList.Add("M = D");
                }
                AssemblyList.Add("@OPERAND1");
                AssemblyList.Add(" D = M");
                AssemblyList.Add("@OPERAND2");
                if (temp.Operator == "+")
                {
                    AssemblyList.Add("D = D + M");
                }
                else
                {
                    AssemblyList.Add("D = D - M");
                }
                AssemblyList.Add("@RESULT");
                AssemblyList.Add("M = D");

                computeVariabletoR0(AssemblyList, aSimple.Variable.Name);
                updateDestinationWithResult(AssemblyList);
            }


            return(AssemblyList);
        }
예제 #3
0
        //Parses a stack of tokens, containing a single assignment statement.
        //The structure must be "let <var> = <expression>;" where expression can be of an arbitrary complexity, i.e., any complex expression is allowed.
        //Parsing must detect syntax problems (e.g. "let" or "=" are missing, opened parantheses are not closed, sentence does not end with a ;, and so forth).
        //When syntax errors are detected, a SyntaxErrorException must be thrown, with an appropriate message explaining the problem.
        public AssignmentStatement Parse(Stack <Token> sTokens)
        {
            Token popedToken = new Token();

            popedToken = sTokens.Pop();
            AssignmentStatement StatmentToReturn  = new AssignmentStatement();
            VariableExpression  variableWorkingOn = new VariableExpression(),
                                SecondVariable    = new VariableExpression();
            NumericExpression num = new NumericExpression();

            if (popedToken.Type != Token.TokenType.Keyword)
            {
                throw new SyntaxErrorException("We accept only LL(0) type, Unrecogmized KeyWord", popedToken);
            }
            popedToken = sTokens.Pop();
            if ((popedToken.Type == Token.TokenType.ID) && (popedToken.Name.ElementAt(0) >= '0') && (popedToken.Name.ElementAt(0) <= '9'))
            {
                throw new SyntaxErrorException("All variables can not start with a number", popedToken);
            }
            else if (popedToken.Name.Contains("?") || popedToken.Name.Contains("#") || popedToken.Name.Contains("@"))
            {
                throw new SyntaxErrorException("Variable can not contain the '?,#,@' signs", popedToken);
            }
            else if ((popedToken.Type != Token.TokenType.ID))
            {
                throw new SyntaxErrorException("Expecting a variable name", popedToken);
            }
            else
            {
                variableWorkingOn.Name    = popedToken.Name;
                StatmentToReturn.Variable = variableWorkingOn;
            }
            popedToken = sTokens.Pop();
            if (!popedToken.Name.Equals("="))
            {
                throw new SyntaxErrorException("Expecting a '=' sign", popedToken);
            }
            popedToken = sTokens.Pop();
            if (Char.IsDigit(popedToken.Name, 0))
            {
                bool success = false;
                success = Int32.TryParse(popedToken.Name, out num.Value);
                if (!success)
                {
                    throw new SyntaxErrorException("Invalid number", popedToken);
                }
                StatmentToReturn.Value = num;
            }
            else if (Char.IsLetter(popedToken.Name, 0))
            {
                SecondVariable.Name    = popedToken.Name;
                StatmentToReturn.Value = SecondVariable;
            }
            else if (popedToken.Name == "(")
            {
                StatmentToReturn.Value = BinaryExpressionCreate(new BinaryOperationExpression(), ref sTokens);
                if ((sTokens.Count > 0))
                {
                    if (sTokens.Pop().Name != ")")
                    {
                        throw new SyntaxErrorException("Missing ')' symbol", popedToken);
                    }
                }
            }
            else
            {
                throw new SyntaxErrorException("Invalid value", popedToken);
            }
            if (sTokens.Count > 1)
            {
                throw new SyntaxErrorException("Invalid value", popedToken);
            }
            if (sTokens.Count == 0 || (sTokens.Count == 1 && (sTokens.Pop().Name != ";")))
            {
                throw new SyntaxErrorException("Expecting ';' at the end of the statement", popedToken);
            }
            if (sTokens.Count > 0)
            {
                throw new SyntaxErrorException("No code after ';'", popedToken);
            }
            return(StatmentToReturn);
        }
예제 #4
0
        private Expression SimplifyExpressions(
            Expression expression,
            List <LetStatement> newLetStatements,
            List <VarDeclaration> lVars,
            bool isFirst
            )
        {
            Expression simplifiedExpression;
            var        binaryOperationExpression = expression as BinaryOperationExpression;

            if (binaryOperationExpression == null)
            {
                simplifiedExpression = expression;
            }
            else
            {
                var tempSimplifiedExpression = new BinaryOperationExpression
                {
                    Operator = binaryOperationExpression.Operator,

                    Operand1 = SimplifyExpressions(
                        binaryOperationExpression.Operand1,
                        newLetStatements,
                        lVars,
                        false
                        ),
                    Operand2 = SimplifyExpressions(
                        binaryOperationExpression.Operand2,
                        newLetStatements,
                        lVars,
                        false
                        )
                };

                if (tempSimplifiedExpression.Operand1 == binaryOperationExpression.Operand1 &&
                    tempSimplifiedExpression.Operand2 == binaryOperationExpression.Operand2)
                {
                    simplifiedExpression = binaryOperationExpression;
                }
                else
                {
                    simplifiedExpression = tempSimplifiedExpression;
                }

                if (!isFirst)
                {
                    string artificialVarName = $"_{m_cLocals}";
                    m_cLocals++;
                    lVars.Add(new VarDeclaration("int", artificialVarName));
                    newLetStatements.Add(new LetStatement
                    {
                        Variable = artificialVarName,
                        Value    = simplifiedExpression
                    });
                    simplifiedExpression = new VariableExpression
                    {
                        Name = artificialVarName
                    };
                }
            }

            return(simplifiedExpression);
        }
예제 #5
0
        private List <string> GenerateCodeForUnaryAssignment(LetStatement aSimple, Dictionary <string, int> dSymbolTable)
        {
            List <string> lAssembly = new List <string>();
            //add here code for computing a single let statement containing only a simple expression
            Expression value = aSimple.Value;

            if (value is NumericExpression)
            {
                lAssembly.Add("//Numeric Value " + aSimple);

                NumericExpression numExp = (NumericExpression)value;

                //next 8 lines rep @var
                lAssembly.Add("@LCL");
                lAssembly.Add("D=M");
                lAssembly.Add("@" + dSymbolTable[aSimple.Variable]);
                lAssembly.Add("D=A+D");//D=a's address
                lAssembly.Add("@_a");
                lAssembly.Add("M=D");
                lAssembly.Add("@" + RESULT);
                lAssembly.Add("M=D");

                lAssembly.Add("@" + numExp.Value);
                lAssembly.Add("D=A");
                lAssembly.Add("@_a");
                lAssembly.Add("A=M");
                lAssembly.Add("M=D");
                lAssembly.Add("@" + RESULT);
                lAssembly.Add("M=D");
            }
            else if (value is VariableExpression)
            {
                lAssembly.Add("//Variable value" + aSimple);

                //Example: let a = b;
                //LCL[a]=LCL[b]
                VariableExpression valExp = (VariableExpression)value;
                int valuesIndex           = dSymbolTable[valExp.ToString()];

                //first store value of LCL[b] in RESULT
                lAssembly.Add("@LCL");
                lAssembly.Add("D=M");
                lAssembly.Add("@" + dSymbolTable[valExp.ToString()]);
                lAssembly.Add("A=D+A");
                lAssembly.Add("D=M");
                lAssembly.Add("@" + RESULT);
                lAssembly.Add("M=D");

                //next store a's address in virtual register "_a"
                lAssembly.Add("@LCL");
                lAssembly.Add("D=M");
                lAssembly.Add("@" + dSymbolTable[valExp.ToString()]);
                lAssembly.Add("D=D+A");
                lAssembly.Add("@_a");
                lAssembly.Add("M=D");

                //update "a"
                lAssembly.Add("@" + RESULT);
                lAssembly.Add("D=M");
                lAssembly.Add("@_a");
                lAssembly.Add("A=M");
                lAssembly.Add("M=D");
            }

            return(lAssembly);
        }
예제 #6
0
        public List <LetStatement> SimplifyExpressions(LetStatement s, List <VarDeclaration> lVars)
        {
            //add here code to simply expressins in a statement.
            //add var declarations for artificial variables.
            //check that all vars appear in vardeclarations
            List <LetStatement> output = new List <LetStatement>();
            //first check that all vars in expression were declared;
            List <string> varNames = new List <string>();

            foreach (VarDeclaration varDec in lVars)
            {
                varNames.Add(varDec.Name);
            }
            if (!varNames.Contains(s.Variable))
            {
                throw new SyntaxErrorException(" the variable " + s.Variable + " was never defined in expression " + s, new Token());
            }
            CheckThatAllVariablesWereDeclared(s.Value, varNames);

            if (s.Value is BinaryOperationExpression)
            {
                //init data
                numVirtualVars = 0;
                Dictionary <Expression, int> registers = new Dictionary <Expression, int>();
                initVirtualIds(s.Value, registers);
                Stack <LetStatement> lets = new Stack <LetStatement>();
                initLetStatements(s.Value, registers, lets);


                BinaryOperationExpression binExp = (BinaryOperationExpression)(s.Value);
                BinaryOperationExpression binVal = new BinaryOperationExpression();

                // let OPERATOR1 = _xxx
                VariableExpression var1 = makeVariable("_" + registers[binExp.Operand1]);
                binVal.Operand1 = var1;
                LetStatement letOP1 = makeLetStatement(OPERAND1, var1);

                // let OPERATOR2 = _yyy
                VariableExpression var2 = makeVariable("_" + registers[binExp.Operand2]);
                binVal.Operand2 = var2;
                LetStatement letOP2 = makeLetStatement(OPERAND2, var2);

                // let RESULT= _1 and variable=RESULT
                LetStatement letResult = makeLetStatement(RESULT, makeVariable("_" + registers[s.Value]));
                LetStatement letVar    = makeLetStatement(s.Variable, makeVariable(RESULT));



                while (lets.Count > 0)
                {
                    output.Add(lets.Pop());
                }

                output.Add(letOP1);
                output.Add(letOP2);
                output.Add(letResult);
                output.Add(letVar);
            }
            else
            {
                //need to put in RESULT???
                output.Add(s);
            }

            return(output);
        }
예제 #7
0
        public List <string> GenerateCode(LetStatement aSimple, Dictionary <string, int> dSymbolTable)
        {
            List <string> lAssembly = new List <string>();

            lAssembly.Add("//generation started" + aSimple);

            //add here code for computing a single let statement containing only a simple expression
            Expression value    = aSimple.Value;
            string     variable = aSimple.Variable;

            if (value is NumericExpression | value is VariableExpression)
            {
                lAssembly.AddRange(GenerateCodeForUnaryAssignment(aSimple, dSymbolTable));
            }
            else if (value is BinaryOperationExpression)
            {
                lAssembly.Add("//Binary Expression" + aSimple);
                //
                //Example: a = b <op> c
                //first let a=b
                //next  let a=a <op> c
                //
                BinaryOperationExpression binExp = (BinaryOperationExpression)value;
                Expression   operand1            = binExp.Operand1;
                Expression   operand2            = binExp.Operand2;
                LetStatement letAEqualB          = makeLetStatement(variable, operand1);

                //let a=b
                lAssembly.AddRange(GenerateCodeForUnaryAssignment(letAEqualB, dSymbolTable));
                lAssembly.Add("@" + RESULT);
                lAssembly.Add("D=M");
                lAssembly.Add("@" + OPERAND1);
                lAssembly.Add("M=D");


                //let a = a <op> c
                if (operand2 is NumericExpression)
                {
                    lAssembly.Add("//Opearand 2 is Numeric " + aSimple);

                    NumericExpression num = (NumericExpression)operand2;
                    lAssembly.Add("@" + num.Value);
                    lAssembly.Add("D=A");
                    lAssembly.Add("@_a");
                    lAssembly.Add("M=M" + binExp.Operator + "D");
                    lAssembly.Add("D=M");
                    lAssembly.Add("@" + RESULT);
                    lAssembly.Add("M=D");
                }
                else if (operand2 is VariableExpression)
                {
                    lAssembly.Add("//Opearand 2 is a Variable " + aSimple);

                    VariableExpression c = (VariableExpression)operand2;
                    lAssembly.Add("@LCL");
                    lAssembly.Add("D=M");
                    lAssembly.Add("@" + dSymbolTable[c.Name]);
                    lAssembly.Add("D=M");
                    lAssembly.Add("@" + dSymbolTable[variable]);
                    lAssembly.Add("M=M" + binExp.Operator + "D");
                    lAssembly.Add("D=M");

                    lAssembly.Add("@" + RESULT);
                    lAssembly.Add("M=D");
                }
            }


            return(lAssembly);
        }