private ExpressionNode ParseTerm(SymTable symTable)
        {
            var f = ParseFactor(symTable);
            var c = Current;

            while (MulOps.Contains(c.SubType))
            {
                Next();
                var t = ParseFactor(symTable);
                if (
                    t.Type is ArrayTypeSymbol || t.Type is RecordTypeSymbol ||
                    f.Type is ArrayTypeSymbol || f.Type is RecordTypeSymbol
                    )
                {
                    throw new ParserException("Incompatible types", c.Line, c.Position);
                }
                if (c.SubType == Slash)
                {
                    f = ToType(f, TypeSymbol.RealTypeSymbol);
                }
                (f, t) = SelectType(f, t);
                f      = new BinOpNode(new List <Node> {
                    f, t
                }, c.SubType, c.Line, c.Position)
                {
                    Type = f.Type
                };
                c = Current;
            }
            return(f);
        }
        private ExpressionNode ParseExpression(SymTable symTable)
        {
            var e = ParseSimpleExpression(symTable);
            var c = Current;

            while (RelOps.Contains(c.SubType))
            {
                Next();
                var t = ParseSimpleExpression(symTable);
                if (
                    t.Type is ArrayTypeSymbol || t.Type is RecordTypeSymbol ||
                    e.Type is ArrayTypeSymbol || e.Type is RecordTypeSymbol
                    )
                {
                    throw new ParserException("Incompatible types", c.Line, c.Position);
                }
                (e, t) = SelectType(e, t);
                e      = new BinOpNode(new List <Node> {
                    e, t
                }, c.SubType, c.Line, c.Position)
                {
                    Type = TypeSymbol.IntTypeSymbol
                };
                c = Current;
            }
            return(e);
        }
        private ExpressionNode ParseSimpleExpression(SymTable symTable)
        {
            if (Current.SubType == CharConstant)
            {
                var tmp = Current;
                Next();
                return(new ConstNode(null, tmp.Value, tmp.Line, tmp.Position)
                {
                    Type = TypeSymbol.CharTypeSymbol
                });
            }
            var t = ParseTerm(symTable);
            var c = Current;

            while (AddOps.Contains(c.SubType))
            {
                Next();
                var temp = ParseTerm(symTable);
                if (
                    t.Type is ArrayTypeSymbol || t.Type is RecordTypeSymbol ||
                    temp.Type is ArrayTypeSymbol || temp.Type is RecordTypeSymbol
                    )
                {
                    throw new ParserException("Incompatible types", c.Line, c.Position);
                }
                (t, temp) = SelectType(t, temp);
                t         = new BinOpNode(new List <Node> {
                    t, temp
                }, c.SubType, c.Line, c.Position)
                {
                    Type = t.Type
                };
                c = Current;
            }
            return(t);
        }