-
Notifications
You must be signed in to change notification settings - Fork 3
/
reader.rkt
121 lines (102 loc) · 3.05 KB
/
reader.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
111
112
113
114
115
116
117
118
119
120
121
;Asi64
;Copyright Ross McKinlay, 2017
#lang racket
(require syntax/readerr)
(provide wrapper1
make-asi-readtable)
(define (make-asi-readtable)
(make-readtable (current-readtable)
#\{ 'terminating-macro read-lbrace
#\@ 'terminating-macro read-@
#\% 'terminating-macro read-%
#\£ 'terminating-macro read-£
#\$ 'terminating-macro read-$
))
(define (wrapper1 thk)
(parameterize ([current-readtable (make-asi-readtable)])
(thk)))
(define read-lbrace
(case-lambda
[(ch in)
(parse-6502-block in in (object-name in))]
[(ch in src line col pos)
(parse-6502-block in in src)]))
(define read-@
(case-lambda
[(ch in)
#'#:immediate ]
[(ch in src line col pos)
#'#:immediate]))
(define read-£
(case-lambda
[(ch in)
#'#:indirect ]
[(ch in src line col pos)
#'#:indirect]))
(define read-%
(case-lambda
[(ch in)
(parse-number #\% (read in))]
[(ch in src line col pos)
(parse-number #\% (read in))]))
(define (read-hex-string in)
(define (aux acc)
(let ([c (peek-char in)])
(cond
[(string-contains? "0123456789abcdefABCDEF" (make-string 1 c))
(aux (string-append acc (make-string 1 (read-char in))))]
[else acc])))
(aux ""))
(define read-$
(case-lambda
[(ch in)
(parse-number #\$ (read-hex-string in))]
[(ch in src line col pos)
(parse-number #\$ (read-hex-string in))]))
(define (parse-number pre input)
(let ([radix
(case pre
[(#\$) 16]
[(#\%) 2])]
[str (cond [(number? input) (number->string input)]
[(symbol? input) (symbol->string input)]
[else input])])
(string->number (string-replace str "_" "") radix)))
(define (parse-6502-block val in src)
(define (parse-6502-line acc paren-count)
; skip nested expressions, we assume a line ends at the first newline char
; outside of parens.
(let ([c (peek-char in)])
(cond
[(and (equal? c #\;) (equal? paren-count 0))
;treat a comment as an end-of-line
;(writeln "comment")
(begin
(read-line in)
`(6502-line ,@(reverse acc)))]
[(and (equal? c #\newline) (equal? paren-count 0))
;(writeln "new line")
(begin
(read-char in)
`(6502-line ,@(reverse acc)))]
[(char-whitespace? c)
(begin
(read-char in)
(parse-6502-line acc paren-count))]
[(equal? c #\})
`(6502-line ,@(reverse acc))]
[else
(parse-6502-line (cons [read-syntax "" in] acc) paren-count)])))
(define (aux acc)
(let ([c (peek-char in)])
(cond
[(equal? c #\})
(begin
(read-char in)
`(6502-block ,@(reverse acc)))]
[else
(let ([c (parse-6502-line '() 0)])
(if (equal? c '(6502-line))
(aux acc)
(aux (cons c acc))))])))
(aux '()))