Notice that every (nested expression) must start with a rune, and expressions may be juxtaposed:
(+ 3)(+ 4 5)
print(* 4 5)
The advantage is that this structure can be unambiguously encoded to text in a large variety of different ways. There are five different layouts, and they can be mixed freely.
Nested Layout:
(= x 3)(| print)(| concat msg (| show (* x x)))
Open Layout (indentation sensitive):
= x 3
| print
| concat msg
| show
* x x
= x 3
| print
| concat msg | show * x x
Infix Layout:
(x = 3)(| print)(concat | msg | (show | (x * x)))
Closed Layouts: (nested and |prefix)
(x=3)(print|(concat|msg)(show|(x*x)))
Or any combination:
= x 3
| print
| concat msg (| show x*x)
There is also some syntactic sugar.
(no-rune nested expressions) default to | rune.
= x 3
| print
(concat msg (show x*x))
You can write multiple runes within a () form (which work the same was as open-form:
(x=3)(|print)(| concat msg | show x*x)
All of these different forms parse into the exact same R-expression structure.
This gives a much more expressive syntax, but still gives you all of the advantages of s-expressions:
Very simple parser and printer.
Generic parser and pretty-printer that can be shared between languages.
Enables traditional Lisp meta-programming (defmacro + syntax-rules).
namechar = [a-zA-Z_]
runechar = [$!#%&*+,-./:<=>?@\\^`|~]
/"""(.*)/ -> P # Page
/'''(.*)/ -> P # Page
/;(.*)/ -> C # Comment
/(namechar+)/ -> N # Name
/(runechar+)/ -> R # Rune
/( +)/ -> S # Whitespace
/'([^']*)'/ -> T # Text
/"([^"]*)"/ -> T # Text
leaf = P | T | N
shut = (nest | leaf)+
shin = shut (R shut)*
form = R shin | shin
frag = R shin | R | shin
# In infix mode, always occurs after `form`.
plix = ')'
| R S form plix
| S ')'
| S R S form plix
| S form plix
# In prefix mode, always occurs after `R` or `form`.
pree = ')'
| S ')'
| S R pree
| S form pree
# Body of parenthesis, decides if infix or prefix
prest = ')'
| form plix
| R pree
# Body of [bracket expression]
broke = ']'
| S ']'
| S frag broke
# Body of {curly expression}
carl = '}'
| S '}'
| S frag carl
# [Any] (nested) {expression}
nest = '(' prest
| '(' S prest
| '[' broke
| '[' frag broke
| '{' carl
| '{' frag carl
# Open space (can include line-comment)
open = C
| S C
| S
loan = EOF
| open EOF
| open frag loan
lean = EOF
| frag loan
line = open lean
| lean