#include <iostream>
#include "lists.h"
using namespace std;

//  *** EXPR ***

typedef int token;

typedef struct expr_block *expr;


// *** EXPR_LIST ***

typedef list_pair<expr> expr_pair;

typedef expr_pair * expr_list;


// *** EXPR_BLOCK, et. al. **

struct expr_block {

    virtual void put()
    {
        // you can write this if you like to help you with debugging
        cerr << "ERROR: forgot to write method put for expr!\n";
    }

    virtual void gen_postfix()
    {
        cerr << "ERROR: forgot to write method gen_postfix for expr!\n";
    }

    virtual expr gen_three_address()
    {
        cerr << "ERROR: forgot to write method gen_three_address for expr!\n";
    }
};


struct identifier_expr : expr_block {
    char *name;

    identifier_expr(char *s) :
        name(s)
    {
    }
    virtual void gen_postfix();
    virtual expr gen_three_address();
};

struct constant_expr : expr_block {
    int value;

    constant_expr(int val) :
        value(val)
    {
    }
    virtual void gen_postfix();
    virtual expr gen_three_address();
};

struct binary_expr : expr_block {
    token binary_op;
    expr left, right;
    binary_expr(token op, expr l, expr r) :
        binary_op(op), left(l), right(r)
    {
    }
    virtual void gen_postfix();
    virtual expr gen_three_address();
};

struct assign_expr : expr_block {
    expr left, right;
    assign_expr(expr l, expr r) :
        left(l), right(r)
    {
    }
    virtual void gen_postfix();
    virtual expr gen_three_address();
};

struct unary_expr : expr_block {
    token unary_op;
    expr operand;

    unary_expr(token op, expr o) :
        unary_op(op), operand(o)
    {
    }
    virtual void gen_postfix();
    virtual expr gen_three_address();
};

struct output_expr : expr_block {
    char *op;
    char *id;

    output_expr(char *o, char *i) :
        op(o), id(i)
    {
    }
    virtual void gen_postfix();
    virtual expr gen_three_address();
};

struct declaration_expr : expr_block {
    char *id;
    char *ty;

    declaration_expr(char *i, char *t) :
        id(i), ty(t)
    {
    }
    virtual void gen_postfix();
    virtual expr gen_three_address();
};

struct declare_expr : expr_block {
    expr_list decls;
    expr_list stmts;

    declare_expr(expr_list d, expr_list s) :
        decls(d), stmts(s)
    {
    }
    virtual void gen_postfix();
    virtual expr gen_three_address();
};

struct temp_expr : expr_block {
    static int current_index;
    int index;

    temp_expr() :
        index(current_index++)
    {
    }
    virtual void gen_postfix();
    virtual expr gen_three_address();
};
