a proper shift/reduce parser