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.
% /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]>