#lang scheme/base
(require "depend.ss"
"primitive.ss"
"combinator.ss"
"input.ss"
)
(define digit (char-between #\0 #\9))
(define not-digit (char-not-between #\0 #\9))
(define lower-case (char-between #\a #\z))
(define upper-case (char-between #\A #\Z))
(define alpha (choice lower-case upper-case))
(define alphanumeric (choice alpha digit))
(define hexdecimal (char-in '(#\a #\b #\c #\d #\e #\f
#\A #\B #\C #\D #\E #\F
#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9)))
(define whitespace (char-in '(#\space #\return #\newline #\tab #\vtab)))
(define not-whitespace (char-not-in '(#\space #\return #\newline #\tab #\vtab)))
(define ascii (char-between (integer->char 0) (integer->char 127)))
(define word (choice alphanumeric (char= #\_)))
(define not-word (char-when (lambda (c)
(not (or (char<=? #\a c #\z)
(char<=? #\A c #\Z)
(char<=? #\0 c #\9)
(char=? c #\_))))))
(define sign (zero-one (char= #\-) #\+))
(define natural (one-many digit))
(define decimal (seq number <- (zero-many digit)
point <- (char= #\.)
decimals <- natural
(return (append number (cons point decimals)))))
(define (hexdecimals->number hexes)
(define (hex->num hex)
(- (char->integer hex)
(char->integer (case hex
((#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) #\0)
((#\a #\b #\c #\d #\e #\f) #\a)
((#\A #\B #\C #\D #\E #\F) #\A)))
(- (case hex
((#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) 0)
((#\a #\b #\c #\d #\e #\f) 10)
((#\A #\B #\C #\D #\E #\F) 10)))))
(define (helper rest total)
(if (null? rest)
total
(helper (cdr rest) (+ (hex->num (car rest)) (* total 16)))))
(helper hexes 0))
(define hexdecimals (seq num <- (zero-many hexdecimal)
(return (hexdecimals->number num))))
(define positive (choice decimal natural))
(define (make-signed parser)
(seq +/- <- sign
number <- parser
(return (cons +/- number))))
(define (make-number parser)
(seq n <- parser
(return (string->number (list->string n)))))
(define natural-number (make-number natural))
(define integer (make-number (make-signed natural)))
(define positive-number (make-number positive))
(define real-number (make-number (choice (seq exp <- (make-signed positive)
e <- (choice #\E #\e)
magenta <- (make-signed natural)
(return (append exp (list e) magenta)))
(make-signed positive)
)))
(define hexdecimal-number (make-number hexdecimals))
(define (escaped-char escape char (as #f))
(seq (char= escape)
c <- (if (char? char) (char= char) char)
(return (if as as c))))
(define e-newline (escaped-char #\\ #\n #\newline))
(define e-return (escaped-char #\\ #\r #\return))
(define e-tab (escaped-char #\\ #\t #\tab))
(define e-backslash (escaped-char #\\ #\\))
(define (quoted open close escape)
(seq (char= open)
atoms <- (zero-many (choice e-newline
e-return
e-tab
e-backslash
(escaped-char escape close)
(char-not-in (list close #\\))))
(char= close)
(return atoms)))
(define (make-quoted-string open (close #f) (escape #\\))
(seq v <- (quoted open (if close close open) escape)
(return (list->string v))))
(define single-quoted-string (make-quoted-string #\'))
(define double-quoted-string (make-quoted-string #\"))
(define quoted-string
(choice single-quoted-string double-quoted-string))
(define whitespaces (zero-many whitespace))
(define newline
(choice (seq r <- (char= #\return)
n <- (char= #\newline)
(return (list r n)))
(char= #\return)
(char= #\newline)))
(provide (all-defined-out))