public void visitVarDeclaration(VarDeclarationNode node)
        {
            IdentifierNode identifier   = (IdentifierNode)node.getChildren()[0];
            string         variableName = identifier.getVariableName();

            if (this.forLoopControlVariables.Count > 0)
            {
                throw new SemanticException("Declaring variables inside for loop is not allowed.");
            }
            if (variableAlreadyDeclared(variableName))
            {
                throw new SemanticException("Variable '" + variableName + "' already declared.");
            }
            TypeNode typeNode = (TypeNode)node.getChildren()[1];

            MiniPLTokenType type = (MiniPLTokenType)typeNode.getValue();

            if (type == MiniPLTokenType.TYPE_IDENTIFIER_INTEGER)
            {
                this.symbolTable.addVariable(variableName, 0);
            }
            else if (type == MiniPLTokenType.TYPE_IDENTIFIER_STRING)
            {
                this.symbolTable.addVariable(variableName, "");
            }
            else if (type == MiniPLTokenType.TYPE_IDENTIFIER_BOOL)
            {
                this.symbolTable.addVariable(variableName, false);
            }
            else
            {
                throw new Exception("Unknown type usage in semantic analyzer.");
            }
        }
        private void updateValue(INode node)
        {
            IdentifierNode identifier   = (IdentifierNode)node.getChildren()[0];
            string         variableName = identifier.getVariableName();
            INode          possibleNode = node.getChildren()[1];

            foreach (INode child in possibleNode.getChildren())
            {
                child.accept(this);
            }
            if (this.symbolTable.hasInteger(variableName))
            {
                this.symbolTable.updateVariable(variableName, popInt());
                this.intType = false;
            }
            else if (this.symbolTable.hasString(variableName))
            {
                this.symbolTable.updateVariable(variableName, popString());
                this.strType = false;
            }
            else if (this.symbolTable.hasBool(variableName))
            {
                this.symbolTable.updateVariable(variableName, popBool());
            }
        }
        public void visitVarDeclaration(VarDeclarationNode node)
        {
            IdentifierNode  identifier   = (IdentifierNode)node.getChildren()[0];
            string          variableName = identifier.getVariableName();
            TypeNode        typeNode     = (TypeNode)node.getChildren()[1];
            MiniPLTokenType type         = (MiniPLTokenType)typeNode.getValue();

            typeCheck(typeNode, type);
        }
        public void visitIdentifier(IdentifierNode node)
        {
            string variableName = node.getVariableName();

            if (!this.symbolTable.hasVariable(variableName))
            {
                throw new SemanticException("Variable '" + variableName + "' has not been declared.");
            }
        }
        public void visitRead(ReadNode readNode)
        {
            IdentifierNode identifier   = (IdentifierNode)readNode.getChildren()[0];
            string         variableName = identifier.getVariableName();

            if (!this.symbolTable.hasInteger(variableName) && !this.symbolTable.hasString(variableName))
            {
                throw new SemanticException("Wrong type in read statement. Trying to read input to variable " + variableName + ". Read statement can read only integers and strings.");
            }
        }
 public void visitIdentifier(IdentifierNode node)
 {
     if (!this.symbolTable.hasVariable(node.getVariableName()))
     {
         throw new SemanticException("Variable has not been declared.");
     }
     else
     {
         if (this.symbolTable.hasInteger(node.getVariableName()))
         {
             this.typeStack.Push(MiniPLTokenType.TYPE_IDENTIFIER_INTEGER);
         }
         if (this.symbolTable.hasString(node.getVariableName()))
         {
             this.typeStack.Push(MiniPLTokenType.TYPE_IDENTIFIER_STRING);
         }
         if (this.symbolTable.hasBool(node.getVariableName()))
         {
             this.typeStack.Push(MiniPLTokenType.TYPE_IDENTIFIER_BOOL);
         }
     }
 }
        public void visitForLoop(ForLoopNode node)
        {
            IdentifierNode identifier   = (IdentifierNode)node.getChildren()[0];
            string         variableName = identifier.getVariableName();

            if (!variableAlreadyDeclared(variableName))
            {
                throw new SemanticException("The control variable '" + variableName + "' in for loop has not been declared.");
            }
            this.forLoopControlVariables.Push(variableName);
            node.getChildren()[2].accept(this);
            this.forLoopControlVariables.Pop();
        }
        public void visitRead(ReadNode node)
        {
            IdentifierNode identifier   = (IdentifierNode)node.getChildren()[0];
            string         variableName = identifier.getVariableName();

            if (this.symbolTable.hasInteger(variableName))
            {
                this.symbolTable.updateVariable(variableName, readInteger());
            }
            else if (this.symbolTable.hasString(variableName))
            {
                this.symbolTable.updateVariable(variableName, readString());
            }
        }
        public void visitVarAssignment(VarAssignmentNode node)
        {
            IdentifierNode identifier   = (IdentifierNode)node.getChildren()[0];
            string         variableName = identifier.getVariableName();

            if (!variableAlreadyDeclared(variableName))
            {
                throw new SemanticException("Variable '" + variableName + "' has not been declared.");
            }
            if (this.forLoopControlVariables.Contains(variableName))
            {
                throw new SemanticException("Control variable '" + variableName + "' cannot be assigned a new value inside for loop.");
            }
        }
        public void visitIdentifier(IdentifierNode node)
        {
            string variableName = node.getVariableName();

            if (this.symbolTable.hasInteger(variableName))
            {
                this.intType = true;
                this.intStack.Push(this.symbolTable.getInt(variableName));
            }
            else if (this.symbolTable.hasString(variableName))
            {
                this.strType = true;
                this.strStack.Push(this.symbolTable.getString(variableName));
            }
            else if (this.symbolTable.hasBool(variableName))
            {
                this.boolStack.Push(this.symbolTable.getBool(variableName));
            }
        }
        public void visitForLoop(ForLoopNode forLoopNode)
        {
            IdentifierNode    identifier      = (IdentifierNode)forLoopNode.getChildren()[0];
            string            controlVariable = identifier.getVariableName();
            RangeOperatorNode rangeNode       = (RangeOperatorNode)forLoopNode.getChildren()[1];
            StatementListNode forStatements   = (StatementListNode)forLoopNode.getChildren()[2];

            rangeNode.getChildren()[0].accept(this);
            int begin = popInt();

            rangeNode.getChildren()[1].accept(this);
            int end = popInt();

            for (int i = begin; i <= end; i++)
            {
                this.symbolTable.updateVariable(controlVariable, i);
                foreach (INode child in forStatements.getChildren())
                {
                    child.accept(this);
                }
            }
        }
        public void visitVarAssignment(VarAssignmentNode node)
        {
            IdentifierNode  identifier   = (IdentifierNode)node.getChildren()[0];
            string          variableName = identifier.getVariableName();
            INode           expression   = node.getChildren()[1];
            MiniPLTokenType type;

            if (this.symbolTable.hasInteger(variableName))
            {
                type = MiniPLTokenType.TYPE_IDENTIFIER_INTEGER;
                typeCheck(expression, type);
            }
            else if (this.symbolTable.hasString(variableName))
            {
                type = MiniPLTokenType.TYPE_IDENTIFIER_STRING;
                typeCheck(expression, type);
            }
            else if (this.symbolTable.hasBool(variableName))
            {
                type = MiniPLTokenType.TYPE_IDENTIFIER_BOOL;
                typeCheck(expression, type);
            }
        }