-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathparse.rkt
85 lines (70 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
#lang racket/base
(require "combinator.rkt")
(require "parser-struct.rkt")
(provide parse)
(define (object->external-representation o)
(let ((s (open-output-string)))
(write o s)
(get-output-string s)))
(define-syntax parse
(syntax-rules (:= quote ? ! @ /)
((_ start (nonterminal (alternative body0 body ...) ...) ...)
(let ()
(define nonterminal
(parser
(lambda (results)
(results->result results 'nonterminal
(lambda ()
((parse* #f "alts" nonterminal
((begin body0 body ...) alternative) ...)
results))))))
...
start))))
(define-syntax parse*
(syntax-rules (:= quote ? ! @ /)
((_ #f "alts" nt (body alternative))
(parse* #f "alt" nt body alternative))
((_ #f "alts" nt (body alternative) rest0 rest ...)
(packrat-or (parse* #f "alt" nt body alternative)
(parse* #f "alts" nt rest0 rest ...)))
((_ #f "alt" nt body ())
(parser
(lambda (results) (make-result body results))))
((_ #f "alt" nt body ((! fails ...) rest ...))
(packrat-unless (string-append "Nonterminal " (symbol->string 'nt)
" expected to fail "
(object->external-representation '(fails ...)))
(parse* #f "alt" nt #t (fails ...))
(parse* #f "alt" nt body (rest ...))))
((_ #f "alt" nt body ((/ alternative ...) rest ...))
(packrat-check (parse* #f "alts" nt (#t alternative) ...)
(parser
(lambda (result) (parse* #f "alt" nt body (rest ...))))))
((_ #f "alt" nt body (var := 'val rest ...))
(packrat-check-base 'val
(lambda (var)
(parse* #f "alt" nt body (rest ...)))))
((_ #f "alt" nt body (var := @ rest ...))
(lambda (results)
(let ((var (parse-results-position results)))
((parse* #f "alt" nt body (rest ...)) results))))
((_ #f "alt" nt body (var := (? p) rest ...))
(packrat-check-pred p
(lambda (var)
(parse* #f "alt" nt body (rest ...)))))
((_ #f "alt" nt body (var := val rest ...))
(packrat-check val
(lambda (var)
(parse* #f "alt" nt body (rest ...)))))
((_ #f "alt" nt body (? p rest ...))
(packrat-check-pred p
(lambda (dummy)
(parse* #f "alt" nt body (rest ...)))))
((_ #f "alt" nt body ('val rest ...))
(packrat-check-base 'val
(lambda (dummy)
(parse* #f "alt" nt body (rest ...)))))
((_ #f "alt" nt body (val rest ...))
(packrat-check val
(lambda (dummy)
(parse* #f "alt" nt body (rest ...)))))))