-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparse.rkt
110 lines (94 loc) · 2.97 KB
/
parse.rkt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#lang racket/base
(provide parse-program parse-program!
parse-exp parse-exp!)
(require (for-syntax racket/base racket/syntax))
(require racket/match
megaparsack megaparsack/text
data/monad data/applicative
"types.rkt")
(define-syntax (define-prod stx)
(syntax-case stx ()
[(_ name (fields ...))
(with-syntax ([name/p (format-id #'name "~a/p" #'name)]
[field-names (for/list ([field (syntax->datum #'(fields ...))]
#:unless (string? field))
(car field))]
[parsers (for/list ([field (syntax->list #'(fields ...))])
(if (string? (syntax-e field))
field
(syntax-case field ()
[(_ parser)
(with-syntax ([parser/p (format-id #'parser "~a/p" #'parser)])
#'(delay/p parser/p))])))])
#`(begin
(define name/p
(parse-and-apply/p
name
#,@(for/list ([field (syntax->list #'(fields ...))])
(if (string? (syntax-e field))
field
(syntax-case field ()
[(_ parser)
(with-syntax ([parser/p (format-id #'parser "~a/p" #'parser)])
#'(delay/p parser/p))])))))))]))
(define (full/p p)
(do
[x <- p]
eof/p
(pure x)))
(define (leading-ws/p p)
(do
(many/p space/p)
p))
(define (trail-ws/p p)
(do
[x <- p]
(many/p space/p)
(pure x)))
(define (tok/p s) (trail-ws/p (string/p s)))
(define (parse-and-apply/p c . lst)
(define (rec lst acc)
(match lst
[(list) (pure (apply c (reverse acc)))]
[(cons (? string? a) b)
(chain
(lambda (_)
(rec b acc))
(tok/p a))]
[(cons a b)
(chain
(lambda (s)
(rec b (cons s acc)))
a)]))
(rec lst '()))
(define num/p integer/p)
(define var/p
(trail-ws/p
(do
[c <- letter/p]
[cs <- (many/p (or/p letter/p digit/p))]
(pure (string->symbol (list->string (cons c cs)))))))
(define-prod const-exp ([e1 num]))
(define-prod diff-exp ("-" "(" [e1 exp] "," [e2 exp] ")"))
(define-prod zero?-exp ("zero?" "(" [e1 exp] ")"))
(define-prod if-exp ("if" [e1 exp] "then" [e2 exp] "else" [e3 exp]))
(define-prod var-exp ([e1 var]))
(define-prod let-exp ("let" [id var] "=" [e1 exp] "in" [body exp]))
(define exp/p
(trail-ws/p
(or/p
const-exp/p
diff-exp/p
zero?-exp/p
if-exp/p
let-exp/p
var-exp/p)))
(define-prod a-program ([e1 exp]))
(define (parse-exp! s)
(parse-result! (parse-exp s)))
(define (parse-exp s)
(parse-string (full/p exp/p) s))
(define (parse-program! s)
(parse-result! (parse-program s)))
(define (parse-program s)
(parse-string (full/p (leading-ws/p a-program/p)) s))