#cs(module parse mzscheme (require parser-tools/lex (prefix : parser-tools/lex-sre) "cfg-parser.ss" parser-tools/yacc syntax/readerr "prims.ss") (define-lex-abbrevs [lex:letter (:or (:/ #\a #\z) (:/ #\A #\Z))] [lex:digit (:/ #\0 #\9)] [lex:whitespace (:or #\newline #\return #\tab #\space #\vtab)] [lex:comment (:: (:* lex:whitespace) "comment" (:* (:~ #\;)) #\;)]) (define-tokens non-terminals ( GOTO IF THEN ELSE FOR DO STEP UNTIL WHILE OWN ARRAY STRING PROCEDURE SWITCH LABEL VALUE BEGIN END POWER PLUS MINUS TIMES SLASH DIVIDE LESS LESS-OR-EQUAL EQUAL GREATER-OR-EQUAL GREATER NOT-EQUAL ASSIGN NEGATE AND OR IMPLIES EQUIV COMMA COLON SEMICOLON OPEN CLOSE OPENSQ CLOSESQ EOF UNPARSEABLE)) (define stx-for-original-property (read-syntax #f (open-input-string "original"))) (define-syntax (token stx) (syntax-case stx () [(_ name val) (identifier? (syntax name)) (let ([name (syntax name)]) (with-syntax ([token-name (datum->syntax-object name (string->symbol (format "token-~a" (syntax-e name))))] [source-name (datum->syntax-object name 'source-name)] [start-pos (datum->syntax-object name 'start-pos)] [end-pos (datum->syntax-object name 'end-pos)]) (syntax (token-name (datum->syntax-object #f val (list source-name (position-line start-pos) (position-col start-pos) (position-offset start-pos) (- (position-offset end-pos) (position-offset start-pos))) stx-for-original-property)))))])) (define-syntax (ttoken stx) (syntax-case stx () [(_ name) (identifier? (syntax name)) (syntax (token name 'name))])) (define (lex source-name) (lexer [(:+ lex:whitespace) (void)] ["true" (token #t)] ["false" (token #f)] ["real" (token 'real)] ["integer" (token 'integer)] ["Boolean" (token 'boolean)] ["goto" (ttoken GOTO)] ["if" (ttoken IF)] ["then" (ttoken THEN)] ["else" (ttoken ELSE)] ["for" (ttoken FOR)] ["do" (ttoken DO)] ["step" (ttoken STEP)] ["until" (ttoken UNTIL)] ["while" (ttoken WHILE)] ["own" (ttoken OWN)] ["array" (ttoken ARRAY)] ["string" (ttoken STRING)] ["procedure" (ttoken PROCEDURE)] ["switch" (ttoken SWITCH)] ["label" (ttoken LABEL)] ["value" (ttoken VALUE)] [(:: "begin" lex:comment) (ttoken BEGIN)] ["begin" (ttoken BEGIN)] [(:: "end" lex:comment) (ttoken BEGIN)] ["end" (ttoken END)] ["^" (token POWER 'expt)] ["+" (token PLUS '+)] ["-" (token MINUS '-)] ["*" (token TIMES '*)] ["/" (token SLASH '/)] ["div" (token DIVIDE 'quotient)] ["<" (token LESS '<)] ["<=" (token LESS-OR-EQUAL '<=)] ["=" (token EQUAL '=)] [">" (token GREATER '>)] [">=" (token GREATER-OR-EQUAL '>=)] ["!=" (token NOT-EQUAL '!=)] ["!" (token NEGATE '!)] ["&" (token AND '&)] ["|" (token OR '\|)] ["=>" (token IMPLIES '==>)] ["==" (token EQUIV '==)] [":=" (ttoken ASSIGN)] ["," (ttoken COMMA)] [":" (ttoken COLON)] [(:: ";" lex:comment) (ttoken SEMICOLON)] [";" (ttoken SEMICOLON)] ["(" (ttoken OPEN)] [")" (ttoken CLOSE)] ["[" (ttoken OPENSQ)] ["]" (ttoken CLOSESQ)] [(:: lex:letter (:* (:or lex:letter lex:digit))) (token (string->symbol lexeme))] [(:+ lex:digit) (token (string->number lexeme))] [(:or (:: (:+ lex:digit) #\. (:* lex:digit)) (:: (:* lex:digit) #\. (:+ lex:digit))) (token (string->number lexeme))] [(:: #\` (:* (:~ #\' #\`)) #\') (let ([s lexeme]) (token (substring s 1 (sub1 (string-length s)))))] [(eof) (ttoken EOF)] [any-char (token UNPARSEABLE (string->symbol lexeme))])) (define parse (cfg-parser (tokens non-terminals) (start ) (end EOF) (error (lambda (a b stx) (raise-read-error (format "parse error near ~a" (syntax-e stx)) (syntax-source stx) (syntax-line stx) (syntax-column stx) (syntax-position stx) (syntax-span stx)))) (suppress) (grammar ;; ==================== Expressions ==================== ( [() $1] [() $1] [() $1]) ;; -------------------- Numbers -------------------- ( [() $1] [(IF THEN ELSE ) (make-a60:if $2 $4 $6)]) ( [() $1] [( ) (make-a60:unary 'num 'num $1 $2)] [( ) (make-a60:binary 'num 'num $2 $1 $3)]) ( [() $1] [( ) (make-a60:binary 'num 'num $2 $1 $3)]) ( [() $1] [( POWER ) (make-a60:binary 'num 'num $2 $1 $3)]) ( [(PLUS) $1] [(MINUS) $1]) ( [(TIMES) $1] [(SLASH) $1] [(DIVIDE) $1]) ( [() $1] [() $1] [() $1] [() $1] [(OPEN CLOSE) $2]) ;; -------------------- Booleans -------------------- ( [(LESS) $1] [(LESS-OR-EQUAL) $1] [(EQUAL) $1] [(GREATER-OR-EQUAL) $1] [(GREATER) $1] [(NOT-EQUAL) $1]) ( [( ) (make-a60:binary 'bool 'num $2 $1 $3)]) ( [() $1] [() $1] [() $1] [() $1] [(OPEN CLOSE) $2]) ( [() $1] [(NEGATE ) (make-a60:unary 'bool 'bool $1 $2)]) ( [() $1] [( AND ) (make-a60:binary 'bool 'bool $2 $1 $3)]) ( [() $1] [( OR ) (make-a60:binary 'bool 'bool $2 $1 $3)]) ( [() $1] [( IMPLIES ) (make-a60:binary 'bool 'bool $2 $1 $3)]) ( [() $1] [( EQUIV ) (make-a60:binary 'bool 'bool $2 $1 $3)]) ( [() $1] [(IF THEN ELSE ) (make-a60:if $2 $4 $6)]) ;; -------------------- Designationals -------------------- (