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.
By 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.
This also applies to accented/national characters, as
the Pilot ROM routines converts these characters correctly.
LispMe supports integer, real and complex numbers.
During scanning, the conversion from small integers to big integers
to reals is automatical.
LispMe supports integers with radix specifications, where #b
means binary, #o octal, #d decimal, and #x
hexadecimal. LispMe accepts real
numbers according to this grammar:
real ::= [sign] ureal.
ureal ::= mantissa [exponent]
| radix r-digit+.
sign ::= '+' | '-'.
mantissa ::= digit+ ['.' digit*]
| '.' digit+.
exponent ::= ('e' | 'E') ['+' | '-'] digit+.
radix ::= '#b' | '#B' | '#o' | '#O' | '#d' | '#D' | '#x' | '#X'.
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-unit
| real i-unit
| sign i-unit
| real '@' real.
i-unit ::= 'i' | 'I'.
The @-syntax denotes complex numbers in polar form,
left to the @ is the magnitude, right is the angle.
In LispMe all integer numbers are considered exact?, real
and complex numbers are considered inexact?.
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.
In LispMe even string constants are mutable, so expressions like
(string-set! "foo" 0 #\b) (evaluating to "boo")
are allowed.
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.
Reserved keywords
The following keywords can't be used as variable names. You'll get this
error message if you try so.