#lang racket ; Unicalc repl ; author: Robert Keller ; purpse: Provide read-eval-print loop ; Caution: Functions uniparse, multiply, divide, etc. are dummy. ; You need to provide them from your code. These loops will go through ; the motions, but don't expect them to display the correct answers as is. ; ; Two loops are provided: (repl) and (verbose). ; repl is intended for end-users, while verbose may be used for debugging. ;; repl means "read-eval-print-loop" ;; It repeats the following steps, until the end-of-file object is entered: ;; Print a prompt string. ;; Read a string from the input. ;; Parse the string. ;; If the parse has no errors, eval the result using Unicalc. ;; Format the result using format-quantity. ;; Print the formatted result. ;; Print two blank lines. (define (repl) (read-eval-print-loop 'unicalc>\ )) ;; verbose is a verbose version of the repl, ;; which shows information about the parse, as well as the unicalc value. (define (verbose) (verbose-read-eval-print-loop '\ )) ;; (terminate) is called when end-of-input is indicated. (define (terminate) (display "Thank you for using Unicalc.")) ;; The actual read-eval-print-loop, with the prompt-string as an argument: (define (read-eval-print-loop prompt) (begin (display prompt) (let ((input (read-line))) (cond [(eof-object? input) (terminate)] [else (begin (let ((outcome (uniparse input))) (begin (if (succeeded? outcome) (begin (if (null? (get-residue outcome)) null (begin (display "*** caution: unparsed residue: ") (display (list->string (get-residue outcome))) (newline))) (let ((answer (eval (get-value outcome)))) (if (error? answer) (begin (display "*** ")(display answer)) (display (format-quantity answer)) )) null) (begin (display "*** unable to parse: ") (display input) (newline) )))) (newline) (repl))])))) ;; The verbose read-eval-print loop (e.g. for debugging) (define (verbose-read-eval-print-loop prompt) (begin (display prompt) (let ((input (read-line))) (cond [(eof-object? input) (terminate)] [else (begin (display " input: ")(display input) (newline) (let ((outcome (uniparse input))) (begin (display " result: ")(display (get-result outcome)) (newline) (display " residue: ")(display (list->string (get-residue outcome))) (newline) (display " parsed: ")(display (list 'quote (get-value outcome))) (newline) (if (succeeded? outcome) (let ((answer (eval (get-value outcome)))) (if (error? answer) (begin (display "calculated: ")(display answer) (newline)) (begin (display "calculated: ")(display answer) (newline) (display " formatted: ")(display (format-quantity answer))(newline)) )) null) )) (newline) (verbose))])))) ;; error? is used to determine whether the unicalc result was an error (define (error? answer) (and (list? answer) (equal? (first answer) 'error))) ;; format-quantity governs how unicalc quantities are formatted for output. ; I'm leaving this for you to do. (define (format-quantity quantity) quantity) ; top-level parse function, returns a string as described above ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; This is part of assignments 3 and 4. Replace with your own function. ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (define (uniparse input-string) (make-outcome 'success '() '(divide (multiply (make-numeric-quantity 2345) (normalize-unit 'mile)) (normalize-unit 'hour)))) ; Construct a parser outcome (define (make-outcome result residue value) (list result residue value)) ; Get the result part of an Outcome (define (get-result Outcome) (first Outcome)) ; Get the residue part of an Outcome (define (get-residue Outcome) (second Outcome)) ; Get the value part of an Outcome (define (get-value Outcome) (third Outcome)) ; Determine whether an Outcome is succesful (define (succeeded? Outcome) (equal? 'success (get-result Outcome))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; The following are part of assignment 2. Replace with your functions. ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (define (multiply Q1 Q2) Q1) (define (divide Q1 Q2) Q1) (define (make-numeric-quantity number) (make-quantity number '() '())) (define (make-quantity multiplier numerator denominator) (list multiplier numerator denominator)) (define (normalize-unit unit) (make-quantity 1 (list unit) '())) ; Use one of these for your loop: ;(verbose) ;(repl)