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); }
//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); }
//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); }
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); }
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); }
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); }
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); }