Racket's reader is a recursive-descent parser. It reads one datum at a time from a stream of characters; the datums of a module are then read by the macro expander as code. The rules below are those of the default readtable, as the Racket Reference (chapter 1.4, The Reader) gives them. A language written in S-expressions uses them; other languages (Scribble, Rhombus, Datalog) bring their own reader.
Delimiters and dispatch
White space, a byte-order mark and these characters are delimiters, which end a name or number: ( ) [ ] { } " , ' ` ;. A delimited sequence that starts with any other character is read as a symbol, a number or an extflonum. In it, # has a meaning only as the first character; | starts text that is taken as it stands (spaces and delimiters included) up to the next |; and \ takes the next character as it stands. The reader then chooses by the first characters:
| Starts with | Reads as |
|---|---|
( [ { | a list or pair, ended by the matching bracket of any of the three kinds |
) ] } | an error unless it ends a list |
" | a string |
' ` , ,@ | quote, quasiquote, unquote, unquote-splicing |
; | a line comment |
#t #f #true #false | booleans (upper case too) |
#( #[ #{ and #3( | a vector, with an optional length |
#fl( #fx( (and #Fl, #Fx, with a length) | a flvector or fxvector |
#s( | a prefab structure |
#\ | a character |
#" | a byte string |
#<< | a here string |
#rx #px #rx# #px# | a regular expression (string or byte string follows) |
#hash #hasheq #hasheqv #hashalw | an immutable hash table |
#& | a box |
#: | a keyword |
#% | a symbol (the #%app family) |
#| #; #! | block comment, S-expression comment, line comment (or #lang alias) |
#' #` #, #,@ | syntax, quasisyntax, unsyntax, unsyntax-splicing |
#e #i #b #o #d #x | a number with a prefix |
#ci #cs | switch case sensitivity for the datum that follows |
#reader #lang | a reader extension; see below |
#~ | compiled code (a binary form; not written by hand) |
#0= #0# | a graph tag and a reference to it |
| anything else | a symbol (or a number, if it parses as one) |
Comments
| Form | Reads |
|---|---|
; … | to the next line break (linefeed, carriage return, next-line, line separator or paragraph separator) |
#| … |# | a block comment; they nest |
#; datum | reads one datum and drops it; a comment on a list covers the whole list |
#! or #!/ … | a line comment that continues to the next line if the line ends with a backslash; used as the first line of a script |
#lang racket
#| a block comment #| nested |# still a comment |#
(define xs '(1 2 3)) ; to the end of the line
(list 1 #;(this is dropped) 2 #;3 4) ; => '(1 2 4)
Symbols and keywords
A symbol is a delimited sequence that is not a number. . alone is never a symbol (it makes a pair), |a b| and a\ b are symbols with a space in them, and #%app is a symbol. Symbols are case-sensitive unless read-case-sensitive is false or #ci is used; letters in |…| or after \ are never folded. A keyword is #: followed by symbol characters and is never read as a number: #:1 is a keyword.
Numbers
A sequence is a number when it matches the grammar below (in any letter case). The same grammar holds in every radix; the radix changes only the digits and, for hexadecimal, which letters are exponent marks.
| Part | Forms |
|---|---|
| Exactness prefix | #e (exact) or #i (inexact); may come before or after a radix prefix, as in #e#x10 and #x#e10 |
| Radix prefix | #b binary, #o octal, #d decimal, #x hexadecimal |
| Integer | an optional sign and digits: -12, +7 |
| Rational | 1/2, -3/4 (exact) |
| Decimal | 1.5, .5, 5.; inexact unless #e or read-decimal-as-inexact is false |
| Exponent | digits, an exponent mark and an integer: 1e3. The marks are s l d e f (in hexadecimal only s l, since d e f are digits). f and s mean single-precision where single flonums are supported and enabled, and otherwise double precision |
| # digits | a # after the digits stands for an unknown digit and reads as 0: 1#.#, 12#.## |
| Complex | rectangular 1+2i, +i, 1/2-3/4i, and polar 1@2 |
| Specials | +inf.0 -inf.0 +nan.0 -nan.0 (double) and +inf.f -inf.f +nan.f -nan.f (single) |
| Extflonum | a decimal with t as the exponent mark: 1.0t0, 1t2, and +inf.t -inf.t +nan.t -nan.t; a radix prefix is allowed, an exactness prefix is not, and it cannot be part of a complex number |
42 -7 1/3 3.14 .5 6.02e23 1e-3 #e1.5 #i1/3 #x1F #b1010 #o777
1+2i 3@1.5708 +inf.0 -nan.0 1.0t0 #x#e1.8
1+ is not a number; it is a name (the function that adds one in the older dialects of Scheme).Strings and byte strings
A string runs from " to the next " that a backslash does not escape. It may hold raw newlines. These escapes are recognised; any other backslash is a read error.
| Escape | Means |
|---|---|
\a \b \t \n \v \f \r \e | alarm (7), backspace (8), tab (9), linefeed (10), vertical tab (11), formfeed (12), return (13), escape (27) |
\" \' \\ | the character itself (the backslash before ' has no effect) |
\ and 1 to 3 octal digits | the character with that code, from 0 to 255 (the longest form wins) |
\x and 1 or 2 hexadecimal digits | that code |
\u and 1 to 4 hexadecimal digits | that code; two escapes \uD83D\uDE00 in the surrogate ranges make one character |
\U and 1 to 8 hexadecimal digits | that code (it must be a valid character) |
\ then a line break | nothing: the line break is dropped, so a string can continue on the next line |
A byte string is #"…". It takes the same escapes except \u and \U, and every character that is not escaped must have a code from 0 to 255.
Here strings
#<< and a terminator word, up to the end of the line, starts a here string. Its text is every line after that, up to a line that holds only the terminator. No escape is recognised, a carriage return is not a line break here, and the text of the terminator line is not part of the string. A here string with an empty terminator, or one that reaches the end of the file without its terminator, is a read error.
(define poem #<<END
Roses are "red"; \n is not an escape here
END
)
(define s "tab:\t and unicode:\u03BB\U1F600 and \x41 and \101")
(define b #"bytes \x00\xFF")
printf, format, eprintf, fprintf, error and raise-user-error read their format string with ~ directives: ~a display, ~s write, ~v print, ~e error format, ~c a character, ~b ~o ~x numbers in base 2, 8 or 16, ~n or ~% a newline, ~~ a tilde, ~.a ~.s ~.v truncated output, and a ~ followed by white space skips the white space. Upper-case letters give the same directives. The viewer marks these directives in a literal first or second argument of those functions.
Characters
#\ starts a character. The forms are:
| Form | Character |
|---|---|
#\nul or #\null | NUL (0) |
#\backspace | backspace (8) |
#\tab | tab (9) |
#\newline or #\linefeed | linefeed (10) |
#\vtab | vertical tab (11) |
#\page | form feed (12) |
#\return | carriage return (13) |
#\space | space (32) |
#\rubout | delete (127) |
#\ and exactly 3 octal digits | that code: #\101 is A |
#\u and 1 to 4 hex digits, #\U and 1 to 8 | that code: #\u3BB is λ |
#\ and one character | the character, as long as it and the character after it are not both alphabetic (so #\a, #\a) and #\( work; #\ab is an error), and it is not an octal digit followed by an octal digit |
The names are read only when the next character is not alphabetic. The viewer colours the whole #\… token as a string.
Quotation
| Prefix | Same as |
|---|---|
' d | (quote d) |
` d | (quasiquote d) |
, d | (unquote d) |
,@ d | (unquote-splicing d) |
#' d | (syntax d) |
#` d | (quasisyntax d) |
#, d | (unsyntax d) |
#,@ d | (unsyntax-splicing d) |
The longest prefix wins. The `, , and ,@ forms can be turned off with read-accept-quasiquote.
Lists, pairs and brackets
(…), […] and {…} read the same and may be mixed only if each closes with its own kind. A delimited . before the last datum makes a pair: (1 . 2), (1 2 . 3). A pair of delimited dots around a middle element is the reader's infix notation: (1 . + . 2) reads as (+ 1 2). The reader marks which bracket was used (the 'paren-shape property), and can be told to tag lists in square brackets or braces (read-square-bracket-with-tag, read-curly-brace-with-tag) or to refuse them. By habit, square brackets mark the clauses of cond, case, let and similar forms.
Vectors, structures, hash tables and boxes
| Form | Reads |
|---|---|
#(1 2 3), #[…], #{…} | a vector. #3(a b) is a vector of length 3: the last element repeats to fill it, and an empty #3() is filled with 0 |
#fl(1.0 2.0), #fl3(…) | a flvector (each element is read as if prefixed with #i) |
#fx(1 2), #fx3(…) | a fxvector (each element is read as if prefixed with #e) |
#s(name field …) | an instance of a prefab structure; the first datum is the prefab key (a symbol in the simplest case). #s(posn 1 2) |
#hash((k . v) …) | an immutable hash table keyed by equal?; #hasheq uses eq?, #hasheqv uses eqv?, #hashalw uses equal-always?. A later pair for the same key hides an earlier one |
#&d | a box holding d |
In read-syntax mode flvectors and fxvectors are not allowed. The contents of all of these are data, never code: in #(a (f x)) the list is a list.
Regular expressions
#rx"…" reads as (regexp "…"), #px"…" as (pregexp "…"), #rx#"…" as (byte-regexp #"…") and #px#"…" as (byte-pregexp #"…"). The text after the prefix is read as a string or byte string, so each regular-expression backslash is doubled: #px"\\d+". See Strings and regexps for the syntax inside.
Graph structure
#1=100 tags the next datum with the number 1 and #1# stands for that datum, so the reader can make shared or circular data: #0=(1 . #0#) is an infinite list. A tag has up to eight digits, must be defined once and before its use, and is accepted by read (and by read-syntax only when read-syntax-accept-graph is true; the default is false). A tag inside a #; comment can still be used by other parts of the same enclosing datum.
Reader extensions: #reader and #lang
#reader followed by a datum (usually a module path) loads that module's read or read-syntax function and gives it the rest of the stream. #lang name is the constrained form: one space, then a name of ASCII letters and digits and + - _ / (not starting or ending with /), ended by white space. It means #reader (submod name reader) if that submodule exists, and otherwise #reader name/lang/reader. #!name is another spelling of #lang name. read-accept-reader and read-accept-lang turn them off.
The module that read-accept-reader and #lang load defines the language, which is why a file's contents can mean anything: see The #lang family. The reader can also be changed from within, with a custom readtable (make-readtable), which changes what each character starts. The viewer does not follow readtables.
How the viewer colours the tokens
| Colour | Tokens |
|---|---|
| Comment | ;, #| |#, #; with the datum it drops, #! lines, and Scribble's @; comments |
| String | strings, byte strings, here strings, the text of regular expressions, characters #\x |
| String escape (literal colour) | the escapes in strings and byte strings |
| Number | every number, extflonum and special value that parses under the grammar above |
| Literal | #t #f #true #false, keywords #:key, null empty true false eof pi, string escapes |
| Directive | #lang and its language name, #reader, quote marks ' ` , ,@ #' #` #, #,@, vector, struct, hash and box prefixes, #rx and #px, graph tags, #ci #cs #~, format directives in strings, and the @ and brackets of Scribble forms |
| Keyword | special forms and syntax words (define lambda let cond match struct class require provide …), every name beginning define-, define/, for/, for*/ or let/, ..., _, #%app and the other kernel forms |
| Function | the head of a call, the names of the procedures of racket/base and the common libraries, in-… and current-… names |
| Type | module paths in require and the language of module, class names ending in %, contract names ending in /c, exn:… types, prop:… and gen:… names, structure type names, and in a typed module every type |
| Variable | the names a form binds: parameters, let and for bindings, struct fields, pattern variables |
The colouring follows the text, not the program. A macro the program defines is coloured as a function call unless its name starts define- or for/.
Not described
Known, not yet covered
- Viewer: the contents of a regular expression (character classes, groups,
(?:) are coloured as an ordinary string, not as regexp syntax. - Viewer:
#~compiled-code literals are marked at the two characters only; what follows is read as ordinary tokens. - Viewer: custom readtables,
read-cdot(C-style infix dot) andread-square-bracket-with-tagare not followed; the default readtable is assumed. Reader modules written by the user (#reader) are read by the default reader after their module path. - Reference: the Reference sections on readtables, the printer (how values are written back) and the parameters of
readwere read only in part.
See also
- Data types – what these tokens become
- Strings and regexps – string functions and the regular-expression language
- Scheme: lexical structure – the Scheme reader, which Racket differs from in brackets, keywords and here strings