;;; Code stored as: {turing}<3-lisp.problem-sets>arith-recognizer.3-lisp ;;; {phylum}<3-lisp>course>problem-sets>arith-recognizer.3-lisp ;;;========================================================================== ;;; Simple ARITH Expression Recognizer ;;;========================================================================== ;;; ;;; Recognizes ARITH expressions. ;;; Built on top of the Lexical Analyser ;;; ------------------------------------ ;;; Assumed grammar: ( is the primitive lexical item) ;;; ;;; ::= | ;;; ;;; ::= "+" "(" "," ")" ;;; "-" "(" "," ")" ;;; "*" "(" "," ")" ;;; "/" "(" "," ")" ;;; ARITH-RECOGNIZE Main recognition routine. Returns a message ;;; =============== identifying whether or not the STRING encodes a single ;;; well-formed ARITH expression. (define ARITH-RECOGNIZE (lambda [string] (if (null (dynamic-catch (arith-recognize-expression (lexical-analysis string)))) "Accepted" "Rejected"))) ;;; Ancillary recognition functions: ;;; ;;; The following procedures call ERROR-IN-RECOGNITION immediately upon ;;; finding a grammatical error of any sort, which does not return (since ;;; the procedures below are not designed to do anything sensible about ;;; continuing from errors), but instead does a DYNAMIC-THROW (q.v.). ;;; ARITH-RECOGNIZE-EXPRESSION Attempts to recognize an arbitrary ARITH ;;; ========================== expression. (define ARITH-RECOGNIZE-EXPRESSION (lambda [tail] (cond [(member (first tail) ["+" "*" "-" "/"]) (arith-recognize-args (rest tail))] [(numeral-expression (first tail)) (rest tail)] [$true (arith-error-in-recognition)]))) ;;; ARITH-RECOGNIZE-ARGS attempts to recognize an ARITH args expression ;;; ==================== (define ARITH-RECOGNIZE-ARGS (lambda [tail] (letseq [[tail (arith-recognize-token "(" tail)] [tail (arith-recognize-expression tail)] [tail (arith-recognize-token "," tail)] [tail (arith-recognize-expression tail)] [tail (arith-recognize-token ")" tail)]] tail))) (define ARITH-RECOGNIZE-TOKEN (lambda [token tail] (if (and (not (null tail)) (= token (first tail))) (rest tail) (arith-error-in-recognition)))) ;;; ARITH-ERROR-IN-RECOGNITION Signals an error by sending back non-empty sequence. ;;; ========================== (define ARITH-ERROR-IN-RECOGNITION (lambda [] (dynamic-throw ["something"]))) ;;; ======================================================================== ;;; DIFFERENT VERSION USING OBJECTS ;;; ======================================================================== ;;; A2-RECOGNIZE Main recognition routine. Returns a message ;;; ============ identifying whether or not the STRING encodes a single ;;; well-formed ARITH expression. (define A2-RECOGNIZE (lambda [string] (letseq [[s (lexan-object string)] [answer (dynamic-catch (a2-recognize-expression s))]] (if (and answer (= (next-token s) 'eot)) "Accepted" "Rejected")))) ;;; Ancillary recognition functions: ;;; ;;; The following procedures call ERROR-IN-RECOGNITION immediately upon ;;; finding a grammatical error of any sort, which does not return (since ;;; the procedures below are not designed to do anything sensible about ;;; continuing from errors), but instead does a DYNAMIC-THROW (q.v.). ;;; A2-RECOGNIZE-EXPRESSION Attempts to recognize an arbitrary ARITH ;;; ======================= expression. (define A2-RECOGNIZE-EXPRESSION (lambda [s] (cond [(member (next-token s) ["+" "*" "-" "/"]) (a2-recognize-args s)] [(numeral-expression (get-token s)) $true] [$true (a2-error-in-recognition)]))) ;;; A2-RECOGNIZE-ARGS Attempts to recognize an ARITH args expression ;;; ================= (define A2-RECOGNIZE-ARGS (lambda [s] (get-token s) ; skip the operator (a2-recognize-token "(" s) (a2-recognize-expression s) (a2-recognize-token "," s) (a2-recognize-expression s) (a2-recognize-token ")" s))) ;;; A2-RECOGNIZE-TOKEN Ensures that the next token in s is token ;;; ================== (define A2-RECOGNIZE-TOKEN (lambda [token s] (if (not (= token (get-token s))) (a2-error-in-recognition) $true))) ;;; A2-ERROR-IN-RECOGNITION Signals an error by sending back $false. ;;; ======================= (define A2-ERROR-IN-RECOGNITION (lambda [] (dynamic-throw $false)))