Back to index

LispMe syntax

Syntactic elements

Identifiers

Identifiers (atoms) are similar to identifiers in other programming languages, but they may consist of a larger set of characters. Allowed characters are: 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.

Numbers

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: 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 #

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.

Comments

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.

Valid LispMe expressions

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.
and begin case cond define
delay else if lambda let
letrec or quasiquote quote set!
unquote unquote-splicing