summaryrefslogtreecommitdiff
path: root/src/lexer-test.lisp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lexer-test.lisp')
-rw-r--r--src/lexer-test.lisp189
1 files changed, 95 insertions, 94 deletions
diff --git a/src/lexer-test.lisp b/src/lexer-test.lisp
index 916af29..c6f131a 100644
--- a/src/lexer-test.lisp
+++ b/src/lexer-test.lisp
@@ -1,32 +1,79 @@
(in-package :monkey)
-(defun make-tokens (&rest tokens)
- (loop :for token :in tokens
- :if (consp token)
- :collect (make-token (car token) (cadr token))
- :if (typep token 'token-type)
- :collect (as-token token)))
+(defparameter *tests* (make-hash-table))
+(defparameter *test-name* nil)
-(defun test-lexer (str expect)
- (let ((lexer (make-lexer str)))
- (not (find nil (mapcar #'token= (lexer-tokens lexer) expect)))))
+(eval-always
+ (defun make-tokens (&rest tokens)
+ (loop :for token :in tokens
+ :if (consp token)
+ :collect (make-token (car token) (cadr token))
+ :if (typep token 'token-type)
+ :collect (as-token token)))
+ (defun test-lexer (str expected-tokens)
+ (labels ((expected-next ()
+ (prog1 (car expected-tokens)
+ (setf expected-tokens (cdr expected-tokens)))))
+ (format t "Testing ~s..." *test-name*)
+ (let* ((lexer (make-lexer str))
+ (tokens (lexer-tokens lexer))
+ (expected-token (expected-next))
+ (ok t))
+ (loop :for token :in tokens
+ :for i :from 1
+ :if (not (token= token expected-token))
+ :do (format t "~&token ~d: expected ~a but got ~a~%" i expected-token token)
+ (setf ok nil)
+ :else :do (setf expected-token (expected-next)))
+ (unless (null ok)
+ (format t " ok~%")))))
-(defun test-1 ()
- (test-lexer "=+(){},;"
- (make-tokens :t/=
- :t/+
- :t/lparen
- :t/rparen
- :t/lbrace
- :t/rbrace
- :t/comma
- :t/semicolon
- :t/eof)))
+ (defun tokenize (designator)
+ (cond ((typep designator 'token-type)
+ (as-token designator))
+ ((stringp designator)
+ (make-token :t/ident designator))
+ ((integerp designator)
+ (make-token :t/int (princ-to-string designator)))
+ ((characterp designator)
+ (case designator
+ (#\( (as-token :t/lparen))
+ (#\) (as-token :t/rparen))
+ (#\; (as-token :t/semicolon))
+ (#\{ (as-token :t/lbrace))
+ (#\} (as-token :t/rbrace))))
+ ((consp designator)
+ (apply #'make-token designator))))
+ (defun define-lexer-test (name string tokens)
+ `(progn
+ (setf (gethash ',name *tests*) t)
+ (defun ,name ()
+ (let ((*test-name* ',name))
+ (test-lexer ,string (list ,@(mapcar (lambda (tok) `(tokenize ',tok))
+ tokens)))))))
-(defun test-2 ()
- (test-lexer "let five = 5;
+ (defmacro deftest ((type &optional name) &body args)
+ (case type
+ (:lexer (apply #'define-lexer-test
+ (or name (gensym "LEXER-TEST"))
+ args)))))
+
+(defun run-tests ()
+ (let ((ok t) key val)
+ (with-hash-table-iterator (it *tests*)
+ (loop :do (multiple-value-setq (ok key val) (it))
+ :while ok
+ :do (funcall (symbol-function key))))))
+
+(deftest (:lexer test-1)
+ "=+(){},;"
+ (:t/= :t/+ :t/lparen :t/rparen
+ :t/lbrace :t/rbrace :t/comma :t/semicolon :t/eof))
+
+(deftest (:lexer test-2)
+ "let five = 5;
let ten = 10;
let add = fn(x, y) {
@@ -45,75 +92,29 @@ if (5 < 10) {
10 == 10;
10 != 9;
"
- (make-tokens :t/let
- (list :t/ident "five")
- :t/=
- (list :t/int "5")
- :t/semicolon
- :t/let
- (list :t/ident "ten")
- :t/=
- (list :t/int "10")
- :t/semicolon
- :t/let
- (list :t/ident "add")
- :t/=
- :t/function
- :t/lparen
- (list :t/ident "x")
- :t/comma
- (list :t/ident "y")
- :t/rparen
- :t/lbrace
- (list :t/ident "x")
- :t/+
- (list :t/ident "y")
- :t/rbrace
- :t/semicolon
- :t/let
- (list :t/ident "result")
- :t/=
- (list :t/ident "add")
- :t/lparen
- (list :t/ident "five")
- :t/comma
- (list :t/ident "ten")
- :t/rparen
- :t/semicolon
- :t/!
- :t/-
- :t//
- :t/*
- :t/semicolon
- (list :t/int "5")
- :t/<
- (list :t/int "10")
- :t/>
- (list :t/int "5")
- :t/semicolon
- (list :t/if "if")
- :t/lparen
- (list :t/int "5")
- :t/<
- (list :t/int "10")
- :t/rparen
- :t/lbrace
- :t/return
- :t/true
- :t/semicolon
- :t/rbrace
- :t/else
- :t/lbrace
- :t/return
- :t/false
- :t/semicolon
- :t/rbrace
- (list :t/int "10")
- :t/==
- (list :t/int "10")
- :t/semicolon
- (list :t/int "10")
- :t/!=
- (list :t/int "9")
- :t/semicolon
- :t/eof "")))
+ (:t/let "five" :t/= 5 #\;
+ :t/let "ten" :t/= 10 #\;
+ :t/let "add" :t/= :t/function #\( "x" :t/comma "y" #\) #\{
+ "x" :t/+ "y" #\;
+ #\} #\;
+ :t/let "result" :t/= "add" #\( "five" :t/comma "ten" #\) #\;
+ :t/! :t/- :t// :t/* #\;
+ 5 :t/< 10 :t/> 5 #\;
+ :t/if #\( 5 :t/< 10 #\) #\{
+ :t/return :t/true #\;
+ #\} :t/else #\{
+ :t/return :t/false #\;
+ #\}
+ 10 :t/== 10 #\;
+ 10 :t/!= 9 #\;
+ :t/eof))
+
+
+(deftest (:lexer test-fail)
+ "abc gf 5 fn =+(){},;"
+ (:t/= :t/+ :t/lparen :t/rparen
+ :t/lbrace :t/rbrace :t/comma :t/semicolon :t/eof))
+
+(deftest (:lexer test-fail-2)
+ "let abc x + 5;"
+ (:t/let "abc" :t/= "x" :t/+ 5 :t/eof))