first commit
This commit is contained in:
commit
627ac5fe66
|
@ -0,0 +1,4 @@
|
|||
An interpreter for the [Brainf**k](https://esolangs.org/wiki/Brainfuck) esoteric programming language written in Racket Lisp.
|
||||
|
||||
This implemetation includes the `!` operator which allows all following characters to be read into the input tape automatically.
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
#lang racket
|
||||
(require "semantics.rkt")
|
||||
(provide greater-than
|
||||
less-than
|
||||
plus
|
||||
minus
|
||||
period
|
||||
comma
|
||||
colon
|
||||
brackets
|
||||
(rename-out [my-module-begin #%module-begin]))
|
||||
|
||||
;; The current-state is a parameter used by the
|
||||
;; rest of this language.
|
||||
(define current-state (make-parameter (new-state)))
|
||||
|
||||
;; Every module in this language will make sure that it
|
||||
;; uses a fresh state.
|
||||
(define-syntax-rule (my-module-begin body ...)
|
||||
(#%plain-module-begin
|
||||
(parameterize ([current-state (new-state)])
|
||||
body ...)))
|
||||
|
||||
(define-syntax-rule (greater-than)
|
||||
(increment-ptr (current-state)))
|
||||
|
||||
(define-syntax-rule (less-than)
|
||||
(decrement-ptr (current-state)))
|
||||
|
||||
(define-syntax-rule (plus)
|
||||
(increment-byte (current-state)))
|
||||
|
||||
(define-syntax-rule (minus)
|
||||
(decrement-byte (current-state)))
|
||||
|
||||
(define-syntax-rule (period)
|
||||
(write-byte-to-stdout (current-state)))
|
||||
|
||||
(define-syntax-rule (comma)
|
||||
(read-byte-from-stdin (current-state)))
|
||||
|
||||
(define-syntax-rule (colon)
|
||||
(write-number-to-stdout (current-state)))
|
||||
|
||||
(define-syntax-rule (brackets body ...)
|
||||
(loop (current-state) body ...))
|
||||
|
||||
#|
|
||||
(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)
|
||||
(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)
|
||||
(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)
|
||||
(period)(minus)(minus)(minus)(period)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(period)(period)(plus)(plus)(plus)(period)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)
|
||||
(minus)(plus)(plus)(plus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)
|
||||
(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)
|
||||
(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(plus)(plus)(plus)(plus)(plus)(plus)
|
||||
(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(plus)(period)
|
||||
(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)
|
||||
(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)(comma)(period)(brackets(comma)(period))
|
||||
|#
|
||||
|
||||
#|
|
||||
;Hello World!
|
||||
(plus)(plus)(plus)(plus)(plus) (plus)(plus)(plus)(plus)(plus)
|
||||
(brackets
|
||||
(greater-than) (plus)(plus)(plus)(plus)(plus) (plus)(plus)
|
||||
(greater-than) (plus)(plus)(plus)(plus)(plus) (plus)(plus)
|
||||
(plus)(plus)(plus) (greater-than) (plus)(plus)(plus)
|
||||
(greater-than) (plus) (less-than)(less-than)(less-than)
|
||||
(less-than) (minus))
|
||||
(greater-than) (plus)(plus) (period)
|
||||
(greater-than) (plus) (period)
|
||||
(plus)(plus)(plus)(plus)(plus) (plus)(plus) (period)
|
||||
(period) (plus)(plus)(plus) (period)
|
||||
(greater-than) (plus)(plus) (period)
|
||||
(less-than)(less-than) (plus)(plus)(plus)(plus)(plus)
|
||||
(plus)(plus)(plus)(plus)(plus) (plus)(plus)(plus)(plus)(plus)
|
||||
(period) (greater-than) (period)
|
||||
(plus)(plus)(plus) (period)
|
||||
(minus)(minus)(minus)(minus)(minus)(minus)(period)
|
||||
(minus)(minus)(minus)(minus)(minus)(minus)(minus)(minus)
|
||||
(period)(greater-than) (plus) (period) (greater-than) (period)
|
||||
|#
|
|
@ -0,0 +1,71 @@
|
|||
#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)]))
|
|
@ -0,0 +1,11 @@
|
|||
#lang s-exp syntax/module-reader "language.rkt"
|
||||
#:read my-read
|
||||
#:read-syntax my-read-syntax
|
||||
|
||||
(require "parser.rkt")
|
||||
|
||||
(define (my-read-syntax src in)
|
||||
(parse-expr src in))
|
||||
|
||||
(define (my-read in)
|
||||
(syntax->datum (my-read-syntax #f in)))
|
|
@ -0,0 +1,62 @@
|
|||
#lang racket
|
||||
(require rackunit)
|
||||
(provide (all-defined-out))
|
||||
;; Our state contains two pieces.
|
||||
(define-struct state (data ptr) #:mutable)
|
||||
|
||||
;; Creates a new state, with a byte array of 30000 zeros, and
|
||||
;; the pointer at index 0.
|
||||
(define (new-state)
|
||||
(make-state (make-vector 30000 0) 0))
|
||||
|
||||
;; increment the data pointer
|
||||
(define (increment-ptr a-state)
|
||||
(set-state-ptr! a-state (add1 (state-ptr a-state))))
|
||||
|
||||
;; decrement the data pointer
|
||||
(define (decrement-ptr a-state)
|
||||
(set-state-ptr! a-state (sub1 (state-ptr a-state))))
|
||||
|
||||
;; increment the byte at the data pointer
|
||||
(define (increment-byte a-state)
|
||||
(define v (state-data a-state))
|
||||
(define i (state-ptr a-state))
|
||||
(vector-set! v i (add1 (vector-ref v i))))
|
||||
|
||||
;; decrement the byte at the data pointer
|
||||
(define (decrement-byte a-state)
|
||||
(define v (state-data a-state))
|
||||
(define i (state-ptr a-state))
|
||||
(vector-set! v i (sub1 (vector-ref v i))))
|
||||
|
||||
;; print the byte at the data pointer
|
||||
(define (write-byte-to-stdout a-state)
|
||||
(define v (state-data a-state))
|
||||
(define i (state-ptr a-state))
|
||||
;(write-byte (vector-ref v i) (current-output-port)))
|
||||
(cond
|
||||
[(eof-object? (vector-ref v i));if the vector is pointing at eof; then set the current position to zero
|
||||
(vector-set! v i 0)]
|
||||
[else
|
||||
(write-byte (vector-ref v i) (current-output-port))]))
|
||||
|
||||
;;prints the byte as a number at the data pointer
|
||||
(define (write-number-to-stdout a-state)
|
||||
(define v (state-data a-state))
|
||||
(define i (state-ptr a-state))
|
||||
(print (vector-ref v i) (current-output-port)))
|
||||
|
||||
;; read a byte from stdin into the data pointer
|
||||
(define (read-byte-from-stdin a-state)
|
||||
(define v (state-data a-state))
|
||||
(define i (state-ptr a-state))
|
||||
(vector-set! v i (read-byte (current-input-port))))
|
||||
|
||||
;; loops
|
||||
(define-syntax-rule (loop a-state body ...)
|
||||
(local [(define (loop)
|
||||
(unless (= (vector-ref (state-data a-state) (state-ptr a-state))
|
||||
0)
|
||||
body ...
|
||||
(loop)))]
|
||||
(loop)))
|
|
@ -0,0 +1,20 @@
|
|||
#lang reader "reader.rkt"
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.---.+++++++.
|
||||
.+++.----------+++
|
||||
------------------------------------------------------------------------
|
||||
++++++++++++++++++++++++++++++++.--------------------------------,.[,.]!World
|
||||
|
||||
increments and decrements tape location 0 to write HELLO
|
||||
|
||||
increments and decrements tape location 0 in the following way 79-10+3-72+32 = 32 {space}
|
||||
|
||||
32-32 = 0; {NULL}
|
||||
|
||||
Reads {W} from input and then prints {W}
|
||||
Reads {o} from input and then prints {o}
|
||||
Reads {r} from input and then prints {r}
|
||||
Reads {l} from input and then prints {l}
|
||||
Reads {d} from input and then prints {d}
|
||||
Reads {NULL} from input and then breaks loop since tape location 0 is now {0}
|
||||
|
||||
(then prints all of this text because it is after the '!')
|
|
@ -0,0 +1,22 @@
|
|||
#lang reader "reader.rkt"
|
||||
|
||||
>
|
||||
I +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>
|
||||
N ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>
|
||||
F ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>
|
||||
I +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>
|
||||
N ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>
|
||||
I +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>
|
||||
T ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>
|
||||
E +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>
|
||||
++++++++++++++++++++++++++++++++.>
|
||||
L ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>
|
||||
O +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>
|
||||
O +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>
|
||||
P ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>
|
||||
++++++++++++++++++++++++++++++++.>
|
||||
<[[<]>.[>.]<]
|
||||
|
||||
>,.[>,.]
|
||||
<[[<]>.[>.]<]
|
||||
!INFINITE LOOP
|
|
@ -0,0 +1,20 @@
|
|||
#lang reader "reader.rkt"
|
||||
|
||||
,.>>+<<[,.>>+<<] this is the simple cat program it reads in a value then moves 2 to the right and adds 1 to the counter then moves back to the input cell again
|
||||
|
||||
>++++++++++++++++++++++++++++++++.[-] we leave the 2nd print the space
|
||||
|
||||
>- Have to subtract 1 because otherwise it will include the eof character
|
||||
|
||||
>>++++++++++<<[->+>-[>+>>]>[+[-<+>]>+>>]<<<<<<]>> in cell do N modulo 10
|
||||
[-]>>>++++++++++<[->-[>+>>]>[+[-<+>]>+>>]<<<<<]> in cell do N modulo 10
|
||||
[-]>>[>++++++[-<++++++++>]<. print hundreds
|
||||
<<+>+>[-]]<[<[->-<]++++++[->++++++++<]>.[-]] print tens
|
||||
<<++++++[-<++++++++>]<. print ones
|
||||
[-]<<[-<+>]< cleanup
|
||||
|
||||
[-] reset the buffer
|
||||
++++++++++. print newline
|
||||
|
||||
test input
|
||||
!Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque gravida arcu id arcu eleifend pulvinar. Sed metus.
|
|
@ -0,0 +1,15 @@
|
|||
#lang reader "reader.rkt"
|
||||
|
||||
,.>>+<<[,.>>+<<] this is the simple cat program it reads in a value then moves 2 to the right and adds 1 to the counter then moves back to the input cell again
|
||||
|
||||
>++++++++++++++++++++++++++++++++. we leave the 2nd print the space
|
||||
|
||||
>- Have to subtract 1 becuase otherwise it will incude the eof character
|
||||
|
||||
: Print the value (using one of the bf extensions)
|
||||
|
||||
[-] reset the buffer
|
||||
++++++++++. print newline
|
||||
|
||||
test input
|
||||
!Input
|
|
@ -0,0 +1,5 @@
|
|||
#lang reader "reader.rkt"
|
||||
|
||||
>,.[>,.]<<[.<]
|
||||
|
||||
!race
|
|
@ -0,0 +1,28 @@
|
|||
#lang reader "reader.rkt"
|
||||
|
||||
0 1 2 3 4 5
|
||||
(input 11)(input 12)(input 21)(input 22)(input 1 count)(input 2 count)
|
||||
|
||||
,------------------------------------------------ in 0; read input ; subtract ascii zero
|
||||
[->>>>++++++++++<<<<] in 0; add 10 for each number in 0 to 4
|
||||
> goto 1
|
||||
,------------------------------------------------ in 1; read input ; subtract ascii zero
|
||||
[->>>+<<<] in 1; add 1 for each number in 1 to 4
|
||||
> goto 2
|
||||
,------------------------------------------------ in 2; read input ; subtract ascii zero
|
||||
[->>>++++++++++<<<] in 2; add 10 for each number in 2 to 5
|
||||
> goto 3
|
||||
,------------------------------------------------ in 3; read input ; subtract ascii zero
|
||||
[->>+<<] in 3; add 1 for each number in 3 to 5
|
||||
> goto 4
|
||||
>[<+>-]< add each number in 5 to 4
|
||||
|
||||
>>++++++++++<<[->+>-[>+>>]>[+[-<+>]>+>>]<<<<<<]>> in cell 4 do N modulo 10
|
||||
[-]>>>++++++++++<[->-[>+>>]>[+[-<+>]>+>>]<<<<<]> in cell 4 do N modulo 10
|
||||
[-]>>[>++++++[-<++++++++>]<. print hundreds
|
||||
<<+>+>[-]]<[<[->-<]++++++[->++++++++<]>.[-]] print tens
|
||||
<<++++++[-<++++++++>]<. print ones
|
||||
[-]<<[-<+>]< cleanup
|
||||
|
||||
testing data
|
||||
!9999
|
|
@ -0,0 +1,2 @@
|
|||
#lang reader "reader.rkt"
|
||||
,------------------------------------------------[->>>>++++++++++<<<<]>,------------------------------------------------[->>>+<<<]>,------------------------------------------------[->>>++++++++++<<<]>,------------------------------------------------[->>+<<]>>[<+>-]<>>++++++++++<<[->+>-[>+>>]>[+[-<+>]>+>>]<<<<<<]>>[-]>>>++++++++++<[->-[>+>>]>[+[-<+>]>+>>]<<<<<]>[-]>>[>++++++[-<++++++++>]<.<<+>+>[-]]<[<[->-<]++++++[->++++++++<]>.[-]]<<++++++[-<++++++++>]<.[-]<<[-<+>]<!9999
|
Loading…
Reference in New Issue