#lang racket/base

(provide parse-sequence
         parse-success-or-error)

(require racket/match)

(define-match-expander parse-sequence
  (syntax-rules ()
    [(_ predicate? to-list item-pat item-expr from-list target-pat)
     (? predicate? (app (lambda (v)
                          (let loop ((inputs (to-list v)) (acc-rev '()))
                            (match inputs
                              ['() (values #t (from-list (reverse acc-rev)))]
                              [(cons untransformed remainder)
                               (match untransformed
                                 [item-pat (loop remainder (cons item-expr acc-rev))]
                                 [_ (values #f #f)])])))
                        #t target-pat))]))

(define (parse-success-or-error parser-name parser)
  (lambda (input)
    (match (parser input)
      [(? eof-object?) (error parser-name "Invalid input")]
      [v v])))
