Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 450 lines (400 sloc) 17.843 kb
1ae5539 @soegaard Inital commit
authored
1 #lang racket
2 (require "parameter.rkt")
3 (require syntax/srcloc)
a978152 @soegaard Added note on handling special values in the parser.
authored
4
5 ;;;
6 ;;; TODO: Handle special values.
7 ;;; Pasting an image into the REPL breaks the parser at the moment.
8
1ae5539 @soegaard Inital commit
authored
9 ;;;
10 ;;; NOTES:
11 ;;; Changes from planet version: ]] (CDB) Bug fixed
12 ;;; Strings are supported.
13 ;;; Assignments changed from set! to define.
14 ;;; Assignment of functions.
15 ;;; Bug fix: identifiers with more than one _ wasn't converted correctly
16
17 ; <e> = <num>
18 ; | <string>
19 ; | <id> variable reference
20 ; | <e> [ <args> ] application
21 ; | { <args> } list construction
22 ; | <e> + <e> addition
23 ; | <e> - <e> subtraction
24 ; | <e> * <e> multiplication
25 ; | <e> / <e> division
26 ; | <e> ^ <e> exponentiation
27 ; | - <e> negation
28 ; | ( <e> ) grouping
29 ; | <id> ( <args> ) := <e> function definition
30
31 ; <id> An identifier begins with a letter,
32 ; and is optionally followed by series of letters, digits or underscores.
33 ; An underscore is converted to a -. Thus list_ref will refer to list-ref.
34
35 ; <num> A number is an non-empty series of digits,
36 ; optionally followed by a period followed by a series of digits.
37
38 ; <string> A number is a " followed by a series of non-" characters followed by a " .
39
2d90353 @soegaard Attempt to get syntax coloring working.
authored
40 (provide parse-expression
41 color-lexer)
1ae5539 @soegaard Inital commit
authored
42
43 (require parser-tools/yacc
44 parser-tools/lex
45 (prefix-in : parser-tools/lex-sre)
46 syntax/readerr)
47
6edd14c @soegaard Special values are now supported.
authored
48 (define-tokens value-tokens (NUMBER STRING IDENTIFIER IDENTIFIEROP IDENTIFIER:= SPECIAL))
1ae5539 @soegaard Inital commit
authored
49 (define-empty-tokens
50 op-tokens
51 (newline
52 :=
53 OP CP ; ( )
54 CP:= ; ):=
55 OB CB ; [ ]
56 OC CC ; { }
57 ODB ; [[ ]]
58 COMMA ; ,
59 SEMI ; ;
60 PERIOD ; .
61 LAMBDA ; lambda or λ
62 SQRT ; √
63 NEG ; ¬ (logical negation)
64 LESS-EQUAL ; <= or ≤
65 GREATER-EQUAL ; >= or ≥
66 NOT-EQUAL ; <> or ≠
67 = < >
68 + - * / ^
69 DEFINE
70 EOF))
71
72 (define-lex-abbrevs
3360a1a @soegaard Added support for greek letters
authored
73 [greek (:or (char-range #\α #\ω) (char-range #\Γ #\Ω))]
74 [roman (:or (:/ "a" "z") (:/ #\A #\Z) )]
75 [letter (:or roman greek)]
1ae5539 @soegaard Inital commit
authored
76 [digit (:/ #\0 #\9)]
77 [string (:: #\" (:* (:~ #\")) #\")]
78 [identifier (:: letter (:* (:or letter digit #\_ #\?)))]
79 [identifier:= (:: letter (:* (:or letter digit #\_ #\?)) ":=")]
aa52845 @soegaard Attempting to fix the interaction reader in the REPL
authored
80 [identifierOP (:: letter (:* (:or letter digit #\_ #\?)) "(")]
81 [comment (:: "%" (complement (:: any-string #\newline any-string)) #\newline)])
1ae5539 @soegaard Inital commit
authored
82
83 (define (string-drop-right n s)
84 (substring s 0 (- (string-length s) n)))
85
94ac668 @soegaard Add original property to parsed identifiers. This allow Check Syntax …
authored
86
1ae5539 @soegaard Inital commit
authored
87 (define expression-lexer
88 (lexer-src-pos
6edd14c @soegaard Special values are now supported.
authored
89 [(eof) (token-EOF)]
90 [(special) (token-SPECIAL lexeme)]
1ae5539 @soegaard Inital commit
authored
91 [(:or #\tab #\space #\newline) ; this skips whitespace
92 (return-without-pos (expression-lexer input-port))]
93 [#\newline (token-newline)] ; (token-newline) returns 'newline
94 [(:or ":=" "+" "-" "*" "/" "^" "<" ">" "=" "\"") (string->symbol lexeme)]
95 ["(" 'OP]
96 [")" 'CP]
97 ["[" 'OB]
98 ["]" 'CB]
99 ["{" 'OC]
100 ["}" 'CC]
101 ["[[" 'ODB]
102 ; ["]]" 'CDB]
103 ["," 'COMMA]
104 [";" 'SEMI]
105 ["." 'PERIOD]
106 [#\λ 'LAMBDA]
107 ["lambda" 'LAMBDA]
108 ["" 'SQRT]
109 ["¬" 'NEG]
110 ["" 'LESS-EQUAL]
111 ["<=" 'LESS-EQUAL]
112 ["" 'GREATER-EQUAL]
113 [">=" 'GREATER-EQUAL]
114 ["<>" 'NOT-EQUAL]
115 ["" 'NOT-EQUAL]
116 ["define" 'DEFINE]
aa52845 @soegaard Attempting to fix the interaction reader in the REPL
authored
117 [comment
118 (return-without-pos (expression-lexer input-port))]
1ae5539 @soegaard Inital commit
authored
119 [string
120 (token-STRING (substring lexeme 1 (- (string-length lexeme) 1)))]
121 ; The parser can only look ahead 1 token, so we have 3
122 ; different identifiers to see whether := or ( comes after the identfier.
123 ; This is enough to prevent shift/reduce conflicts between atom, definition,
124 ; and application.
125 [identifier:=
126 (token-IDENTIFIER:=
127 (string->symbol (string-drop-right 2 (regexp-replace* #rx"_" lexeme "-"))))]
128 [identifierOP
129 (token-IDENTIFIEROP
130 (string->symbol (string-drop-right 1 (regexp-replace* #rx"_" lexeme "-"))))]
131 [identifier
132 (token-IDENTIFIER (string->symbol (regexp-replace* #rx"_" lexeme "-")))]
133 [(:+ digit) (token-NUMBER (string->number lexeme))]
134 [(:: (:+ digit) #\. (:* digit)) (token-NUMBER (string->number lexeme))]))
135
2d90353 @soegaard Attempt to get syntax coloring working.
authored
136 ; The color-expression-lexer is for syntax coloring.
137 ; The function returns 5 values:
138 ; - Either a string containing the matching text or the eof object.
139 ; Block comments and specials currently return an empty string.
140 ; This may change in the future to other string or non-string data.
141 ; - A symbol in '(error comment sexp-comment white-space constant
142 ; string no-color parenthesis other symbol eof).
143 ; - A symbol in '(|(| |)| |[| |]| |{| |}|) or #f.
144 ; - A number representing the starting position of the match (or #f if eof).
145 ; - A number representing the ending position of the match (or #f if eof).
146
c53891e @soegaard Syntax coloring works
authored
147 (define (syn-val a b c d e)
553318f @soegaard Refinement of Check Syntax arrows
authored
148 (values a ; string with mathching text
149 b ; symbol in '(comment white-space no-color eof)
150 c ; symbol in '(|(| |)| |[| |]| |{| |}|) or #f.
151 (position-offset d) ; start pos
c53891e @soegaard Syntax coloring works
authored
152 #;(position-offset e)
553318f @soegaard Refinement of Check Syntax arrows
authored
153 (max ; end pos
154 (position-offset e)
155 (+ (position-offset d) 1))))
c53891e @soegaard Syntax coloring works
authored
156
2d90353 @soegaard Attempt to get syntax coloring working.
authored
157 (define color-lexer
3360a1a @soegaard Added support for greek letters
authored
158 ; REMEMBER to restart DrScheme to test any changes in the color-lexer.
159 ; The lexer is only imported into DrRacket at startup.
c53891e @soegaard Syntax coloring works
authored
160 (lexer
2d90353 @soegaard Attempt to get syntax coloring working.
authored
161 [(eof)
c53891e @soegaard Syntax coloring works
authored
162 (syn-val lexeme 'eof #f start-pos end-pos)]
2d90353 @soegaard Attempt to get syntax coloring working.
authored
163 [(:or #\tab #\space #\newline)
c53891e @soegaard Syntax coloring works
authored
164 (syn-val lexeme 'white-space #f start-pos end-pos)]
2d90353 @soegaard Attempt to get syntax coloring working.
authored
165 [(:or ":=" "+" "-" "*" "/" "^" "<" ">" "=" "\"")
c53891e @soegaard Syntax coloring works
authored
166 (syn-val lexeme 'symbol #f start-pos end-pos)]
2d90353 @soegaard Attempt to get syntax coloring working.
authored
167 [(:or "(" ")" "[" "]" "{" "}")
c53891e @soegaard Syntax coloring works
authored
168 (syn-val lexeme 'parenthesis #f start-pos end-pos)]
2d90353 @soegaard Attempt to get syntax coloring working.
authored
169 [(:or "[[" "," ";" "." "λ" "lambda" "" "¬" "" "<=" "" ">=" "<>" "")
c53891e @soegaard Syntax coloring works
authored
170 (syn-val lexeme 'no-color #f start-pos end-pos)]
2d90353 @soegaard Attempt to get syntax coloring working.
authored
171 ["define"
c53891e @soegaard Syntax coloring works
authored
172 (syn-val lexeme 'constant #f start-pos end-pos)]
aa52845 @soegaard Attempting to fix the interaction reader in the REPL
authored
173 [comment
174 (syn-val lexeme 'comment #f start-pos end-pos)]
2d90353 @soegaard Attempt to get syntax coloring working.
authored
175 [string
c53891e @soegaard Syntax coloring works
authored
176 (syn-val lexeme 'string #f start-pos end-pos)]
2d90353 @soegaard Attempt to get syntax coloring working.
authored
177 ; The parser can only look ahead 1 token, so we have 3
178 ; different identifiers to see whether := or ( comes after the identfier.
179 ; This is enough to prevent shift/reduce conflicts between atom, definition,
180 ; and application.
553318f @soegaard Refinement of Check Syntax arrows
authored
181 [":="
c53891e @soegaard Syntax coloring works
authored
182 (syn-val lexeme 'symbol #f start-pos end-pos)]
553318f @soegaard Refinement of Check Syntax arrows
authored
183 [identifier
184 (syn-val lexeme 'symbol #f start-pos end-pos)]
2d90353 @soegaard Attempt to get syntax coloring working.
authored
185 [(:+ digit)
c53891e @soegaard Syntax coloring works
authored
186 (syn-val lexeme 'constant #f start-pos end-pos)]
2d90353 @soegaard Attempt to get syntax coloring working.
authored
187 [(:: (:+ digit) #\. (:* digit))
aa52845 @soegaard Attempting to fix the interaction reader in the REPL
authored
188 (syn-val lexeme 'constant #f start-pos end-pos)]
189 ; catch anything else
190 [any-char
191 (syn-val lexeme 'error #f start-pos end-pos)]))
2d90353 @soegaard Attempt to get syntax coloring working.
authored
192
94ac668 @soegaard Add original property to parsed identifiers. This allow Check Syntax …
authored
193 ; read-syntax puts on the syntax-object read s.t.
194 ; DrRacket knows it is original syntax.
195 ; And then DrRacket draws arrows after check syntax.
196 (define (sym->original-syntax sym srcloc)
197 (define p (open-input-string (symbol->string sym)))
198 (port-count-lines! p)
199 (match-define (list source-name line column position span) srcloc)
200 (set-port-next-location! p line column position)
201 (read-syntax source-name p))
1ae5539 @soegaard Inital commit
authored
202
203 ;; A macro to build the syntax object
94ac668 @soegaard Add original property to parsed identifiers. This allow Check Syntax …
authored
204 (define-for-syntax (build stx original?)
1ae5539 @soegaard Inital commit
authored
205 (syntax-case stx ()
206 [(_ o value start end)
94ac668 @soegaard Add original property to parsed identifiers. This allow Check Syntax …
authored
207 (if original?
208 #'(borg o value start end 0 0)
209 #'(b o value start end 0 0))]
1ae5539 @soegaard Inital commit
authored
210 [(_ o value start end start-adjust end-adjust)
211 (with-syntax
94ac668 @soegaard Add original property to parsed identifiers. This allow Check Syntax …
authored
212 ([start-pos (datum->syntax #'start
213 (string->symbol
214 (format "$~a-start-pos"
215 (syntax->datum #'start))))]
216 [end-pos (datum->syntax #'end
217 (string->symbol
218 (format "$~a-end-pos"
219 (syntax->datum #'end))))]
220 [org (if original? #t #f)])
1ae5539 @soegaard Inital commit
authored
221 #`(datum->syntax
94ac668 @soegaard Add original property to parsed identifiers. This allow Check Syntax …
authored
222 o
223 (if (and org (or (symbol? value) (identifier? value)))
224 (sym->original-syntax
225 value (list (if (syntax? o) (syntax-source o) 'missing-in-action--sorry)
226 (if (and o (syntax-line o))
227 (+ (syntax-line o) (position-line start-pos) start-adjust -1) #f)
228 (if (and o (syntax-column o))
229 (+ (syntax-column o) (position-offset start-pos) start-adjust) #f)
230 (if (and o (syntax-position o))
231 (+ (syntax-position o) (- (position-offset start-pos) start-adjust 1)) #f)
232 (- (+ (position-offset end-pos) end-adjust)
233 (+ (position-offset start-pos) start-adjust))))
234 value)
235 (list (if (syntax? o) (syntax-source o) 'missing-in-action--sorry)
236 (if (and o (syntax-line o))
237 (+ (syntax-line o) (position-line start-pos) start-adjust -1) #f)
238 (if (and o (syntax-column o))
239 (+ (syntax-column o) (position-offset start-pos) start-adjust) #f)
240 (if (and o (syntax-position o))
241 (+ (syntax-position o) (- (position-offset start-pos) start-adjust 1)) #f)
242 (- (+ (position-offset end-pos) end-adjust)
243 (+ (position-offset start-pos) start-adjust)))
244 o o))]))
245
246 (define-syntax (b stx)
247 (build stx #f))
248
249 (define-syntax (borg stx)
250 (define out (build stx #t))
251 ;(displayln (list 'borg out))
252 out)
253
1ae5539 @soegaard Inital commit
authored
254
255 ; for testing: builds lists instead of syntax objects
256 #;(define-syntax (b stx)
257 (syntax-case stx ()
258 [(_ _ val _ _)
259 #'val]))
260
261 (define (display-position-token pos)
262 (display (position->list pos)))
263
264 (define (position->list pos)
265 (list (position-offset pos)
266 (position-line pos)
267 (position-col pos)))
268
269 (define source-name #f)
270 (define orig-stx #f)
271 (define o #f)
272
273 (define (expression-parser src-name orig)
274 (λ (gen)
275 (set! source-name src-name)
276 (set! orig-stx orig)
277 (set! o orig)
278 (the-parser gen)))
279
280
281 (define the-parser
282 (parser
283 (src-pos)
284 ;(debug "parser-dump.txt")
285 ;(yacc-output "parser-dump.yacc")
286 (start start)
287 (end newline EOF)
288 (tokens value-tokens op-tokens)
289 (error (lambda (token-ok? name val start end)
290 ; The first argument will be #f if and only if the error is that an invalid token was received.
291 ; The second and third arguments will be the name and the value of the token at which the error was detected.
292 ; The fourth and fifth arguments, if present, provide the source positions of that token.
293 #;(unless #f #; (string? (syntax->datum o))
294 (display "DEBUGXXX: ")
295 (display (list o token-ok? name val start end))
296 (display-position-token start) (newline)
297 (display-position-token end) (newline)
298 (displayln source-name)
299 (newline))
300 (error-print-source-location #t)
301 (displayln "Syntax error")
302 (raise-read-error
303 "Syntax error"
304 source-name
305 (position-line start)
306 (position-col start)
307 (position-offset start)
c53891e @soegaard Syntax coloring works
authored
308 (+ (- (position-offset end) (position-offset start))))))
1ae5539 @soegaard Inital commit
authored
309
310 (precs ; (left :=)
94ac668 @soegaard Add original property to parsed identifiers. This allow Check Syntax …
authored
311 ; (right OP)
312 (left - +)
313 (left * /)
314 (right OB)
315 (right ^)
316 (left =) ; comparisons
317 (right NEG)
318 (left SEMI)
319 ; (right IDENTIFIER)
320 )
1ae5539 @soegaard Inital commit
authored
321
322 (grammar
323 (start [(exp) (b o `(#%infix ,$1) 1 1)]
324 [() #f])
325 ;; If there is an error, ignore everything before the error
326 ;; and try to start over right after the error
327
328 (args [(exp) (b o (list $1) 1 1)]
329 [(exp COMMA args) (b o (cons $1 $3) 1 3)]
330 [() '()])
331
332 (ids [() '()]
333 [(IDENTIFIER ids) (b o (cons $1 $2) 1 2)])
94ac668 @soegaard Add original property to parsed identifiers. This allow Check Syntax …
authored
334
1ae5539 @soegaard Inital commit
authored
335 (parenthensis-exp
336 [(OP exp CP) $2])
337
338 (atom
339 [(NUMBER) (b o $1 1 1)]
94ac668 @soegaard Add original property to parsed identifiers. This allow Check Syntax …
authored
340 [(IDENTIFIER) (prec IDENTIFIER) (borg o $1 1 1)]
1ae5539 @soegaard Inital commit
authored
341 [(STRING) (b o $1 1 1)]
6edd14c @soegaard Special values are now supported.
authored
342 [(SPECIAL) (b o $1 1 1)]
1ae5539 @soegaard Inital commit
authored
343 [(parenthensis-exp) $1])
344
345 (construction-exp
346 [(OC args CC) (b o `(,(b o 'list 1 3) ,@$2) 1 3)]
347 [(OP LAMBDA ids PERIOD exp CP) (b o `(,(b o 'lambda 2 2) ,$3 ,$5) 1 6)]
348 [(atom) $1])
349
350 (application-exp
351 ;[(application-exp OB args CB) (b o `(,$1 ,@$3) 1 4)] ; function application
352 ; Due the extra ( in IDENTIFIEROP we need to adjust the end with -1.
94ac668 @soegaard Add original property to parsed identifiers. This allow Check Syntax …
authored
353 [(IDENTIFIEROP args CP) (b o `(,(borg o $1 1 1 0 -1) ,@$2) 1 3)] ; function application
1ae5539 @soegaard Inital commit
authored
354 [(application-exp OP args CP) (prec OP) (b o `(,$1 ,@$3) 1 4 )] ; function application
355 [(application-exp ODB exp CB CB) (b o `(,(b o 'list-ref 1 4) ,$1 ,$3) 1 4)] ; list ref
356 [(construction-exp) $1])
357
94ac668 @soegaard Add original property to parsed identifiers. This allow Check Syntax …
authored
358
1ae5539 @soegaard Inital commit
authored
359 #;(implicit-exp
360 [(application-exp application-exp) (prec *) (b o `(,(b o '* 1 2) ,$1 ,$2) 1 2)] ; implicit
361 [(application-exp) $1])
362
363 (power-exp
364 [(application-exp ^ power-exp) (prec ^) (b o `(expt ,$1 ,$3) 1 3)]
365 [(application-exp) $1])
366
367 (sqrt-exp
368 [(SQRT sqrt-exp) (b o `(,(b o 'sqrt 1 1) ,$2) 1 2)]
369 [(power-exp) $1])
370
371 (negation-exp
372 [(- negation-exp) (b o `(,(b o '- 1 1) ,$2) 1 2)]
373 [(sqrt-exp) $1])
374
375 (multiplication-exp
376 [(multiplication-exp * negation-exp) (prec *) (b o `(,(b o '* 2 2) ,$1 ,$3) 1 3)]
377 [(multiplication-exp / negation-exp) (prec /) (b o `(,(b o '/ 2 2) ,$1 ,$3) 1 3)]
378 ;[(multiplication-exp negation-exp) (prec *) (b o `(,(b o '* 1 2) ,$1 ,$2) 1 2)]
379 [(negation-exp) $1])
94ac668 @soegaard Add original property to parsed identifiers. This allow Check Syntax …
authored
380
1ae5539 @soegaard Inital commit
authored
381 (addition-exp
382 [(addition-exp - multiplication-exp) (prec -) (b o `(,(b o '- 2 2) ,$1 ,$3) 1 3)]
383 [(addition-exp + multiplication-exp) (prec +) (b o `(,(b o '+ 2 2) ,$1 ,$3) 1 3)]
384 [(multiplication-exp) $1])
385
386 (order-exp
387 [(addition-exp LESS-EQUAL addition-exp) (prec =) (b o `(,(b o '<= 2 2) ,$1 ,$3) 1 3)]
388 [(addition-exp < addition-exp) (prec =) (b o `(,(b o '< 2 2) ,$1 ,$3) 1 3)]
389 [(addition-exp GREATER-EQUAL addition-exp) (prec =) (b o `(,(b o '>= 2 2) ,$1 ,$3) 1 3)]
390 [(addition-exp > addition-exp) (prec =) (b o `(,(b o '> 2 2) ,$1 ,$3) 1 3)]
391 [(addition-exp NOT-EQUAL addition-exp) (prec =) (b o `(not (,(b o '= 2 2) ,$1 ,$3)) 1 3)]
392 [(addition-exp = addition-exp) (prec =) (b o `(,(b o '= 2 2) ,$1 ,$3) 1 3)]
393 [(addition-exp) $1])
394
395 (logical-negation-exp
396 [(NEG logical-negation-exp) (prec NEG) (b o `(,(b o 'not 1 1) ,$2) 1 2)]
397 [(order-exp) $1])
398
399 ; The no DEFINE version conflicts with application.
400 ; Solution? Move definition with := into rule for application.
401 (assignment-exp
402 ;[(DEFINE IDENTIFIER := assignment-exp) (b o `(,(b o 'define 3 3) ,$2 ,$4) 2 4)]
403 ;[(DEFINE IDENTIFIER OP args CP := assignment-exp) (b o `(,(b o 'define 4 4) (,$2 ,@$4) ,$7) 2 6)]
94ac668 @soegaard Add original property to parsed identifiers. This allow Check Syntax …
authored
404 [(IDENTIFIER:= assignment-exp) (borg o `(,(b o 'define 1 1)
405 ,(borg o $1 1 1
1ae5539 @soegaard Inital commit
authored
406 ; adjust end with -2 due to the chars in :=
407 0 -2)
408 ,(b o $2 2 2)) 1 2)]
94ac668 @soegaard Add original property to parsed identifiers. This allow Check Syntax …
authored
409 [(IDENTIFIEROP args CP := assignment-exp) (b o `(,(b o 'define 2 2) (,(borg o $1 1 1) ,@(borg o $2 2 2)) ,$5) 1 5)]
1ae5539 @soegaard Inital commit
authored
410 [(logical-negation-exp) $1])
411
412 (compound-exp
413 [(compound-exp SEMI assignment-exp) (b o `(,(b o 'begin 2 2) ,$1 ,$3) 1 3)]
414 [(assignment-exp) $1])
94ac668 @soegaard Add original property to parsed identifiers. This allow Check Syntax …
authored
415
1ae5539 @soegaard Inital commit
authored
416 (exp
3c1ebea @soegaard Make the presence of a terminating semi colon optional
authored
417 [(compound-exp) $1]
418 [(compound-exp SEMI) $1]) ; the last SEMI is optional
419 )))
1ae5539 @soegaard Inital commit
authored
420
421 (define (parse-expression src stx ip)
422 (port-count-lines! ip)
aa52845 @soegaard Attempting to fix the interaction reader in the REPL
authored
423 (define out
3c1ebea @soegaard Make the presence of a terminating semi colon optional
authored
424 ((expression-parser
425 (if src src (object-name ip))
426 ; If you change any of these values, then
427 ; you must change the builder b which uses
428 ; the the values in here to add to newly read
429 ; objects. If the lexer/parser was only to
430 ; read from entire files, there would be no problem,
431 ; but sometimes one must read from strings
432 ; entered in a repl. There the syntax-objects must be
433 ; adjusted.
434 (datum->syntax #f
435 'here
436 (list (if src src (object-name ip))
437 1 ; line 1
438 0 ; column 0
439 1 ; offset/position 1 (contract for datum->syntax requires a positive offset)
440 #f) ; span
441 )) ; no properties
442 ; The following Tom Foolery is to needed to turn
443 ; SEMI EOF into EOF
444 ; This allows one to have an optional semi colon in the end of the file.
445 (λ () (expression-lexer ip))))
4283d69 @soegaard Bracket expressions are now correctly read in the DrRacket REPL
authored
446 ;(displayln out)
447 (if (eq? out #f)
448 eof
449 out))
Something went wrong with that request. Please try again.