public ScopedSymbolTable CreateCurrentScope(string name)
        {
            var levelZero = new ScopedSymbolTable(name, null, _logger);

            CurrentScope = levelZero;

            DefineBuiltIns(levelZero);
            return(levelZero);
        }
        public ScopedSymbolTable(string scopeName, ScopedSymbolTable parentScope = null, ILogger logger = null)
        {
            ParentScope = parentScope;
            _logger     = logger ?? new Logger();
            ScopeName   = scopeName;
            ScopeLevel  = ParentScope?.ScopeLevel + 1 ?? 0;

            if (parentScope?.ScopeLevel >= ScopeLevel)
            {
                throw new InvalidOperationException($"Parent scope must be greater:\nParent: {parentScope}, Current: {this}");
            }
        }
        public AnnotatedNode VisitProgram(PascalProgramNode programNode)
        {
            var levelZero = CreateCurrentScope(programNode.ProgramName);


            var global = new ScopedSymbolTable("Global", levelZero, _logger);

            CurrentScope = global;
            programNode.Block.Annotations.Add("Main", null);
            VisitBlock(programNode.Block);
            CurrentScope = global;
            programNode.Block.Annotations.Add("SymbolTable", global);

            return(new AnnotatedNode(programNode));
        }
        public static void DefineBuiltIns(ScopedSymbolTable levelZero)
        {
            levelZero.Define(new BuiltInTypeSymbol(PascalTerms.Int, PascalTerms.Real));
            levelZero.Define(new BuiltInTypeSymbol(PascalTerms.Real));
            levelZero.Define(new BuiltInTypeSymbol(PascalTerms.Pointer));
            levelZero.Define(new BuiltInTypeSymbol(PascalTerms.String));
            levelZero.Define(new BuiltInTypeSymbol(PascalTerms.Char, PascalTerms.String));
            levelZero.Define(new BuiltInTypeSymbol(PascalTerms.Boolean));
            levelZero.Define(new ProcedureDeclarationSymbol("READ", new List <ParameterNode>()
            {
                new ParameterNode(new VarDeclarationNode(new VariableOrFunctionCall(new TokenItem()
                {
                    Value = "look"
                }),
                                                         new TypeNode(new TokenItem()
                {
                    Value = PascalTerms.Char
                })))
            }));

            levelZero.Define(new FunctionDeclarationSymbol("UpCase", new List <ParameterNode>()
            {
                new ParameterNode(new VarDeclarationNode(new VariableOrFunctionCall(new TokenItem()
                {
                    Value = "look"
                }),
                                                         new TypeNode(new TokenItem()
                {
                    Value = PascalTerms.Char
                })))
            }, levelZero.LookupSymbol(PascalTerms.Char, true)));
            levelZero.Define(new ProcedureDeclarationSymbol("WriteLn", new List <ParameterNode>()));
            levelZero.Define(new ProcedureDeclarationSymbol("Halt", new List <ParameterNode>()));
            levelZero.Define(new ProcedureDeclarationSymbol("WriteLn", new List <ParameterNode>()
            {
                new ParameterNode(new VarDeclarationNode(new VariableOrFunctionCall(new TokenItem()
                {
                    Value = "x1"
                }),
                                                         new TypeNode(new TokenItem()
                {
                    Value = PascalTerms.Char
                }))),
                new ParameterNode(new VarDeclarationNode(new VariableOrFunctionCall(new TokenItem()
                {
                    Value = "x2"
                }),
                                                         new TypeNode(new TokenItem()
                {
                    Value = PascalTerms.Char
                }))),
                new ParameterNode(new VarDeclarationNode(new VariableOrFunctionCall(new TokenItem()
                {
                    Value = "x3"
                }),
                                                         new TypeNode(new TokenItem()
                {
                    Value = PascalTerms.Char
                }))),
                new ParameterNode(new VarDeclarationNode(new VariableOrFunctionCall(new TokenItem()
                {
                    Value = "x4"
                }),
                                                         new TypeNode(new TokenItem()
                {
                    Value = PascalTerms.Char
                }))),
            }));


            levelZero.Define(new ProcedureDeclarationSymbol("WriteLn", new List <ParameterNode>()
            {
                new ParameterNode(new VarDeclarationNode(new VariableOrFunctionCall(new TokenItem()
                {
                    Value = "x1"
                }),
                                                         new TypeNode(new TokenItem()
                {
                    Value = PascalTerms.Char
                }))),
                new ParameterNode(new VarDeclarationNode(new VariableOrFunctionCall(new TokenItem()
                {
                    Value = "x2"
                }),
                                                         new TypeNode(new TokenItem()
                {
                    Value = PascalTerms.Char
                }))),
            }));
            levelZero.Define(new ProcedureDeclarationSymbol("WriteLn", new List <ParameterNode>()
            {
                new ParameterNode(new VarDeclarationNode(new VariableOrFunctionCall(new TokenItem()
                {
                    Value = "x1"
                }),
                                                         new TypeNode(new TokenItem()
                {
                    Value = PascalTerms.Char
                }))),
            }));

            levelZero.Define(new ProcedureDeclarationSymbol("ReadLn", new List <ParameterNode>()
            {
            }));
            levelZero.Define(new ProcedureDeclarationSymbol("ReadLn", new List <ParameterNode>()
            {
                new ParameterNode(new VarDeclarationNode(new VariableOrFunctionCall(new TokenItem()
                {
                    Value = "x1"
                }),
                                                         new TypeNode(new TokenItem()
                {
                    Value = PascalTerms.Char
                }))),
            }));

            levelZero.Define(new ProcedureDeclarationSymbol("Write", new List <ParameterNode>()
            {
                new ParameterNode(new VarDeclarationNode(new VariableOrFunctionCall(new TokenItem()
                {
                    Value = "x1"
                }),
                                                         new TypeNode(new TokenItem()
                {
                    Value = PascalTerms.Char
                }))),
                new ParameterNode(new VarDeclarationNode(new VariableOrFunctionCall(new TokenItem()
                {
                    Value = "x2"
                }),
                                                         new TypeNode(new TokenItem()
                {
                    Value = PascalTerms.Char
                }))),
            }));
            levelZero.Define(new ProcedureDeclarationSymbol("Write", new List <ParameterNode>()
            {
                new ParameterNode(new VarDeclarationNode(new VariableOrFunctionCall(new TokenItem()
                {
                    Value = "x1"
                }),
                                                         new TypeNode(new TokenItem()
                {
                    Value = PascalTerms.Char
                }))),
            }));
        }