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

                if (SymbolTable.ContainsKey (name)) {
                    throw new SemanticError ("Variable with name " + name + " is already defined",
                    node.Children [0].Row, node.Children [0].Column);
                }

                string type = node.Children [1].Name;
                string value;

                //  If not explicitly initialized, variables are assigned an appropriate default value.
                if (type == "Int") {
                    value = "0";
                } else if (type == "Bool") {
                    value = "false";
                } else {
                    value = null;
                }

                SymbolTable.Add (name, new Symbol (name, type, value));

                // node.Children [2] is the value expression, check that the types match
                if (node.Children.Count == 3) {
                    VisitChildren (node.Children [2]);
                    string typeFromStack = TypeStack.Pop ();

                    if (typeFromStack != type) {
                        throw new SemanticError ("Expression value assigned for " + name +
                        " was not the same type of " + type, node.Children [2].Row,
                        node.Children [2].Column);
                    }
                }

            } catch (SemanticError error) {
                Errors.Add (error);
                TypeStack.Clear ();
            }
        }
        public void Visit(VarDeclStmt node)
        {
            string name = node.Children [0].Name;
            string type = node.Children [1].Name;
            string value;

            //  If not explicitly initialized, variables are assigned an appropriate default value.
            if (type == "Int") {
                value = "0";
            } else if (type == "Bool") {
                value = "false";
            } else {
                value = null;
            }

            // node.Children [2] is the value expression
            if (node.Children.Count == 3) {
                VisitChildren (node.Children [2]);
                value = ValueStack.Pop ().Value;
            }

            SymbolTable.Add (name, new Symbol (name, type, 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);
            }
        }