Notice that every (nested expression) must start with a rune, and expressions may be juxtaposed:
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:
Open Layout (indentation sensitive):
Infix Layout:
Closed Layouts: (nested and |prefix)
Or any combination:
There is also some syntactic sugar.
(no-rune nested expressions) default to | rune.
You can write multiple runes within a () form (which work the same was as open-form:
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