-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlistquery.scm
More file actions
240 lines (211 loc) · 8.49 KB
/
listquery.scm
File metadata and controls
240 lines (211 loc) · 8.49 KB
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
;;todo: remove from leaves, anys etc from results as they are not needed, only the vals are
;; (import (srfi11))
(define (merge-list lst)
(foldl (lambda (x r) (map cons x r))
(map list (car lst))
(cdr lst)))
(merge-list '((1 2 3) ( a b c) (q r s)))
;; (map (lambda (x y) (list x y)) '(a b c) '(1 2 3))
(define (query2 qs as bs rs depth)
(cond [(equal? qs '(branch))
;;at end of branch parsing
(values as bs rs #t)]
[(null? qs)
;;on no more queries
(values as bs rs #t)]
[(and (null? as) (equal? 'many0 (car qs)))
;;on no more input, at end of many parsing
(values '() bs rs #t)]
[(null? as)
;;no more input and queries left
(values '() bs rs #f)]
[(equal? 'value (car qs))
;;on value parsing
(if (list? (car as))
(values (cdr as) (cons (car as) bs) rs #f)
(values (cdr as) bs (cons (car as) rs) #t))]
[(equal? 'any (car qs))
;;on any parsing
(if (list? (car as))
(values (cdr as) (cons (car as) bs) rs #f)
(values (cdr as) bs (cons (car as) rs) #t))]
[(equal? 'leaf (car qs))
;;on leaf parsing
(if (equal? (cadr qs) (car as))
(values (cdr as) bs (cons (car as) rs) #t)
(values (cdr as) (cons (car as) bs) rs #f))]
[(equal? 'relative0 (car qs))
(if (list? (car as))
(let-values ([(as2 bs2 rs2 ok2)
(query2 (cons 'relative (cdr qs)) (car as) '() rs (+ 1 depth))])
(if ok2
(values (cons (append-reverse bs2 as2) (cdr as)) bs rs2 #t)
(query2 qs (cdr as) (cons (car as) bs) rs depth) ))
(query2 qs (cdr as) (cons (car as) bs) rs depth) )]
[(equal? 'relative (car qs))
(let-values ([(as2 bs2 rs2 ok2)
(query2 (cons 'branch (cdr qs)) as bs rs (+ 1 depth))])
(if ok2
(values as2 bs2 rs2 #t)
(query2 (cons 'relative0 (cdr qs)) as bs rs depth) ))]
[(or (equal? 'many (car qs))
(equal? 'many0 (car qs)))
;;on many starting or continuing parsing
(let-values ([(as2 bs2 rs2 ok2)
;;try query within many query
(query2 (list 'branch (cadr qs)) as bs '() (+ 1 depth))])
(cond [ok2
;;on success, try query again from last pos
(query2 (cons 'many0 (cdr qs)) as2 bs2 (cons rs2 rs) depth)]
[(equal? 'many0 (car qs))
;;on fail and a continued many, return sucess
(values as bs rs #t)]
[else
;;on fail and a first many, return failed
(values as2 bs2 rs2 #f)]))]
[(equal? 'branch (car qs))
;;on branch
(cond [(equal? 'relative (caadr qs))
;;on inner relative
(let-values ([(as2 bs2 rs2 ok2)
;;try inner relative query
(query2 (cadr qs) as bs '() (+ 1 depth))])
(if ok2
;;on success, try next query within branch and restore
;;discarded input
(query2 (cons 'branch (cddr qs)) (append-reverse bs2 as2) '() (cons rs2 rs) depth)
;;on fail, return failed
(values as2 bs2 rs #f)
))]
[(equal? 'many (caadr qs))
;;on inner many
(let-values ([(as2 bs2 rs2 ok2)
;;try inner many query
(query2 (cadr qs) as bs '() (+ 1 depth))])
(if ok2
;;on success, try next query within branch and restore
;;discarded input
(query2 (cons 'branch (cddr qs)) (append-reverse bs2 as2) '()
(append
(merge-list rs2)
rs) depth)
;;on fail, return failed
(values as2 bs2 rs #f)
))]
[(and (equal? 'branch (caadr qs)) (list? (car as)))
;;on inner branch and current input element is a list
(let-values ([(as2 bs2 rs2 ok2)
;;try inner branch query
(query2 (cadr qs) (car as) '() rs (+ 1 depth))])
(if ok2
;;on success, try next query within branch and restore
;;discarded input
(query2 (cons 'branch (cddr qs)) (append-reverse bs (cdr as)) '() rs2 depth)
;;on fail, try the same query on the next input element,
;;discarding current input element
(query2 qs (cdr as) (cons (car as) bs) rs depth) ))]
[(equal? 'branch (caadr qs))
;;on inner branch and current input element is not a list,
;;try the same query on the next input element, discarding
;;current input element
(query2 qs (cdr as) (cons (car as) bs) rs depth)]
[else
;;on inner query not a branch
(let-values ([(as2 bs2 rs2 ok2)
;;try inner query
(query2 (cadr qs) as bs rs (+ 1 depth))])
(if ok2
;;on success, try next query within branch and restore
;;discarded input
(query2 (cons 'branch (cddr qs)) (append-reverse bs2 as2) '() rs2 depth)
;;on fail, try the same query on the next input element,
;;discarding current input element
(query2 qs as2 bs2 rs depth) ))])]
[else
;;unable to parse query
;; (values as bs rs #f)
(error "problem with" qs as bs rs) ]))
(define (append-reverse lst tail)
;; (append lst tail)
;; (append (reverse lst) tail)
(if (null? lst)
tail
(append-reverse (cdr lst) (cons (car lst) tail)))
)
;; (append-reverse (list 1 2 3 4) (list 5))
(define (whitespace n)
(if (> n 0)
(string-append " " (whitespace (- n 1)))
""))
;; (when #t
;; (set! query2
;; (let ([query3 query2]
;; [count 0])
;; (lambda (qs as bs rs depth)
;; (set! count (+ 1 count))
;; (let ([count2 count])
;; (display (whitespace depth))
;; (write (list '+ count2 '@ depth 'in: qs as bs rs )) (newline)
;; (let-values ([(as2 bs2 rs2 ok2)
;; (query3 qs as bs rs depth)])
;; (display (whitespace depth))
;; (write (list '- count2 '@ depth 'out as2 bs2 rs2 ok2)) (newline)
;; (values as2 bs2 rs2 ok2))
;; )))))
(define (query qs as)
(let-values ([(as2 bs2 rs2 ok2) (query2 qs as '() '() 0)])
;; (write (list 'result as2 bs2 rs2 ok2)) (newline)
(if ok2
;; (reverse rs2)
rs2
'())))
;; (define-syntax (qmatch-case stx)
;; (syntax-case stx ()
;; [(_ x (c0 r0) ) #'2]
;; [(_ x (c0 r0) (c r) ... (else e)) #'1]
;; [(_ x (c0 r0) (c r) ... (else e)) #'1]
;; ))
;; (define-syntax (qmatch stx)
;; (syntax-case stx (else)
;; ;; [(_ ) #'(error "query match: expecting input.")]
;; ;; [(_ x) #'(error "query match: expecting cases.")]
;; [(_ x (c0 r0) ) #'2]
;; [(_ x (c0 r0) (c r) ... (else e)) #'1]
;; [(_ x (c0 r0) (c r) ... (else e)) #'1]
;; ))
;; (qmatch '(html (body (p "hello")))
;; [a b]
;; [c d]
;; [else e]
;; )
;; (define-syntax (qqq stx)
;; (syntax-case stx ()
;; [(_ x ,y ) #'(quote ,y)]
;; ))
;; (qqq 1 ,())
(let* ([q '(branch (leaf body)
(many
(branch
(leaf p) (value)
(many (branch (leaf a) (value)))
))
;; (many (value))
;; (branch (leaf y) (branch (leaf z) (leaf w)))
)]
[d '(body
"yo1" "hello1"
(p "hello" (a "world") (a "there"))
(p "x" (a "y"))
;; (p "hello") (p "world")
(y (z w))
)]
[r (query q d)]
;; [x (group-values q r)]
)
(pretty-print q)
;; (pretty-print (reverse-query q))
(pretty-print d)
(pretty-print r)
;; (pretty-print x)
;; (pretty-print (reverse-query q))
)