private void ParseFunctionDecl(SymTable symTable)
        {
            var      c            = Current;
            SymTable procSymTable = new SymTable {
                Parent = symTable
            };
            var h = ParseFunctionHeading(procSymTable);

            Require(Semicolon);
            if (symTable.Contains(h.Name))
            {
                throw new ParserException("Duplicate identifier {h.Name}", c.Line, c.Position);
            }
            var f = new FunctionSymbol
            {
                Name       = h.Name,
                Parameters = h.Parameters,
                ReturnType = h.ReturnType
            };

            symTable.Add(h.Name, f);
            var backup = CurrentReturnType;

            CurrentReturnType = f.ReturnType;
            var b = ParseBlock(procSymTable);

            CurrentReturnType = backup;
            Require(Semicolon);
            f.Block = b;
        }
        private void ParseFieldDecl(SymTable parentSymTable, SymTable recSymTable)
        {
            var c = Current;

            Require(Identifier);
            List <string> idents = new List <string> {
                c.Value.ToString()
            };
            var t = Current;

            while (t.SubType == Comma)
            {
                Next();
                t = Current;
                Require(Identifier);
                idents.Add(t.Value.ToString());
            }
            Require(Colon);
            var tp = ParseType(parentSymTable);

            foreach (var i in idents)
            {
                if (recSymTable.Contains(i))
                {
                    throw new ParserException($"Field {i} already declared", c.Line, c.Position);
                }
                recSymTable.Add(i, new VarSymbol {
                    Name = i, Type = tp, Value = null
                });
            }
        }
        private void ParseProcedureDecl(SymTable symTable)
        {
            var      c            = Current;
            SymTable procSymTable = new SymTable {
                Parent = symTable
            };
            var h = ParseProcedureHeading(procSymTable);

            Require(Semicolon);
            if (symTable.Contains(h.Name))
            {
                throw new ParserException($"Duplicate identifier {h.Name}", c.Line, c.Position);
            }
            var p = new ProcedureSymbol {
                Name = h.Name, Parameters = h.Parameters
            };

            symTable.Add(h.Name, p);
            var backup = CurrentReturnType;

            CurrentReturnType = null;
            var b = ParseBlock(procSymTable);

            CurrentReturnType = backup;
            p.Block           = b;
            Require(Semicolon);
        }
        private void ParseConstantDecl(SymTable symTable)
        {
            var c = Current;

            Next();
            if (Current.SubType == Equal)
            {
                Next();
                var ce = ParseConstExpr(symTable);
                if (symTable.Contains(c.Value.ToString()))
                {
                    throw new ParserException($"Duplicate identifier {c.Value}", c.Line, c.Position);
                }
                symTable.Add(c.Value.ToString(),
                             new ConstSymbol
                {
                    Name  = c.Value.ToString(),
                    Type  = ce.Type,
                    Value = new SimpleConstant {
                        Type = ce.Type, Value = ce.Value
                    }
                });
                return;
            }
            if (Current.SubType != Colon)
            {
                throw new ParserException($"Expected '=' or ':', got {Current.SubType}.", Current.Line,
                                          Current.Position);
            }
            Next();
            var t = ParseType(symTable);

            Require(Equal);
            var tc = ParseTypedConstant(symTable, t);

            CheckImplicitTypeCompatibility(tc.Type, t);
            symTable.Add(c.Value.ToString(),
                         new TypedConstSymbol
            {
                Name  = c.Value.ToString(),
                Type  = t,
                Value = new SimpleConstant {
                    Type = t, Value = tc
                }
            });
        }