コード例 #1
0
        //
        // 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(";");
        }
コード例 #2
0
        //
        // 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("}");
        }
コード例 #3
0
        //
        // 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("}");
        }
コード例 #4
0
        //
        // ('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);
        }
コード例 #5
0
        //
        // 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(";");
        }
コード例 #6
0
        //
        // 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(";");
        }
コード例 #7
0
        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);
                }
            }
        }
コード例 #8
0
        //
        // ( (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;
            }
        }
コード例 #9
0
        //
        // 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);
        }
コード例 #10
0
        //
        // 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);
                }
            }
        }