Back to index
LispMe syntax
Syntactic elements
Identifiers (atoms) are similar to identifiers in other programming languages,
but they may consist of a larger set of characters. Allowed characters
are:
- upper case characters A B C D E F G H I J K L M N O P Q R S T
U V W X Y Z
- lower case characters a b c d e f g h i j k l m n o p q r s t
u v w x y z
- digits 0 1 2 3 4 5 6 7 8 9
- ASCII punctuation characters ! $ % & * + - / : < = > ? ^ _ ~
- all non-ASCII Pilot characters with the exception of
numericSpaceChr (##80 on PalmOS 3.2 and lower,
##19 on PalmOS3.3) and ##a0 (nonBreakSpaceChr), which
are treated as white space.
A symbol can consist of upto 256 characters from the above set with the
exception that tokens starting with a digit or + or -
followed by a digit are interpreted as numbers.
Using the option Case-sensitive symbols
you can determine, if symbols are case-insensitive or not.
Case-insensitive symbols are generally converted to lower case.
Unfortunately this doesn't apply to accented/national characters, as
the Pilot ROM routines don't convert these characters.
LispMe supports integer, real and complex numbers.
Any number entered which is too large to represented as a 15 bit
signed integer
(-16384 to 16383), is automatically converted to floating point.
LispMe supports inputting decimal numbers only. It accepts real
numbers according to this grammar:
real ::= [sign] ureal.
ureal ::= mantissa [exponent].
sign ::= '+' | '-'.
mantissa ::= digit+ ['.' digit*]
| '.' digit+.
exponent ::= ('e' | 'E') ['+' | '-'] digit+.
Real numbers are represented in IEEE-754 64 bit double
precision format, which means about 15 decimal digits accuracy.
Complex numbers can be written according to this grammar:
complex ::= real
| real sign ureal 'i'
| real 'i'
| sign 'i'
| real '@' real.
The @-syntax denotes complex numbers in polar form,
left to the @ is the magnitude, right is the angle.
LispMe does not support the exactness property required by
R4RS, nor does it support big integers or rationals.
Characters
Character objects are denoted by prefixing the character with
#\. LispMe doesn't know special character names
like #\space and #\newline, but you can create
those values with the
integer->char
function or use the hex syntax, which is an extension to
R4RS: Two hash chars ## followed by two
hexadecimal digits (0-9, a-f) denote a character whose code is
the value of the two hex digits given.
Examples
#\ü denotes the lower case german
character ü (u umlaut)
##0a denotes the carriage return/linefeed char
on the pilot
Strings
Strings are sequences of characters enclosed within double quotation
marks ". Any character from the Pilot char set can be written
in a string with three exceptions:
- " the double quotation would terminate the string
- \ the backslash introduces an escape sequence
- # the hash sign introduces a hexadecimal character
These characters in a string must be preceeded by a backslash \.
The # syntax is a LispMe extension,
which allows an arbitrary
character to be included in a string. After the # exactly
two hexadecimal digits (0-9, a-f) are expected, which denote the
character to be included.
In contrast to C or C++, you can have #00 bytes
in a string.
Example
"a\\#0aa\#" denotes a string consisting of
letter a, backslash, linefeed (hex 0a), letter a, hash sign.
Other literals
There're 3 special literals all beginning with a hash sign #
- #f denotes
the boolean value false.
- #t denotes
the boolean value true.
- #n denotes
a value which doesn't print.
Pairs and lists
A pair (or dotted pair) is a data structure consisting of two
components, called the car and the cdr. A pair
consisting of the car component a and the
cdr component b is written
(a . b). If one of the components is a number,
you should write a space character between the number and the dot to
avoid confusion with a decimal point.
LispMe's scanner munches as much input as possible when recognizing
tokens, so be picky with spaces, especially with dotted pairs/floating
point numbers. Notice the difference:
(a.1) is read as (a 0.1) (list)
(a. 1) is read as (a . 1) (dotted pair)
A list is either a special value () called the empty list, or
a pair, whose cdr component is a list, for example
(1 . (2 . (3 . ()))) There's also a shorter syntax for lists
which omits both the dot and the parentheses around the cdr
component, so this example can also be written (1 2 3). Lists
of these form (the last cdr is the empty list) are called
proper lists. Improper lists don't have the empty list as their last
cdr, like (1 . (2 . (3 . 4))), which can be written
as (1 2 3 . 4), too. It's an
error to write more than one
dot in a list.
Vectors
Vectors are sequences of arbitrary objects, which can be accessed by
an integer index in constant time. Vector constants are written like
lists, but they start with #( and are terminated by ).
In contrast to lists, there are no "dotted" vectors. In contrast to
R4RS, vector constants need not to be quoted in LispMe.
A semicolon ; starts a comment. All characters following it
upto the end of the current line are ignored. Note that there must
be a hard line feed (Graffiti stroke downward slash), word
wrapping to the next line is not considered a line feed.
The LispMe Reader
Anything after a complete expression is ignored by the reader and any
incomplete expression is automatically completed with closing parentheses.
So
(+ 3 (* 7 4)) (foo bar) quux
and
(+ 3 (* 7 4
both read as (+ 3 (* 7 4)) and evaluate to 31.
When loading memos, (begin is stuffed into the read buffer before
the actual memo contents is read, so a source memo must be a sequence of
define expressions not
enclosed in parentheses. Instead, the outermost list is automatically
completed by the loading mechanism.
LispMe expressions (programs, see here)
are in fact nested lists and may be viewed as data, too, but not all
nested lists are valid programs. LispMe programs must follow this grammar:
expression ::= literal
| identifier
| special_form
| application
| (quasiquote qq-template)
| `qq-template
literal ::= number
| character
| string
| #f | #t | #n | '()
| #( object* )
| (quote object)
| 'object
special_form ::= (keyword component*)
application ::= (expression+)
qq-template ::= object including unquote and
unquote-splicing special forms
object means the written representation of any LispMe object
and component is a syntactic component different for
(and described at) each keyword in the LispMe catalog.
This grammar is ambiguous due to special forms, but this ambiguity is
resolved by reserving names used as keywords in special forms. A
qq-template may be any LispMe object but is most commonly
a list or vector, which may contain
unquote and
unquote-splicing
special forms.
Symbols
Symbols are printed in lower-case. There's no escape mechanism for
funny characters in symbols, as these cannot be input or generated.
Numbers
Numbers are printed in decimal without leading zeros. If floating
point numbers don't have decimal places, the decimal point is
omitted, too. At most 15 decimal places are printed where the last
decimal digit may not be rounded correctly. Exponential notation
is used for numbers larger than 1015 or smaller than
10-4. (similar to the C format string "%.15g")
Complex numbers always print in rectangular form, where the real and
imaginary part are both printed as described for real numbers.
The special real
values infinity, -infinity
and not-a-number print as [inf], [-inf]
and [nan]. A complex number having an infinite component
prints as [cinf] (complex infinity).
Characters
display and
write
print characters differently. write prefixes a character
with #\ or uses ## for characters with ASCII codes
<32 and display just prints the character itself.
Strings
display and
write
print strings differently. display just prints the contents
of the string without any escape chars and without double quotes.
write encloses the string in double quotes and escapes the
characters ", \ and # with a backslash
\ and writes all characters with ASCII codes <32 in
hex notation.
Pairs and lists
The dot notation is avoided whenever possible. To avoid stack overflow
in the printer, deeply nested lists (the limit in configurable in the
preferences dialog)
print as [deep]. Expressions which are to long for the
output are abbreviated with ... and a
warning is given.
By selecting the option Print quotes,
you can make LispMe print quote-expressions in the abbreviated
form.
Vectors
Vectors are printed using the standard syntax #( ... ). The
depth limit (like with lists) applies to vectors, too.
Closures
Closures print as [clos n], where n
indicates the number of arguments
- n>=0 means exactly n arguments
- n<0 means at least |n|-1 arguments
(= |n| arguments, the last one being the rest argument)
See lambda for more info.
Continuations
Continuations (see call/cc)
print as [cont].
Promises
Promises (see delay)
print as [prom].
Ports
Output ports print as [outport] and input ports as
[inport n], where n is the current
read position from the beginning of the memo. The special end-of-file
object (returned by read, for
example) prints as [eof].
Macros
Macros (see here)
print as [macro].
Summary of specially printed objects
[-inf] | negative infinity |
[cinf] | complex infinity |
[clos n] | closure |
[cont] | continuation |
[deep] | deeply nested list or vector |
[eof] | end-of-file object |
[inf] | positive infinity |
[inport n] | input port |
[macro] | macros |
[nan] | not a number |
[outport] | output port |
[prom] | promise |
#n | a symbol created by gensym |