public void Visit(AssignmentStmt node)
        {
            try {
                string name = node.Children [0].Name;

                if (!SymbolTable.ContainsKey (name)) {
                    throw new SemanticError ("Variable " + name +
                    " needs to be declared before use", node.Children [0].Row,
                        node.Children [0].Column);
                }

                // check if the assigned expression is of the same type as the variable in symbol table
                VisitChildren (node.Children [1]);
                string type = TypeStack.Pop ();

                if (type != SymbolTable [name].Type) {
                    throw new SemanticError ("Variable " + name + " of type " + SymbolTable [name].Type +
                    " can not be assigned a value of type " + type, node.Children [0].Row, node.Children [0].Column);
                }
            } catch (SemanticError error) {
                Errors.Add (error);
                TypeStack.Clear ();
            }
        }
        public void Visit(AssignmentStmt node)
        {
            string name = node.Children [0].Name;

            // visit the children, the value should be on top of the stack after that
            VisitChildren (node.Children [1]);
            StackValue stackValue = ValueStack.Pop ();
            // update the value in symbol table
            SymbolTable [name].Value = stackValue.Value;
        }
        private Statement Stmt()
        {
            switch ((Token.Types)currentToken.Type) {
                case Token.Types.Var:
                    VarDeclStmt varDeclStmt = new VarDeclStmt ("VarDecl", currentToken.Row, currentToken.Column);
                    Match (Token.Types.Var);
                    varDeclStmt.AddChild (IdentifierNameStmt ());
                    Match (Token.Types.Colon);
                    varDeclStmt.AddChild (Type ());

                    if ((Token.Types)currentToken.Type == Token.Types.Assign) {
                        Match (Token.Types.Assign);
                        varDeclStmt.AddChild (Expr ());
                        return varDeclStmt;
                    } else if ((Token.Types)currentToken.Type == Token.Types.Semicolon) {
                        return varDeclStmt;
                    }

                    throw new SyntaxError ("Expected Assign, got: " + currentToken.Type, currentToken.Row, currentToken.Column);
                case Token.Types.Identifier:
                    AssignmentStmt assignmentStmt = new AssignmentStmt ("AssignmentStmt", currentToken.Row, currentToken.Column);
                    assignmentStmt.AddChild (IdentifierNameStmt ());
                    Match (Token.Types.Assign);
                    assignmentStmt.AddChild (Expr ());
                    return assignmentStmt;
                case Token.Types.For:
                    ForStmt forStmt = new ForStmt ("ForStmt", currentToken.Row, currentToken.Column);
                    Match (Token.Types.For);
                    forStmt.AddChild (IdentifierNameStmt ());
                    Match (Token.Types.In);
                    forStmt.AddChild (Expr ());
                    Match (Token.Types.Range);
                    forStmt.AddChild (Expr ());
                    Match (Token.Types.Do);
                    forStmt.AddChild (Stmts ());
                    Match (Token.Types.End);
                    Match (Token.Types.For);
                    return forStmt;
                case Token.Types.Read:
                    ReadStmt readStmt = new ReadStmt ("ReadStmt", currentToken.Row, currentToken.Column);
                    Match (Token.Types.Read);
                    readStmt.AddChild (IdentifierNameStmt ());
                    return readStmt;
                case Token.Types.Print:
                    PrintStmt printStmt = new PrintStmt ("PrintStmt", currentToken.Row, currentToken.Column);
                    Match (Token.Types.Print);
                    printStmt.AddChild (Expr ());
                    return printStmt;
                case Token.Types.Assert:
                    AssertStmt assertStmt = new AssertStmt ("AssertStmt", currentToken.Row, currentToken.Column);
                    Match (Token.Types.Assert);
                    Match (Token.Types.LeftParenthesis);
                    assertStmt.AddChild (Expr ());
                    Match (Token.Types.RightParenthesis);
                    return assertStmt;
                default:
                    throw new SyntaxError ("invalid start symbol for statement " + currentToken.Lexeme,
                        currentToken.Row, currentToken.Column);
            }
        }