#lang racket ; The grammar for expressions is as follows: ; ::= | "or" ; ::= | "and" ; ::= | "not" ; ::= | ("<" | ">" | "<=" | ">=" | "==" | "!=") ; ::= | ("+" | "-") ; ::= | ("*" | "/" | "//" | %) ; ::= | "**" | ("-" | "+") ; ::= | "(" ")" | | True | False | ; "(" ")" ; ::= math.sin | math.cos | tan | math.log | math.exp | abs | ; float | math.ceil | math.floor | math.sqrt ; make these definitions available outside this module (provide (all-defined-out)) ; load supporting code (require "hw7-support.rkt") ; common error check that a list is nonempty (define (require-pair lst) (if (not (pair? lst)) (error "invalid syntax") #t)) (define (parse-expression lst) (require-pair lst) (parse-and lst)) (define (parse-and lst) (require-pair lst) (parse-negation lst)) (define (parse-negation lst) (require-pair lst) (parse-test lst)) (define (parse-test lst) (require-pair lst) (parse-additive lst)) (define (parse-additive lst) (require-pair lst) (parse-term lst)) (define (parse-term lst) (require-pair lst) (parse-element lst)) (define (parse-element lst) (require-pair lst) (parse-factor lst)) (define (parse-factor lst) (require-pair lst) (list (car lst))) ; main driver loop (define (idle) (display ">>> ") (let* ([input (read-line)] [tokens (tokenize input)]) (cond ((equal? input "quit()") (display "bye bye...")) ((not (pair? tokens)) (idle)) (else (begin (if (and (symbol? (car tokens)) (> (length tokens) 1) (eq? (cadr tokens) '=)) (add-var (car tokens) (car (parse-expression (cddr tokens)))) (let ([result (parse-expression tokens)]) (begin (if (= (length result) 1) (let ([result2 (car result)]) (cond ((eq? result2 #t) (display "True")) ((eq? result2 #f) (display "False")) ((number? result2) (display result2)) (else (error "illegal syntax")))) (error "illegal syntax")) (newline)))) (idle)))))) ; variation of main driver that catches errors (define (run) (with-handlers ((exn:fail? (lambda (exn) (display "syntax error") (newline) (run)))) (idle)))