Reader
GOOS and GOAL both use the same reader, which converts text files to S-Expressions and allows these s-expressions to be mapped back to a line in a source file for error messages. This document explains the syntax of the reader. Note that these rules do not explain the syntax of the language (for instance, GOAL has a much more complicated system of integers and many more restrictions), but rather the rules of how your program source must look.
Integer Input
Integers handled by the reader are 64-bits. Any overflow is considered an error. An integer can be specified as a decimal, like 0
or -12345
; in hex, like #xbeef
; or in binary, like #b101001
. All three representations can be used anywhere an integer is used. Hex numbers do not care about the case of the characters. Decimal numbers are signed, and wrapping from a large positive number to a negative number will generate an error. The valid input range for decimals is INT64_MIN
to INT64_MAX
. Hex and binary are unsigned and do not support negative signs, but allow large positive numbers to wrap to negative. Their input range is 0
to UINT64_MAX
. For example, -1
can be entered as -1
or #xffffffffffffffff
, but not as UINT64_MAX
in decimal.
Floating Point Input
Floating point values handled by the reader are implemented with double
. Weird numbers (denormals, NaN, infinity) are invalid and not handled by the reader directly. A number must have a decimal point to be interpreted as floating point. Otherwise, it will be an integer. Leading/trailing zeros are optional.
Character Input
Characters are used to represent characters that are part of text. The character c
is represented by #\c
. This representation is used for all ASCII characters between !
and ~
. There are three special characters which have a non-standard representation:
- Space :
#\\s
- New Line:
#\\n
- Tab:
#\\t
All other characters are invalid.
Strings
A string is a sequence of characters, surrounding by double quotes. The ASCII characters from
to ~
excluding "
can be entered directly. Strings have the following escape codes:
\\
: insert a backslash\n
: insert a new line\t
: insert a tab\"
: insert a double quote
Comments
The reader supports line comments with ;
and multi-line comments with #| |#
. For example
(print "hi") ; prints hi
#|
this is a multi-line comment!
(print "hi") <- this is commented out.
|#
Array
The reader supports arrays with the following syntax:
; array of 1, 2, 3, 4
#(1 2 3 4)
Arrays can be nested with lists, pairs, and other arrays.
Pair
The reader supports pairs with the following syntax:
; pair of a, b
(a . b)
Pairs can be nested with lists, pairs, and arrays.
List
The reader supports lists. Lists are just an easier way of constructing a linked list of pairs, terminated with the empty list. The empty list is a special list written like ()
.
; list of 1, 2, 3
(1 2 3)
; actually the same as
(1 . (2 . (3 . ())))
Symbol
A symbol is a sequence of characters containing no whitespace, and not matching any other data type. (Note: this is not a very good definition). Typically symbols are lower case, and words are separated by a -
. Examples:
this-is-a-symbol
; you can have weird symbols too:
#f
#t
-
*
+
__WEIRDLY-NamedSymbol ; this is weird, but OK.
Reader Macros
The reader has some default macros which are common in Scheme/LISP:
'x
will be replaced with(quote x)
`x
will be replaced with(quasiquote x)
,x
will be replaced with(unquote x)
,@
will be replaced with(unquote-splicing x)