;; Core parser helpers — shared by er-parse-expr and er-parse-module.
;; Everything reads/mutates a parser state dict:
;;   {:toks TOKS :idx INDEX}

(define er-state-make (fn (toks) {:idx 0 :toks toks}))

(define
  er-peek
  (fn
    (st offset)
    (let
      ((toks (get st :toks)) (idx (+ (get st :idx) offset)))
      (if (< idx (len toks)) (nth toks idx) (nth toks (- (len toks) 1))))))

(define er-cur (fn (st) (er-peek st 0)))

(define er-cur-type (fn (st) (get (er-cur st) :type)))
(define er-cur-value (fn (st) (get (er-cur st) :value)))

(define er-advance! (fn (st) (dict-set! st :idx (+ (get st :idx) 1))))

(define er-at-eof? (fn (st) (= (er-cur-type st) "eof")))

(define
  er-is?
  (fn
    (st type value)
    (and
      (= (er-cur-type st) type)
      (or (= value nil) (= (er-cur-value st) value)))))

(define
  er-expect!
  (fn
    (st type value)
    (if
      (er-is? st type value)
      (let ((t (er-cur st))) (er-advance! st) t)
      (error
        (str
          "Erlang parse: expected "
          type
          (if value (str " '" value "'") "")
          " but got "
          (er-cur-type st)
          " '"
          (er-cur-value st)
          "' at pos "
          (get (er-cur st) :pos))))))
