The Emacs Lisp reader (the function read, written in C in lread.c) turns text into Lisp objects. It has no separate token stage: it looks at one character and decides what to read. This page follows the reader from the first character of each form. The viewer’s colouring follows the same rules, so the colours named here are the ones the viewer uses.
White space and delimiters
Any character with a code of 32 or less, and the no-break space (U+00A0), is white space: it separates tokens and is otherwise skipped. That covers space, tab, line feed, carriage return and form feed.
| Character | What the reader does |
|---|---|
( ) | opens and closes a list; () reads as nil |
[ ] | opens and closes a vector |
" | starts a string |
' ` , | prefix: quote, backquote, comma (,@ is comma-at) |
; | starts a comment that runs to the end of the line |
# | starts one of the special forms in the table below |
? | starts a character literal |
. | between two forms in a list, makes a dotted pair; at the start of a token it may begin a number or symbol |
\ | escape: inside a symbol, takes the next character literally |
A symbol or number ends at white space or at any of " ' ; # ( ) [ ] ` ,. Braces { } and the bar | are ordinary symbol characters in Emacs Lisp (unlike Common Lisp, where | quotes). A closing parenthesis or bracket that matches nothing is a read error, and so is end of file inside a form.
Comments
A semicolon outside a string or character literal starts a comment that ends at the line end. There are no block comments. The reader also skips two other kinds of text that are not meant for source files:
#!– the rest of the line is skipped, wherever it is read (for a script’s first line);#@N– the next N characters after the digits (the separating space counts as the first) are skipped;#@00skips to the end of the file. Byte-compiled files use this to hold documentation strings that are loaded on demand (Byte-compilation).
Comments with a meaning to Emacs and to tools (;;; Commentary:, ;;;###autoload, the -*- cookie, Local Variables:) are in File structure. Viewer: comments are Comment colour; the meaningful ones are Directive.
Symbols
A symbol is any run of non-delimiter characters that is not a number. Letters of either case (symbols are case-sensitive), digits and most punctuation are allowed: forward-line, string=, 1+, *scratch*, <=, %d, @. Characters of any script are allowed too. A backslash makes the next character literal, so that a symbol can hold a delimiter or look like a number: foo\ bar, \,, \123, \?a. The symbol whose name is empty is written ##.
| Form | Meaning |
|---|---|
name | an interned symbol, looked up in the obarray (after expanding any shorthand, see below) |
:name | a keyword: a symbol that is interned in the obarray, evaluates to itself, and cannot be set (viewer: Literal) |
#:name | an uninterned symbol, made fresh each time it is read; #: alone is an uninterned symbol with an empty name (viewer: Literal) |
#_name | an interned symbol read without shorthand expansion; #_ alone is the empty symbol |
## | the interned symbol with an empty name |
Shorthands (Emacs 28 and later): a file can set read-symbol-shorthands as a file-local variable to a list of pairs such as (("foo-" . "my-long-package-prefix-")). The reader then expands a symbol that starts with the short prefix to the long one, so that source can use short names for names with a long prefix. #_ and #: turn the expansion off for one symbol.
Naming conventions that tools rely on: foo-p or foop for a predicate, foo-mode for a mode and its variable, foo-mode-hook and foo-functions for hooks, foo-mode-map for a keymap, foo--bar for a private name of the package foo, foo- as a prefix for every name in the package. Names that end in -hook, -function, -functions, -map and several others are treated as risky as file-local variables.
Numbers
A token is read as a number only if it starts with a digit, ., - or +, has no backslash and is entirely number syntax. Everything else that looks similar is a symbol: 1+ and 1- are function names, 1e and 12abc are symbols.
| Kind | Syntax | Examples |
|---|---|---|
| Integer | optional sign, decimal digits, optional trailing .; fixnum or bignum depending on size (bignums since Emacs 27) | 42 -7 +3 10. |
| Radix integer | #b binary, #o octal, #x hexadecimal (letters of either case), or #Nr with a radix 2 to 36; an optional sign after the prefix | #b101 #o17 #xFF #x-1f #24r1k |
| Float | digits with a decimal point and at least one digit after or before it, and/or an exponent e/E with a sign and digits; no suffix letters | 1.5 .5 -3.14 1e3 1.5e-3 +15e2 |
| Infinity and NaN | a float with the exponent e+INF or e+NaN; the sign is part of the number and a NaN carries a sign and a payload | 1.0e+INF -1.0e+INF 0.0e+NaN -0.0e+NaN |
There are no ratios or complex numbers in the language itself (the calc package has its own). 1. is the integer 1 and 1.0 the float. The printer never writes a leading + or a trailing .. Viewer: all of these are Number colour; a token like 1+ is a name.
Character syntax: ?c
A character is an integer, and its source syntax is a question mark followed by the character: ?a is 97, ?A is 65, ?あ is 12354. The viewer shows character syntax in Number colour because that is what it reads as. A character that the reader treats specially must be escaped with a backslash: ?\( ?\) ?\[ ?\] ?\\ ?\; ?\"; the manual advises escaping | ' ` # . , too, and ?\ or ?\s for a space. The reader does accept an unescaped ?( ?) ?[ ?] ?" or ?;, but it records the character in lread--unescaped-character-literals and the byte compiler warns about it. A literal space or tab after the question mark is accepted (? ); a literal newline, return or form feed is not, and a backslash before a newline (?\LF) is an error. The character must be followed by white space or by one of " ' ; ( ) [ ] # ? ` , .; anything else (?ab) is an invalid-read-syntax error.
| Escape | Character |
|---|---|
?\a ?\b ?\t ?\n ?\v ?\f ?\r | 7 (bell), 8 (backspace), 9 (tab), 10 (newline), 11 (vertical tab), 12 (form feed), 13 (return) |
?\e ?\d ?\s ?\\ | 27 (escape), 127 (delete), 32 (space), 92 (backslash) |
?\C-x ?\^x | control x: the code is that of the letter with the control bit; ?\^I and ?\C-i are 9, ?\^? and ?\C-? are 127 |
?\M-x | meta x: bit 227 set |
?\S-x ?\H-x ?\s-x ?\A-x | shift (225), hyper (224), super (223), alt (222); \s is super only when followed by -, otherwise it is a space; modifiers can be chained: ?\C-\M-a, ?\H-\M-\A-x |
?\x41 | hexadecimal code: one or more hex digits (?\xe0); large values can carry modifier bits |
?\101 | octal code: up to three octal digits (?\0 to ?\777) |
?\u00e0 ?\U000000e0 | Unicode code point, exactly four or eight hex digits (at most U+10FFFF) |
?\N{U+E0} ?\N{LATIN SMALL LETTER A WITH GRAVE} | Unicode code point or character name; runs of white space in a name count as one space |
?\z (any other) | a backslash before a character with no special meaning is harmless: ?\+ is ?+ |
Strings
A string starts and ends with ". A new line inside it is part of the string. The same escapes as for characters are available without the question mark, with these differences:
| Escape | Effect in a string |
|---|---|
\" \\ | a double quote, a backslash |
\n \t \r \f \v \a \b \e \d | the control character (as for ?) |
\LF and \ (backslash, space) | nothing: the reader ignores them, so a long string can be continued on the next line |
\s | a space; use a plain space instead |
\x41 \101 \u00e9 \U000000e9 \N{…} | the character with that code or name (use \x41\ to end a hex escape before a hex-digit letter) |
\C-a \^I | the ASCII control character; control characters outside ASCII cannot be in a string |
\M-a | the character with bit 7 set; the string becomes unibyte |
\0 to \377 with a value of 128 or more, \x80 to \xff | a raw byte; a string with such an escape and no multibyte characters is a unibyte string |
Other backslashes are kept as the following character: in a string, \( is just ( (so a regular expression must write "\\(", a backslash escaped by a backslash). Viewer: a string is String colour; the escapes with a meaning are Directive; a string that is passed as a regular expression is Regex colour, and a documentation string is Comment colour (see the overview).
A string may carry text properties and then is written #("text" 0 4 (face bold)): after the text come triples of start, end and a property list.
Lists, vectors and quote
(a b c)is a list of three;(a . b)is one cons cell withbin the cdr, and(a b . c)is a cons whose cdr is(b . c). A dot is a separator only when it is followed by white space, a delimiter or?;.5anda.bare not dots. Only one object may follow the dot.[a b c]is a vector. Its elements are not evaluated:[(+ 1 2)]is a vector holding a list.'xis the list(quote x).#'xis(function x).`xis(\` x),,xis(\, x)and,@xis(\,@ x); the backquote macro gives them meaning (Macros).
Viewer: the prefix characters ' ` , ,@ #' are Directive colour. A list that follows ' or a backquote is data: its first name is not coloured as a call, and a name after a comma is code again.
The # forms
A # at the start of a token selects a special syntax. An unknown character after # is an invalid-read-syntax error.
| Form | Reads as |
|---|---|
#'f | (function f) |
## | the interned symbol with an empty name |
#:name, #_name | an uninterned symbol; a symbol without shorthand expansion |
#xN #oN #bN #NrN | radix integers (see Numbers) |
#N= and #N# | labels for circular and shared structure: #1=(a . #1#) is a list whose cdr is itself. They are read only when read-circle is non-nil (the default) |
#("text" start end plist …) | a string with text properties |
#s(hash-table …) | a hash table: after the type come keyword/value pairs such as size, test, weakness and data (k1 v1 k2 v2) |
#s(type slot …) | a record: the first element is the type, the rest are the slots |
#[args code constants depth …] | a function object: a byte-code function in a compiled file, or an interpreted function in Emacs 30 and later (Byte-compilation) |
#&N"…" | a bool-vector of N bits stored in the bytes of the string that follows |
#^[…] #^^[…] | a char-table, a sub-char-table (printed by Emacs; not meant to be written by hand) |
#$ | the name of the file being loaded, in compiled files that use dynamic documentation |
#@N | skip N characters (see Comments) |
#! | skip the line |
#<buffer foo> | printed form of an object that has no read syntax (a buffer, a marker, a process); reading it signals an error |
Viewer: the # prefixes and the length of #&N are Directive; radix numbers Number; ## and #:name Literal; #! and #@N with the skipped text are Comment; the type name after #s( is Type.
Reading from Lisp
(read STREAM) reads one object from a buffer, a marker, a string, a function or the minibuffer; (read-from-string STRING &optional START END) returns the object and the index where it stopped. (car (read-from-string "(a . b)")) is (a . b). read-circle controls the #N= labels; read-symbol-shorthands the shorthands; obarray is where interned symbols are looked up. The printer’s counterparts are prin1, print-circle and print-escape-newlines. A file is read this way, form by form, by load, and each form is evaluated before the next is read (Evaluation), so a form can change how the rest of the file reads.
Not described
Known, not yet covered
- Reference: the errors the reader gives for each malformed form (the
invalid-read-syntaxmessages) are not listed; they are inlread.c. - Reference: the read syntax of char-tables, sub-char-tables and the full set of
#s(hash-table …)keywords is only named; the printer writes them and they are not written by hand. - Viewer: a symbol that is spelt with
\escapes is coloured by its source text, not by the name it reads as; a shorthand is not expanded before its name is looked up. - Viewer:
#N=and#N#are coloured as prefixes; the viewer does not follow the label.
See also
- Data types – what each of these forms reads as
- Strings and characters – functions on strings and characters, and
format - Printed Representation and Read Syntax – the manual’s chapter on read syntax