// // varDec: 'var' type varName (',' varName)* ';' public void CompileVarDec(int depth) { // compile: 'var' var varToken = Eat("var"); // compile: type var typeToken = EatType(); // compile: varName var varNameToken = EatIdentifier(); // Add to symbol table SymbolTableManager.AddToSubroutineSymbolTable(new SymbolTableItem { Kind = VarKindType.LOCAL, Name = varNameToken.Value, Scope = VarScopeType.SUBROUTINE_LEVEL, Type = typeToken.Value }); // compile: (',' varName)* while (_tokenizer.CurrentToken.Value == ",") { // compile: ',' var commaToken = Eat(","); // compile varName varNameToken = EatIdentifier(); // Add to symbol table SymbolTableManager.AddToSubroutineSymbolTable(new SymbolTableItem { Kind = VarKindType.LOCAL, Name = varNameToken.Value, Scope = VarScopeType.SUBROUTINE_LEVEL, Type = typeToken.Value }); } // compile: ';' var semiColonToken = Eat(";"); }
// // class: 'class' className '{' classVarDec* subroutineDec* '}' public void CompileClass(int depth) { // init class symbol table SymbolTableManager.ResetClassSymbolTable(); // compile 'class' var classToken = Eat("class"); // compile className var identifierToken = EatIdentifier(); className = identifierToken.Value; // compile '{' var leftBraceToken = Eat("{"); // compile classVarDec* while (_tokenizer.CurrentToken.GetKeywordType() == Types.KeywordType.STATIC || _tokenizer.CurrentToken.GetKeywordType() == Types.KeywordType.FIELD) { CompileClassVarDec(depth + 1); } // compile subroutineDec* while (_tokenizer.CurrentToken != null && (_tokenizer.CurrentToken.GetKeywordType() == Types.KeywordType.METHOD || _tokenizer.CurrentToken.GetKeywordType() == Types.KeywordType.FUNCTION || _tokenizer.CurrentToken.GetKeywordType() == Types.KeywordType.CONSTRUCTOR)) { CompileSubroutineDec(depth + 1, identifierToken.Value); } // compile '{' var rightBraceToken = Eat("}"); }
// // subroutineBody: '{' varDec* statements '}' public void CompileSubroutineBody(int depth, string subType, string subName, string className) { // compile: '{' var leftBraceToken = Eat("{"); // compile: varDec* while (_tokenizer.CurrentToken.Value == "var") { CompileVarDec(depth + 1); } _vmWriter.WriteFunction(string.Format("{0}.{1}", className, subName), SymbolTableManager.GetLocalsNum()); // if constructor -> allocate if (subType == "constructor") { int wordsToAllocate = SymbolTableManager.GetFieldsNum(); _vmWriter.WritePush("constant", wordsToAllocate); _vmWriter.WriteCall("Memory.alloc", 1); _vmWriter.WritePop("pointer", 0); } else if (subType == "method") { _vmWriter.WritePush("argument", 0); _vmWriter.WritePop("pointer", 0); } // compile: statements CompileStatements(depth + 1); // compile: '}' var rightBraceToken = Eat("}"); }
// // ('constructor'|'function'|'method') ('void'|type) subtroutineName '(' parameterList ')' subroutineBody public void CompileSubroutineDec(int depth, string className) { // Reset SymbolTable SymbolTableManager.ResetSubroutineSymbolTable(); // compile: ('constructor'|'function'|'method') var subToken = EatSubroutine(); if (subToken.Value != "function" && subToken.Value != "constructor") { SymbolTableManager.AddToSubroutineSymbolTable(new SymbolTableItem { Name = "this", Type = className, Scope = VarScopeType.SUBROUTINE_LEVEL, Kind = VarKindType.ARGUMENT }); } // compile: ('void'|type) var subTypeToken = SoftEatType() ?? Eat("void"); // compile: subtroutineName var subNameToken = EatIdentifier(); // compile: '(' var leftParenToken = Eat("("); // compile: parameterList CompileParameterList(depth + 1); // compile: ')' var rightParenToken = Eat(")"); // compile: subroutineBody CompileSubroutineBody(depth + 1, subToken.Value, subNameToken.Value, className); }
// // classVarDec: ('static'|'field') type varName (',' varName)* ';' public void CompileClassVarDec(int depth) { // compile: 'static' | 'field' var varKind = SoftEat("field") ?? Eat("static"); var stVarKind = (VarKindType)Enum.Parse(typeof(VarKindType), varKind.Value.ToUpper()); // compile: type var typeToken = EatType(); // compile: varName (',' varName)* while (true) { var varNameToken = EatIdentifier(); // Add to symbol table SymbolTableManager.AddToClassSymbolTable(new SymbolTableItem { Kind = stVarKind, Name = varNameToken.Value, Scope = VarScopeType.CLASS_LEVEL, Type = typeToken.Value }); if (_tokenizer.CurrentToken.Value == ",") { var commaToken = Eat(","); continue; } break; } // compile: ';' var semiColonToken = Eat(";"); }
// // 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); } } }
// // ( (type varName) (',' type varName)* )? public void CompileParameterList(int depth) { bool commaEncountered = false; // compile: ( (type varName) (',' type varName)* )? while (_tokenizer.CurrentToken.GetKeywordType() == Types.KeywordType.BOOLEAN || _tokenizer.CurrentToken.GetKeywordType() == Types.KeywordType.INT || _tokenizer.CurrentToken.GetKeywordType() == Types.KeywordType.CHAR || _tokenizer.CurrentToken.TokenType == TokenType.IDENTIFIER || // Handle Array and Object types commaEncountered) { // compile: type var typeToken = EatType(); // compile: varName var varNameToken = EatIdentifier(); // Add to symbol table SymbolTableManager.AddToSubroutineSymbolTable(new SymbolTableItem { Kind = VarKindType.ARGUMENT, Scope = VarScopeType.SUBROUTINE_LEVEL, Type = typeToken.Value, Name = varNameToken.Value }); // compile: ',' if (_tokenizer.CurrentToken.Value == ",") { var commaToken = Eat(","); commaEncountered = true; continue; } else { commaEncountered = false; } break; } }
// // 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); } } }