brainfudge/parser.rkt

71 lines
2.6 KiB
Racket
Raw Normal View History

2022-09-03 23:32:08 -04:00
#lang racket
(require rackunit)
(require racket/port)
;; The only visible export of this module will be parse-expr.
(provide parse-expr)
#|
(define code "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.---.+++++++..+++.---------
-+++------------------------------------------------------------------------++++++++++++++++++++++++++++++++.
--------------------------------,.[,.]!Input")
(cond [(regexp-match-positions "!" code) (substring code (cdar (regexp-match-positions "!" code)))])
(cond [(regexp-match-positions "!" code) (open-input-bytes (string->bytes/utf-8 (substring code (cdar (regexp-match-positions "!" code)))))])
|#
;; parse-expr: any input-port -> (U syntax eof)
;; Either produces a syntax object or the eof object.
(define (parse-expr src in)
(define code (file->string src));file to string
(cond [(regexp-match-positions "!" code) (current-input-port (open-input-bytes (string->bytes/utf-8 (substring code (cdar (regexp-match-positions "!" code))))))])
(define-values (line column position) (port-next-location in))
(define next-char (read-char in))
;; decorate/span: s-expression number -> syntax
;; Wrap the s-expression with source location.
(define (decorate sexp span)
(datum->syntax #f sexp (list src line column position span)))
(cond
[(eof-object? next-char) eof]
[else
(case next-char
[(#\<) (decorate '(less-than) 1)]
[(#\>) (decorate '(greater-than) 1)]
[(#\+) (decorate '(plus) 1)]
[(#\-) (decorate '(minus) 1)]
[(#\,) (decorate '(comma) 1)]
[(#\.) (decorate '(period) 1)]
[(#\:) (decorate '(colon) 1)]
[(#\[)
;; The slightly messy case is bracket. We keep reading
;; a list of exprs, and then construct a wrapping bracket
;; around the whole thing.
(define elements (parse-exprs src in))
(define-values (l c tail-position)
(port-next-location in))
(decorate `(brackets ,@elements)
(- tail-position position))]
[else
(parse-expr src in)])]))
;; parse-exprs: input-port -> (listof syntax)
;; Parse a list of expressions.
(define (parse-exprs source-name in)
(define peeked-char (peek-char in))
(cond
[(eof-object? peeked-char)
(error 'parse-exprs "Expected ], but read eof")]
[(char=? peeked-char #\])
(read-char in)
empty]
[(member peeked-char (list #\< #\> #\+ #\- #\, #\. #\[ #\:))
(cons (parse-expr source-name in)
(parse-exprs source-name in))]
[else
(read-char in)
(parse-exprs source-name in)]))