#lang racket/base (require brag/examples/simple-arithmetic-grammar brag/support racket/set br-parser-tools/lex racket/list rackunit) (define (tokenize ip) (port-count-lines! ip) (define lex/1 (lexer-src-pos [(repetition 1 +inf.0 numeric) (token 'INT (string->number lexeme))] [whitespace (token 'WHITESPACE #:skip? #t)] ["+" (token '+ "+")] ["*" (token '* "*")] [(eof) (token eof)])) (lambda () (lex/1 ip))) ;; expr : term ('+' term)* ;; term : factor (('*') factor)* ;; factor : INT (check-equal? (syntax->datum (parse #f (tokenize (open-input-string "42")))) '(expr (term (factor 42)))) (check-equal? (syntax->datum (parse #f (tokenize (open-input-string "3+4")))) '(expr (term (factor 3)) "+" (term (factor 4)))) (check-equal? (syntax->datum (parse #f (tokenize (open-input-string "3+4+5")))) '(expr (term (factor 3)) "+" (term (factor 4)) "+" (term (factor 5)))) (check-equal? (syntax->datum (parse #f (tokenize (open-input-string "3*4*5")))) '(expr (term (factor 3) "*" (factor 4) "*" (factor 5)))) (check-equal? (syntax->datum (parse #f (tokenize (open-input-string "3*4 + 5*6")))) '(expr (term (factor 3) "*" (factor 4)) "+" (term (factor 5) "*" (factor 6)))) (check-equal? (syntax->datum (parse #f (tokenize (open-input-string "4*5+6")))) '(expr (term (factor 4) "*" (factor 5)) "+" (term (factor 6)))) (check-equal? (syntax->datum (parse #f (tokenize (open-input-string "4+5 *6")))) '(expr (term (factor 4)) "+" (term (factor 5) "*" (factor 6)))) (check-exn exn:fail:parsing? (lambda () (parse #f (tokenize (open-input-string "7+"))))) (check-exn exn:fail:parsing? (lambda () (parse #f (tokenize (open-input-string "7+6+"))))) (check-equal? all-token-types (set '+ '* 'INT))