// // letStatement: 'let' varName ('[' expression ']')? '=' expression ';' public void CompileLetStatement(int depth) { bool isLeftArray = false; // compile: 'let' var letToken = Eat("let"); // compile: varName var varNameToken = EatIdentifier(); var sbVarName = SymbolTableManager.Find(varNameToken.Value); // compile: ('[' expression ']')? if (_tokenizer.CurrentToken.Value == "[") { isLeftArray = true; // compile: '[' var leftBracketToken = Eat("["); // compile: expression CompileExpression(depth + 1, AssignmentType.LEFT); // write array _vmWriter.WritePush(sbVarName.KindDisplay, sbVarName.Number); _vmWriter.WriteOp(new Token { Value = "+" }); // compile: ']' var rightBracketToken = Eat("]"); } // compile: '=' var assignmentToken = Eat("="); // compile: expression CompileExpression(depth + 1, AssignmentType.RIGHT); // pop varAssigned if (isLeftArray) { _vmWriter.WritePop("temp", 0); _vmWriter.WritePop("pointer", 1); _vmWriter.WritePush("temp", 0); _vmWriter.WritePop("that", 0); } else { _vmWriter.WritePop(sbVarName.KindDisplay, sbVarName.Number); } // compile: ';' var semiColonToken = Eat(";"); }
public void WriteExpr(CompilationUnit compUnit) { var compUnits = compUnit.CompUnits; if (compUnits.Count == 1) { Token token = compUnits[0]; if (token.TokenType == TokenType.INT_CONST) { _vmWriter.WritePush("constant", Convert.ToInt32(token.Value)); } else if (token.TokenType == TokenType.IDENTIFIER) { var sbUnit = SymbolTableManager.Find(token.Value); _vmWriter.WritePush(sbUnit.Kind.ToString(), sbUnit.Number); } } }
// // subroutineCall: subroutineName '(' expressionList ')' | (className | varName) '.' subroutineName '(' expressionList '}' public void CompileSubroutineCall(int depth) { int args = 0; int argadder = 0; string sbSubName = string.Empty; var nextToken = _tokenizer.Peek(); // compile: subroutineName '(' expressionList ')' if (nextToken.Value == "(") { argadder = 1; // compile: subroutineName var subName = EatIdentifier(); sbSubName = className + "." + subName.Value; // handle: push 'this' to stack -> push pointer 0 _vmWriter.WritePush("pointer", 0); // compile: '(' var leftParenToken = Eat("("); // compile: expressionList args = CompileExpressionList(depth) + argadder; // compile: ')' var rightParenToken = Eat(")"); } else if (nextToken.Value == ".") { // compile: (className | varName) var nameToken = EatIdentifier(); var sbClass = SymbolTableManager.Find(nameToken.Value); if (sbClass == null) { // handle: class.function(...) sbSubName = nameToken.Value; } else { // handle: obj.method(...) argadder = 1; sbSubName = sbClass.Type; var sbObj = SymbolTableManager.Find(nameToken.Value); _vmWriter.WritePush(sbObj.KindDisplay, sbObj.Number); } // compile '.' var dotToken = Eat("."); sbSubName += dotToken.Value; // compile: subroutineName var subNameToken = EatIdentifier(); sbSubName += subNameToken.Value; // compile: '(' var leftParenToken = Eat("("); // compile: expression args = CompileExpressionList(depth) + argadder; // compile: ')' var rightParenToken = Eat(")"); } // write call _vmWriter.WriteCall(sbSubName, args); }
// // term : integerConstant | stringConstant | keywordConstant | unaryOp term | '(' expression ')' | varName | varName '[' expression ']' | subroutineCall public void CompileTerm(int depth, AssignmentType assignType) { // compile: integerConstant if (_tokenizer.CurrentToken.TokenType == TokenType.INT_CONST) { _vmWriter.WritePush("constant", Convert.ToInt32(_tokenizer.CurrentToken.Value)); _tokenizer.Advance(); } // compile: stringConstant else if (_tokenizer.CurrentToken.TokenType == TokenType.STRING_CONST) { int strLen = _tokenizer.CurrentToken.Value.Length; _vmWriter.WritePush("constant", strLen); _vmWriter.WriteCall("String.new", 1); foreach (char strChar in _tokenizer.CurrentToken.Value) { _vmWriter.WritePush("constant", (int)strChar); _vmWriter.WriteCall("String.appendChar", 2); } _tokenizer.Advance(); } // compile: keywordConstant else if (_tokenizer.CurrentToken.GetKeywordType() == Types.KeywordType.TRUE || _tokenizer.CurrentToken.GetKeywordType() == Types.KeywordType.FALSE || _tokenizer.CurrentToken.GetKeywordType() == Types.KeywordType.NULL || _tokenizer.CurrentToken.GetKeywordType() == Types.KeywordType.THIS) { if (_tokenizer.CurrentToken.GetKeywordType() == KeywordType.TRUE) { _vmWriter.WritePush("constant", 0); _vmWriter.WriteUnaryOp(new Token { Value = "~" }); } if (_tokenizer.CurrentToken.GetKeywordType() == KeywordType.FALSE) { _vmWriter.WritePush("constant", 0); } if (_tokenizer.CurrentToken.GetKeywordType() == KeywordType.THIS) { _vmWriter.WritePush("pointer", 0); } if (_tokenizer.CurrentToken.GetKeywordType() == KeywordType.NULL) { _vmWriter.WritePush("constant", 0); } _tokenizer.Advance(); } // compile: unaryOp term else if (_tokenizer.CurrentToken.Value == "~" || _tokenizer.CurrentToken.Value == "-") { // compile: unaryOp var unaryOpToken = _tokenizer.CurrentToken; _tokenizer.Advance(); // compile: term CompileTerm(depth + 1, assignType); // write op _vmWriter.WriteUnaryOp(unaryOpToken); } // compile: '(' expression ')' else if (_tokenizer.CurrentToken.Value == "(") { // compile '(' var leftParenToken = Eat("("); // compile: expression CompileExpression(depth + 1, assignType); // compile: ')' var rightParenToken = Eat(")"); } // compile: varName | varName '[' expression ']' | subroutineCall '(' expression ')' else if (_tokenizer.CurrentToken.TokenType == TokenType.IDENTIFIER) { var nextToken = _tokenizer.Peek(); var sbVarName = SymbolTableManager.Find(_tokenizer.CurrentToken.Value); // compile: varName '[' expression ']' if (nextToken.Value == "[") { // compile: varName var varNameToken = EatIdentifier(); // compile: '[' var leftBracketToken = Eat("["); // compile: expression CompileExpression(depth + 1, assignType); _vmWriter.WritePush(sbVarName.KindDisplay, sbVarName.Number); _vmWriter.WriteOp(new Token { Value = "+" }); // add offset _vmWriter.WritePop("pointer", 1); _vmWriter.WritePush("that", 0); // compile: ']' var rightBracketToken = Eat("]"); } // compile: subroutineCall else if (nextToken.Value == "(" || nextToken.Value == ".") { CompileSubroutineCall(depth + 1); } // compile: varName else { var varNameToken = EatIdentifier(); _vmWriter.WritePush(sbVarName.KindDisplay, sbVarName.Number); } } }