reader.test 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. ;;;; reader.test --- Exercise the reader. -*- Scheme -*-
  2. ;;;;
  3. ;;;; Copyright (C) 1999, 2001, 2002, 2003, 2007, 2008 Free Software Foundation, Inc.
  4. ;;;; Jim Blandy <jimb@red-bean.com>
  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 2.1 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-suite reader)
  20. :use-module (test-suite lib))
  21. (define exception:eof
  22. (cons 'read-error "end of file$"))
  23. (define exception:unexpected-rparen
  24. (cons 'read-error "unexpected \")\"$"))
  25. (define exception:unterminated-block-comment
  26. (cons 'read-error "unterminated `#! ... !#' comment$"))
  27. (define exception:unknown-character-name
  28. (cons 'read-error "unknown character name .*$"))
  29. (define exception:unknown-sharp-object
  30. (cons 'read-error "Unknown # object: .*$"))
  31. (define exception:eof-in-string
  32. (cons 'read-error "end of file in string constant$"))
  33. (define exception:illegal-escape
  34. (cons 'read-error "illegal character in escape sequence: .*$"))
  35. (define (read-string s)
  36. (with-input-from-string s (lambda () (read))))
  37. (define (with-read-options opts thunk)
  38. (let ((saved-options (read-options)))
  39. (dynamic-wind
  40. (lambda ()
  41. (read-options opts))
  42. thunk
  43. (lambda ()
  44. (read-options saved-options)))))
  45. (with-test-prefix "reading"
  46. (pass-if "0"
  47. (equal? (read-string "0") 0))
  48. (pass-if "1++i"
  49. (equal? (read-string "1++i") '1++i))
  50. (pass-if "1+i+i"
  51. (equal? (read-string "1+i+i") '1+i+i))
  52. (pass-if "1+e10000i"
  53. (equal? (read-string "1+e10000i") '1+e10000i))
  54. ;; At one time the arg list for "Unknown # object: ~S" didn't make it out
  55. ;; of read.c. Check that `format' can be applied to this error.
  56. (pass-if "error message on bad #"
  57. (catch #t
  58. (lambda ()
  59. (read-string "#ZZZ")
  60. ;; oops, this # is supposed to be unrecognised
  61. #f)
  62. (lambda (key subr message args rest)
  63. (apply format #f message args)
  64. ;; message and args are ok
  65. #t)))
  66. (pass-if "block comment"
  67. (equal? '(+ 1 2 3)
  68. (read-string "(+ 1 #! this is a\ncomment !# 2 3)")))
  69. (pass-if "block comment finishing s-exp"
  70. (equal? '(+ 2)
  71. (read-string "(+ 2 #! a comment\n!#\n) ")))
  72. (pass-if "unprintable symbol"
  73. ;; The reader tolerates unprintable characters for symbols.
  74. (equal? (string->symbol "\001\002\003")
  75. (read-string "\001\002\003")))
  76. (pass-if "CR recognized as a token delimiter"
  77. ;; In 1.8.3, character 0x0d was not recognized as a delimiter.
  78. (equal? (read-string "one\x0dtwo") 'one))
  79. (pass-if "returned strings are mutable"
  80. ;; Per R5RS Section 3.4, "Storage Model", `read' is supposed to return
  81. ;; mutable objects.
  82. (let ((str (with-input-from-string "\"hello, world\"" read)))
  83. (string-set! str 0 #\H)
  84. (string=? str "Hello, world"))))
  85. (pass-if-exception "radix passed to number->string can't be zero"
  86. exception:out-of-range
  87. (number->string 10 0))
  88. (pass-if-exception "radix passed to number->string can't be one either"
  89. exception:out-of-range
  90. (number->string 10 1))
  91. (with-test-prefix "mismatching parentheses"
  92. (pass-if-exception "opening parenthesis"
  93. exception:eof
  94. (read-string "("))
  95. (pass-if-exception "closing parenthesis following mismatched opening"
  96. exception:unexpected-rparen
  97. (read-string ")"))
  98. (pass-if-exception "opening vector parenthesis"
  99. exception:eof
  100. (read-string "#("))
  101. (pass-if-exception "closing parenthesis following mismatched vector opening"
  102. exception:unexpected-rparen
  103. (read-string ")")))
  104. (with-test-prefix "exceptions"
  105. ;; Reader exceptions: although they are not documented, they may be relied
  106. ;; on by some programs, hence these tests.
  107. (pass-if-exception "unterminated block comment"
  108. exception:unterminated-block-comment
  109. (read-string "(+ 1 #! comment\n..."))
  110. (pass-if-exception "unknown character name"
  111. exception:unknown-character-name
  112. (read-string "#\\theunknowncharacter"))
  113. (pass-if-exception "unknown sharp object"
  114. exception:unknown-sharp-object
  115. (read-string "#?"))
  116. (pass-if-exception "eof in string"
  117. exception:eof-in-string
  118. (read-string "\"the string that never ends"))
  119. (pass-if-exception "illegal escape in string"
  120. exception:illegal-escape
  121. (read-string "\"some string \\???\"")))
  122. (with-test-prefix "read-options"
  123. (pass-if "case-sensitive"
  124. (not (eq? 'guile 'GuiLe)))
  125. (pass-if "case-insensitive"
  126. (eq? 'guile
  127. (with-read-options '(case-insensitive)
  128. (lambda ()
  129. (read-string "GuiLe")))))
  130. (pass-if "prefix keywords"
  131. (eq? #:keyword
  132. (with-read-options '(keywords prefix case-insensitive)
  133. (lambda ()
  134. (read-string ":KeyWord")))))
  135. (pass-if "prefix non-keywords"
  136. (symbol? (with-read-options '(keywords prefix)
  137. (lambda ()
  138. (read-string "srfi88-keyword:")))))
  139. (pass-if "postfix keywords"
  140. (eq? #:keyword
  141. (with-read-options '(keywords postfix)
  142. (lambda ()
  143. (read-string "keyword:")))))
  144. (pass-if "long postfix keywords"
  145. (eq? #:keyword0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
  146. (with-read-options '(keywords postfix)
  147. (lambda ()
  148. (read-string "keyword0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789:")))))
  149. (pass-if "`:' is not a postfix keyword (per SRFI-88)"
  150. (eq? ':
  151. (with-read-options '(keywords postfix)
  152. (lambda ()
  153. (read-string ":")))))
  154. (pass-if "no positions"
  155. (let ((sexp (with-read-options '()
  156. (lambda ()
  157. (read-string "(+ 1 2 3)")))))
  158. (and (not (source-property sexp 'line))
  159. (not (source-property sexp 'column)))))
  160. (pass-if "positions"
  161. (let ((sexp (with-read-options '(positions)
  162. (lambda ()
  163. (read-string "(+ 1 2 3)")))))
  164. (and (equal? (source-property sexp 'line) 0)
  165. (equal? (source-property sexp 'column) 0))))
  166. (pass-if "positions on quote"
  167. (let ((sexp (with-read-options '(positions)
  168. (lambda ()
  169. (read-string "'abcde")))))
  170. (and (equal? (source-property sexp 'line) 0)
  171. (equal? (source-property sexp 'column) 0)))))