public ArrIdxOperator(SrcPos sp, VarOperand arr, Expr idx)
     :  base(Expr.Kind.arrIdxOperatorKind, sp)
 {
     this.arr  = arr;
     this.idx  = idx;
     this.type = Type.undefType;
     if (arr.sy.kind == Symbol.Kind.undefKind)
     {
         return;
     }
     if (arr.sy.kind != Symbol.Kind.parKind &&
         arr.sy.kind != Symbol.Kind.varKind)
     {
         Errors.SemError(sp.line, sp.col, "invalid symbol kind");
         return;
     } // if
     if (idx.type == Type.undefType)
     {
         return;
     }
     if (arr.type != Type.boolPtrType &&
         arr.type != Type.intPtrType)
     {
         Errors.SemError(sp.line, sp.col, "invalid array type");
         return;
     } // if
     if (idx.type != Type.intType)
     {
         Errors.SemError(sp.line, sp.col, "invalid index type");
         return;
     } // if
     this.type = arr.type.BaseTypeOf();
 }     // ArrIdxOperator
 public DeleteStat(SrcPos sp, VarOperand vo)
     : base(Stat.Kind.deleteStatKind, sp)
 {
     this.vo = vo;
     if (vo.sy.type == Type.undefType)
     {
         return;
     }
     if (!vo.sy.type.IsPtrType())
     {
         Errors.SemError(sp.line, sp.col, "invalid type");
     }
 } // DeleteStat
 public DecStat(SrcPos sp, VarOperand vo)
     : base(Stat.Kind.decStatKind, sp)
 {
     this.vo = vo;
     if (vo.sy.kind != Symbol.Kind.undefKind &&
         vo.sy.kind != Symbol.Kind.varKind)
     {
         Errors.SemError(sp.line, sp.col, "no variable");
     }
     if (vo.sy.type != Type.undefType &&
         vo.sy.type != Type.intType)
     {
         Errors.SemError(sp.line, sp.col, "invalid type");
     }
 } // DecStat
 public InputStat(SrcPos sp, VarOperand vo)
     : base(Stat.Kind.inputStatKind, sp)
 {
     this.vo = vo;
     if (vo.sy.kind != Symbol.Kind.undefKind &&
         vo.sy.kind != Symbol.Kind.parKind && vo.sy.kind != Symbol.Kind.varKind)
     {
         Errors.SemError(sp.line, sp.col, "invalid symbol kind");
     }
     if (vo.sy.type != Type.undefType &&
         vo.sy.type != Type.boolType &&
         vo.sy.type != Type.intType)
     {
         Errors.SemError(sp.line, sp.col, "invalid type");
     }
 } // InputStat
    public AssignStat(SrcPos sp, Expr lhs, Expr rhs)
        : base(Stat.Kind.assignStatKind, sp)
    {
        this.lhs = lhs;
        this.rhs = rhs;
        if (lhs is VarOperand)
        {
            VarOperand vo = lhs as VarOperand;
            if (vo.sy.kind != Symbol.Kind.undefKind &&
                vo.sy.kind != Symbol.Kind.parKind &&
                vo.sy.kind != Symbol.Kind.varKind)
            {
                Errors.SemError(sp.line, sp.col, "lhs: no variable");
            }
        }
        else if (lhs is ArrIdxOperator)
        {
            ; // nothing to check
        }
        else
        {
            Errors.SemError(sp.line, sp.col, "lhs: invalid expression");
        } // else
        if (lhs.type == Type.undefType ||
            rhs.type == Type.undefType ||
            lhs.type == rhs.type)
        {
            return;
        }
        if (lhs.type.IsPtrType() &&
            rhs.kind == Expr.Kind.litOperandKind &&
            ((LitOperand)rhs).type.kind == Type.Kind.intKind &&
            ((LitOperand)rhs).val == 0)
        {
            rhs.type = Type.voidPtrType; // change type of oprand form int to void*
            return;
        } // if

        Errors.SemError(sp.line, sp.col, "type mismatch");
    } // AssignStat
    }         // NT_Stat

    private static void NT_IncDecAssignOrCallStat(out Stat s)
    {
        int    spix = 0;
        Symbol sy = null;
        Expr   lhs = null, e = null;
        SrcPos sp = null;

        s = null;

        for (;;)
        {
            switch (Syn.Interpret())
            {
            case 0:
                return;

            case 1:
                Lex.GETidentAttr(out spix);
                break;

            case 2: // SEM
                sy = SymTab.SymbolOf(spix, Symbol.Kind.varKind,
                                     Symbol.Kind.parKind,
                                     Symbol.Kind.funcKind);

                break;

            case 3: // SEM
                s = new IncStat(sp, new VarOperand(sy));

                break;

            case 4: // SEM
                s = new DecStat(sp, new VarOperand(sy));

                break;

            case 5: // SEM
                lhs = new VarOperand(sy);

                break;

            case 6: // SEM
                sp = new SrcPos();

                break;

            case 7:
                NT_Expr(out e);
                break;

            case 8: // SEM
                lhs = new ArrIdxOperator(sp, new VarOperand(sy), e);

                break;

            case 9: // SEM
                sp = new SrcPos();

                break;

            case 10:
                NT_Expr(out e);
                break;

            case 11: // SEM
                s = new AssignStat(sp, lhs, e);

                break;

            case 12: // SEM
                sp = new SrcPos();

                break;

            case 13:
                NT_ActParList(out e);
                break;

            case 14: // SEM
                s = new CallStat(sp, sy, e);

                break;
            } // switch
        }     // for
    }         // NT_IncDecAssignOrCallStat
    }         // NT_NotFact

    private static void NT_Fact(out Expr f)
    {
        Expr   e = null;
        SrcPos sp = null;
        Symbol sy = null;
        int    spix = 0; int number = 0;
        Type   t = null;

        f = null;

        for (;;)
        {
            switch (Syn.Interpret())
            {
            case 0:
                return;

            case 1: // SEM
                f = new LitOperand(Type.boolType, 0);

                break;

            case 2: // SEM
                f = new LitOperand(Type.boolType, 1);

                break;

            case 3:
                Lex.GETnumberAttr(out number);
                break;

            case 4: // SEM
                f = new LitOperand(Type.intType, number);

                break;

            case 5:
                Lex.GETidentAttr(out spix);
                break;

            case 6: // SEM
                sp = new SrcPos();

                break;

            case 7: // SEM
                sy = SymTab.SymbolOf(spix, Symbol.Kind.constKind,
                                     Symbol.Kind.varKind,
                                     Symbol.Kind.parKind);
                f = new VarOperand(sy);

                break;

            case 8: // SEM
                sy = SymTab.SymbolOf(spix, Symbol.Kind.varKind,
                                     Symbol.Kind.parKind);

                break;

            case 9: // SEM
                sp = new SrcPos();

                break;

            case 10:
                NT_Expr(out e);
                break;

            case 11: // SEM
                f = new ArrIdxOperator(sp, new VarOperand(sy), e);

                break;

            case 12: // SEM
                sy = SymTab.SymbolOf(spix, Symbol.Kind.funcKind);

                break;

            case 13:
                NT_ActParList(out e);
                break;

            case 14: // SEM
                f = new FuncCallOperator(sp, sy, e);

                break;

            case 15: // SEM
                sp = new SrcPos();

                break;

            case 16:
                NT_Type(out t);
                break;

            case 17:
                NT_Expr(out e);
                break;

            case 18: // SEM
                f = new NewOperator(sp, t, e);

                break;

            case 19:
                NT_Expr(out e);
                break;

            case 20: // SEM
                f = e;

                break;
            } // switch
        }     // for
    }         // NT_Fact