diff --git a/README.md b/README.md index 2bf3c19..3b046ca 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# easybf / DrBrainf\*ck +# DrBrainf\*ck This is the repo for the PF1 final project of _Claudio Maggioni_ and _Tommaso Rodolfo Masera_. @@ -15,7 +15,5 @@ Run the file `gui.rkt` using *DrRacket* or the `racket` CLI tool. ## Bugs -- `[` and `]` are not brainf\*ck compliant since the interpreter does not - search for the matching bracket but it considers the nearest bracket; - `,` function not implemented (will crash the program if encountered); - No validation or user-friendly error handling. diff --git a/interpreter.rkt b/interpreter.rkt index ae3c36d..8f7dab5 100644 --- a/interpreter.rkt +++ b/interpreter.rkt @@ -230,23 +230,44 @@ (check-expect (char-at "malusa" 2) "l") (check-error (char-at "another string" 300)) -; find-first: 1String String Nat (Nat -> Nat) -> Nat -; Given a 1String `char`, a String `string` and a start index, returns -; the position of the first occurrence of `char` in `string` starting from the -; index walking the string changing the index using the `walk` function. -(define (find-first char string start walk) - (cond [(string=? (substring string start (add1 start)) - char) start] - [else (find-first char string (walk start) walk)])) +; WalkingDirection can be one of: +; - 'forward +; - 'backward +; Interpretation: the direction to walk the Brainf*ck Program with. + +; find-matching: Program Nat WalkingDirection -> Nat +; Given a program, a starting position in the progam and a walking direction +; returns the position of the matching bracket waking in the direction provided. +(define (find-matching prg start wd) + + (define brkt (if (symbol=? wd 'forward) #\] #\[)) + (define oppos-brkt (if (symbol=? wd 'forward) #\[ #\])) + (define upd-start (if (symbol=? wd 'forward) add1 sub1)) + + ; fm-helper Nat Nat -> Nat + ; Given a starting position and a nest accumulator, returns the position of + ; the matching bracket waking in the direction provided by updating the + ; accumulator recursively with the current level of nesting. + (define (fm-helper s nest) + (cond + [(and (zero? nest) (char=? (string-ref prg s) brkt)) + s] + [(char=? (string-ref prg s) oppos-brkt) + (fm-helper (upd-start s) (add1 nest))] + [(char=? (string-ref prg s) brkt) + (fm-helper (upd-start s) (sub1 nest))] + [else + (fm-helper (upd-start s) nest)])) + + (fm-helper (upd-start start) 0)) ; Tests for find-first -(check-expect (find-first "]" "[++++++---->><-]++++]+--" 0 add1) +(check-expect (find-matching "[++++++---->><-]++++]+--" 0 'forward) 15) -(check-expect (find-first "]" "[+++++][+---->><-]++++]+--" 7 add1) +(check-expect (find-matching "[+++++][+---->><-]++++]+--" 7 'forward) 17) -(check-expect (find-first "[" "[+++++][+---->><-]++++]+--" 17 sub1) - 7) - +(check-expect (find-matching "[+++++[]+---->><-]++++]+--" 17 'backward) + 0) ; exec-loop-start: ProgState -> ProgState ; Given a ProgState, returns a new ProgState with the [ instruction executed @@ -259,7 +280,7 @@ (prog-state-output w) (prog-state-program w) (add1 (if jump - (find-first "]" (prog-state-program w) (prog-state-ip w) add1) + (find-matching (prog-state-program w) (prog-state-ip w) 'forward) (prog-state-ip w)))))) ; Tests for exec-loop-start @@ -281,7 +302,7 @@ (prog-state-output w) (prog-state-program w) (add1 (if jump - (find-first "[" (prog-state-program w) (prog-state-ip w) sub1) + (find-matching (prog-state-program w) (prog-state-ip w) 'backward) (prog-state-ip w)))))) ; Tests for exec-loop-end @@ -320,5 +341,3 @@ "++>+++++[<+>-]++++++++[<++++++>-]<." 35)) ; Run tests (test) - -; TODO: fix matching bracket bug