elisp-reader.test 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. ;;;; elisp-reader.test --- Test the reader used by the Elisp compiler.
  2. ;;;;
  3. ;;;; Copyright (C) 2009 Free Software Foundation, Inc.
  4. ;;;; Daniel Kraft
  5. ;;;;
  6. ;;;; This library is free software; you can redistribute it and/or
  7. ;;;; modify it under the terms of the GNU Lesser General Public
  8. ;;;; License as published by the Free Software Foundation; either
  9. ;;;; version 3 of the License, or (at your option) any later version.
  10. ;;;;
  11. ;;;; This library is distributed in the hope that it will be useful,
  12. ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. ;;;; Lesser General Public License for more details.
  15. ;;;;
  16. ;;;; You should have received a copy of the GNU Lesser General Public
  17. ;;;; License along with this library; if not, write to the Free Software
  18. ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. (define-module (test-elisp-reader)
  20. :use-module (test-suite lib)
  21. :use-module (language elisp lexer)
  22. :use-module (language elisp parser))
  23. ; ==============================================================================
  24. ; Test the lexer.
  25. (define (get-string-lexer str)
  26. (call-with-input-string str get-lexer))
  27. (define (lex-all lexer)
  28. (let iterate ((result '()))
  29. (let ((token (lexer)))
  30. (if (eq? (car token) 'eof)
  31. (reverse result)
  32. (iterate (cons token result))))))
  33. (define (lex-string str)
  34. (lex-all (get-string-lexer str)))
  35. (with-test-prefix "Lexer"
  36. (let ((lexer (get-string-lexer "")))
  37. (pass-if "end-of-input"
  38. (and (eq? (car (lexer)) 'eof)
  39. (eq? (car (lexer)) 'eof)
  40. (eq? (car (lexer)) 'eof))))
  41. (pass-if "single character tokens"
  42. (equal? (lex-string "()[]'`,,@ . ")
  43. '((paren-open . #f) (paren-close . #f)
  44. (square-open . #f) (square-close . #f)
  45. (quote . #f) (backquote . #f)
  46. (unquote . #f) (unquote-splicing . #f) (dot . #f))))
  47. (pass-if "whitespace and comments"
  48. (equal? (lex-string " (\n\t) ; this is a comment\n. ; until eof")
  49. '((paren-open . #f) (paren-close . #f) (dot . #f))))
  50. (pass-if "source properties"
  51. (let ((x (car (lex-string "\n\n \n . \n"))))
  52. (and (= (source-property x 'line) 4)
  53. (= (source-property x 'column) 3))))
  54. (pass-if "symbols"
  55. (equal? (lex-string "foo FOO char-to-string 1+ \\+1
  56. \\(*\\ 1\\ 2\\)
  57. +-*/_~!@$%^&=:<>{}
  58. abc(def)ghi .e5")
  59. `((symbol . foo) (symbol . FOO) (symbol . char-to-string)
  60. (symbol . 1+) (symbol . ,(string->symbol "+1"))
  61. (symbol . ,(string->symbol "(* 1 2)"))
  62. (symbol . +-*/_~!@$%^&=:<>{})
  63. (symbol . abc) (paren-open . #f) (symbol . def)
  64. (paren-close . #f) (symbol . ghi) (symbol . .e5))))
  65. ; Here we make use of the property that exact/inexact numbers are not equal?
  66. ; even when they have the same numeric value!
  67. (pass-if "integers"
  68. (equal? (lex-string "-1 1 1. +1 01234")
  69. '((integer . -1) (integer . 1) (integer . 1) (integer . 1)
  70. (integer . 1234))))
  71. (pass-if "floats"
  72. (equal? (lex-string "1500.0 15e2 15.e2 1.5e3 .15e4 -.345e-2")
  73. '((float . 1500.0) (float . 1500.0) (float . 1500.0)
  74. (float . 1500.0) (float . 1500.0)
  75. (float . -0.00345))))
  76. ; Check string lexing, this also checks basic character escape sequences
  77. ; that are then (hopefully) also correct for character literals.
  78. (pass-if "strings"
  79. (equal? (lex-string "\"foo\\nbar
  80. test\\
  81. \\\"ab\\\"\\\\ ab\\ cd
  82. \\418\\0415\\u0041\\U0000000A\\Xab\\x0000000000000004fG.\" ")
  83. '((string . "foo\nbar
  84. test\"ab\"\\ abcd
  85. !8!5A\nXabOG."))))
  86. (pass-if "ASCII control characters and meta in strings"
  87. (equal? (lex-string "\"\\^?\\C-a\\C-A\\^z\\M-B\\M-\\^@\\M-\\C-a\"")
  88. '((string . "\x7F\x01\x01\x1A\xC2\x80\x81"))))
  89. ; Character literals, taking into account that some escape sequences were
  90. ; already checked in the strings.
  91. (pass-if "characters"
  92. (equal? (lex-string "?A?\\z ? ?\\x21 ?\\^j ?\\\\?\\n?\\\n")
  93. `((character . 65) (character . ,(char->integer #\z))
  94. (character . 32) (character . ,(char->integer #\!))
  95. (character . 10) (character . ,(char->integer #\\))
  96. (character . 10) (character . 10))))
  97. (pass-if "meta characters"
  98. (equal? (map cdr (lex-string "?\\C-[?\\M-\\S-Z?\\^X?\\A-\\s-\\H-\\s"))
  99. `(,(+ (expt 2 26) (char->integer #\[))
  100. ,(+ (expt 2 27) (expt 2 25) (char->integer #\Z))
  101. ,(- (char->integer #\X) (char->integer #\@))
  102. ,(+ (expt 2 22) (expt 2 23) (expt 2 24) 32))))
  103. (pass-if "circular markers"
  104. (equal? (lex-string "#0342= #1#")
  105. '((circular-def . 342) (circular-ref . 1))))
  106. (let* ((lex1-string "#1='((1 2) [2 [3]] 5)")
  107. (lexer (call-with-input-string (string-append lex1-string " 1 2")
  108. get-lexer/1)))
  109. (pass-if "lexer/1"
  110. (and (equal? (lex-all lexer) (lex-string lex1-string))
  111. (eq? (car (lexer)) 'eof)
  112. (eq? (car (lexer)) 'eof)))))
  113. ; ==============================================================================
  114. ; Test the parser.
  115. (define (parse-str str)
  116. (call-with-input-string str read-elisp))
  117. (with-test-prefix "Parser"
  118. (pass-if "only next expression"
  119. (equal? (parse-str "1 2 3") 1))
  120. (pass-if "source properties"
  121. (let* ((list1 (parse-str "\n\n (\n(7) (42))"))
  122. (list2 (car list1))
  123. (list3 (cadr list1)))
  124. (and (= (source-property list1 'line) 3)
  125. (= (source-property list1 'column) 4)
  126. (= (source-property list2 'line) 4)
  127. (= (source-property list2 'column) 1)
  128. (= (source-property list3 'line) 4)
  129. (= (source-property list3 'column) 6))))
  130. (pass-if "constants"
  131. (and (equal? (parse-str "-12") -12)
  132. (equal? (parse-str ".123") 0.123)
  133. (equal? (parse-str "foobar") 'foobar)
  134. (equal? (parse-str "\"abc\"") "abc")
  135. (equal? (parse-str "?A") 65)
  136. (equal? (parse-str "?\\C-@") 0)))
  137. (pass-if "quotation"
  138. (and (equal? (parse-str "'(1 2 3 '4)")
  139. '(quote (1 2 3 (quote 4))))
  140. (equal? (parse-str "`(1 2 ,3 ,@a)")
  141. '(#{`}# (1 2 (#{,}# 3) (#{,@}# a))))))
  142. (pass-if "lists"
  143. (equal? (parse-str "(1 2 (3) () 4 (. 5) (1 2 . (3 4)) (1 . 2) . 42)")
  144. '(1 2 (3) () 4 5 (1 2 3 4) (1 . 2) . 42)))
  145. (pass-if "vectors"
  146. (equal? (parse-str "[1 2 [] (3 4) \"abc\" d]")
  147. #(1 2 #() (3 4) "abc" d)))
  148. (pass-if "circular structures"
  149. (and (equal? (parse-str "(#1=a #2=b #1# (#1=c #1# #2#) #1#)")
  150. '(a b a (c c b) c))
  151. (let ((eqpair (parse-str "(#1=\"foobar\" . #1#)")))
  152. (eq? (car eqpair) (cdr eqpair)))
  153. (let ((circlst (parse-str "#1=(42 #1# #1=5 #1#)")))
  154. (and (eq? circlst (cadr circlst))
  155. (equal? (cddr circlst) '(5 5))))
  156. (let ((circvec (parse-str "#1=[a #1# b]")))
  157. (eq? circvec (vector-ref circvec 1))))))