#lang racket/base
(require brag/examples/0n1n
         brag/support
         rackunit)

(define (lex ip)
  (port-count-lines! ip)
  (lambda ()
    (define next-char (read-char ip))
    (cond [(eof-object? next-char)
           (token eof)]
          [(char=? next-char #\0)
           (token "0" "0")]
          [(char=? next-char #\1)
           (token "1" "1")])))


;; The only rule in the grammar is:
;;
;;      rule-0n1n: ["0" rule-0n1n "1"]
;;
;; It makes use of the "maybe" pattern.  The result type of the
;; grammar rule is:
;;
;; rule-0n1n: (U #f
;;               (list "0" rule-0n1n "1"))

(check-equal? (syntax->datum (parse #f (lex (open-input-string "0011"))))
              '(rule-0n1n "0" (rule-0n1n "0" (rule-0n1n) "1") "1"))

(check-equal? (syntax->datum (parse #f (lex (open-input-string "01"))))
              '(rule-0n1n "0" (rule-0n1n) "1"))

(check-equal? (syntax->datum (parse #f (lex (open-input-string ""))))
              '(rule-0n1n))

(check-equal? (syntax->datum (parse #f (lex (open-input-string "000111"))))
              '(rule-0n1n "0" (rule-0n1n "0" (rule-0n1n "0" (rule-0n1n) "1") "1") "1"))



(check-exn exn:fail:parsing?
           (lambda () (parse #f (lex (open-input-string "0001111")))))

(check-exn exn:fail:parsing?
           (lambda () (parse #f (lex (open-input-string "0001110")))))

(check-exn exn:fail:parsing?
           (lambda () (parse #f (lex (open-input-string "10001110")))))
