add (picrin parser) library
This commit is contained in:
parent
34028172f2
commit
e23bfa5565
|
@ -0,0 +1,8 @@
|
||||||
|
CONTRIB_LIBS += contrib/60.peg/picrin/parser.scm contrib/60.peg/picrin/parser/string.scm
|
||||||
|
|
||||||
|
CONTRIB_TESTS += test-peg
|
||||||
|
|
||||||
|
test-peg: bin/picrin
|
||||||
|
for test in `ls contrib/60.peg/t/*.scm`; do \
|
||||||
|
$(TEST_RUNNER) "$$test"; \
|
||||||
|
done
|
|
@ -0,0 +1,100 @@
|
||||||
|
(define-library (picrin parser)
|
||||||
|
(import (scheme base)
|
||||||
|
(picrin control)
|
||||||
|
(picrin procedure))
|
||||||
|
(export parse
|
||||||
|
;; monadic
|
||||||
|
reify
|
||||||
|
reflect
|
||||||
|
bind
|
||||||
|
unit
|
||||||
|
zero
|
||||||
|
plus
|
||||||
|
fapply
|
||||||
|
;; look ahead
|
||||||
|
with
|
||||||
|
without
|
||||||
|
;; eta
|
||||||
|
lazy
|
||||||
|
;; aux
|
||||||
|
choice
|
||||||
|
optional
|
||||||
|
many
|
||||||
|
between)
|
||||||
|
|
||||||
|
;; type Parser i r = i -> Maybe (r, i)
|
||||||
|
|
||||||
|
(define (parse rule input)
|
||||||
|
(rule input))
|
||||||
|
|
||||||
|
;; monadic operators
|
||||||
|
|
||||||
|
(define-syntax reify
|
||||||
|
(syntax-rules ()
|
||||||
|
((_ expr)
|
||||||
|
(reset (unit expr)))))
|
||||||
|
|
||||||
|
(define (reflect x)
|
||||||
|
(shift k (bind x k)))
|
||||||
|
|
||||||
|
(define (bind m f)
|
||||||
|
(lambda (i)
|
||||||
|
(let ((x (m i)))
|
||||||
|
(and x ((f (car x)) (cdr x))))))
|
||||||
|
|
||||||
|
(define (unit x)
|
||||||
|
(lambda (i)
|
||||||
|
`(,x . ,i)))
|
||||||
|
|
||||||
|
(define zero
|
||||||
|
(lambda (i) #f))
|
||||||
|
|
||||||
|
(define (plus a b)
|
||||||
|
(lambda (i)
|
||||||
|
(or (a i) (b i))))
|
||||||
|
|
||||||
|
(define (fapply f . args)
|
||||||
|
(reify
|
||||||
|
(let loop ((args args) (ps '()))
|
||||||
|
(if (null? args)
|
||||||
|
(apply f (reverse ps))
|
||||||
|
(loop (cdr args) (cons (reflect (car args)) ps))))))
|
||||||
|
|
||||||
|
;; look ahead
|
||||||
|
|
||||||
|
(define (with a)
|
||||||
|
(lambda (i)
|
||||||
|
(and (a i) `(#f . ,i))))
|
||||||
|
|
||||||
|
(define (without a)
|
||||||
|
(lambda (i)
|
||||||
|
(and (not (a i)) `(#f . ,i))))
|
||||||
|
|
||||||
|
;; eta conversion
|
||||||
|
|
||||||
|
(define-syntax lazy
|
||||||
|
(syntax-rules ()
|
||||||
|
((_ expr)
|
||||||
|
(lambda (i) (expr i)))))
|
||||||
|
|
||||||
|
;; aux
|
||||||
|
|
||||||
|
(define (choice . xs)
|
||||||
|
(if (null? xs)
|
||||||
|
zero
|
||||||
|
(plus (car xs) (apply choice (cdr xs)))))
|
||||||
|
|
||||||
|
(define (optional a)
|
||||||
|
(choice a (unit #f)))
|
||||||
|
|
||||||
|
(define (many a)
|
||||||
|
(lazy
|
||||||
|
(choice
|
||||||
|
(reify
|
||||||
|
(let* ((a (reflect a))
|
||||||
|
(b (reflect (many a))))
|
||||||
|
(cons a b)))
|
||||||
|
null)))
|
||||||
|
|
||||||
|
(define (between l x r)
|
||||||
|
(fapply (>> list cadr) l x r)))
|
|
@ -0,0 +1,28 @@
|
||||||
|
(define-library (picrin parser string)
|
||||||
|
(import (except (scheme base) string)
|
||||||
|
(picrin parser))
|
||||||
|
(export string
|
||||||
|
any-char
|
||||||
|
eof
|
||||||
|
parse-string)
|
||||||
|
|
||||||
|
;; string stream parser
|
||||||
|
|
||||||
|
(define (string str)
|
||||||
|
(lambda (i)
|
||||||
|
(let ((i (car i)) (input (cdr i)))
|
||||||
|
(let ((j (min (+ i (string-length str)) (string-length input))))
|
||||||
|
(and (equal? str (string-copy input i j))
|
||||||
|
`(,str . ,(cons j input)))))))
|
||||||
|
|
||||||
|
(define any-char
|
||||||
|
(lambda (i)
|
||||||
|
(let ((i (car i)) (input (cdr i)))
|
||||||
|
(and (< i (string-length input))
|
||||||
|
`(,(string-ref input i) . ,(cons (+ i 1) input))))))
|
||||||
|
|
||||||
|
(define eof
|
||||||
|
(without any-char))
|
||||||
|
|
||||||
|
(define (parse-string rule input)
|
||||||
|
(parse rule (cons 0 input))))
|
|
@ -0,0 +1,45 @@
|
||||||
|
;;; test case
|
||||||
|
|
||||||
|
(import (scheme base)
|
||||||
|
(picrin test)
|
||||||
|
(picrin procedure)
|
||||||
|
(picrin parser)
|
||||||
|
(picrin parser string))
|
||||||
|
|
||||||
|
(test-begin "(picrin parser) and (picrin parser string)")
|
||||||
|
|
||||||
|
(define LPAREN (string "("))
|
||||||
|
(define RPAREN (string ")"))
|
||||||
|
|
||||||
|
(define PLUS (string "+"))
|
||||||
|
(define MINUS (string "-"))
|
||||||
|
|
||||||
|
(define ONE (fapply (constant 1) (string "1")))
|
||||||
|
|
||||||
|
(define S (lazy
|
||||||
|
(fapply (>> list car) A eof)))
|
||||||
|
|
||||||
|
(define A (lazy
|
||||||
|
(choice
|
||||||
|
(fapply (lambda (p _ a) (list '+ p a)) P PLUS A)
|
||||||
|
(fapply (lambda (p _ a) (list '- p a)) P MINUS A)
|
||||||
|
P)))
|
||||||
|
|
||||||
|
(define P (lazy
|
||||||
|
(choice
|
||||||
|
(between LPAREN A RPAREN)
|
||||||
|
ONE)))
|
||||||
|
|
||||||
|
(define-syntax test-success
|
||||||
|
(syntax-rules ()
|
||||||
|
((_ expect str)
|
||||||
|
(test (cons expect (cons (string-length str) str))
|
||||||
|
(parse-string S str)))))
|
||||||
|
|
||||||
|
(test-success 1 "(1)")
|
||||||
|
(test-success '(- (+ 1 1) 1) "((1+1)-1)")
|
||||||
|
(test-success '(- (+ 1 1) 1) "((1+(1))-1)")
|
||||||
|
(test-success '(+ 1 (- 1 (+ 1 (- 1 (+ 1 1))))) "(1+(1-(1+(1-(1+1)))))")
|
||||||
|
(test-success '(+ 1 (+ 1(- 1 (+ 1 (- 1 (+ 1 1)))))) "(1+1+(1-(1+(1-(1+1)))))")
|
||||||
|
|
||||||
|
(test-end)
|
Loading…
Reference in New Issue