A Parser for M-Expressions

Here is a parser for Lisp M-Expressions as documented in the Memo 8, AIM-8

A lot of lisp newbies ask for more conventionnal syntax for lisp. Since day one, lisp was intended to have such a syntax: M-expressions.

Let's newbies play with them, and realize how impractical they are. Note for example, that we cannot use macros anymore because their syntax would need to be known by the M-expression parser, like it's the case for lambda[[...];...]. Macros were added later in lisp history.

Note that S-expressions can still be entered, as literal objects, but using comma instead of space to separate the items in lists.

The file m-expression.lisp contains the M-expression parser and a REPL, in Common-Lisp.

Exemple

% /usr/local/bin/clisp -q -norc -ansi 

[1]> (load"m-expression.lisp" :external-format #+clisp charset:utf-8 #+sbcl :utf-8)
;; Loading file m-expression.lisp ...
;; Loaded file m-expression.lisp
T
[2]> (m-repl)

;; We are going to define a function that is exported by COMMON-LISP, 
;; so let's shadow it first:

COMMON-LISP-USER[1]M-REPL> shadow[SUBST];
 --> T

COMMON-LISP-USER[2]M-REPL> label[subst;λ[[x;y;s];[null[s]->nil;atom[s]⟶
           [y=s->x;1->s];1->combine[subst[x;y;first[s]];
                subst[x;y;rest[s]]]]]];
 --> SUBST

;; S-expressions embedded in M-expressions must use comma as separator:
COMMON-LISP-USER[3]M-REPL> subst[WATER;WINE;(MIX WATER AND WINE
                                  INTO (MIXED WATER AND WINE))];
SIMPLE-ERROR: 
Unexpected S-CLOSE, not (:S-SYMBOL WATER)
 at " AND WINE"

COMMON-LISP-USER[4]M-REPL> SIMPLE-ERROR: 
Please terminate your m-expressions with a semi-colon, not (:S-OPEN)

COMMON-LISP-USER[5]M-REPL> 
SIMPLE-ERROR: 
Please terminate your m-expressions with a semi-colon, not (:S-SYMBOL WATER)

COMMON-LISP-USER[6]M-REPL> 
SIMPLE-ERROR: 
Please terminate your m-expressions with a semi-colon, not (:S-SYMBOL WINE)

COMMON-LISP-USER[7]M-REPL> 
SIMPLE-ERROR: 
Unexpected token in m-term: (:S-CLOSE)
 at ")];"

COMMON-LISP-USER[8]M-REPL> subst[WATER;WINE;(MIX,WATER,AND,WINE,
                                 INTO,(MIXED,WATER,AND,WINE))];
 --> (MIX WATER AND WATER INTO (MIXED WATER AND WATER))

COMMON-LISP-USER[9]M-REPL> subst[WINE;WATER;(MIX,WATER,AND,WINE,
                                 INTO,(MIXED,WATER,AND,WINE))];
 --> (MIX WINE AND WINE INTO (MIXED WINE AND WINE))

COMMON-LISP-USER[10]M-REPL> first[((A,B),C,D)]=(A,B);

 --> NIL

COMMON-LISP-USER[11]M-REPL> combine[A;⋀];
 --> (A)

COMMON-LISP-USER[12]M-REPL> quit[];
NIL
[3]>