The thing that's appealing about s-expression languages is that code-as-data is easy to do because parse, creating and modifying code is dead-easy. Is there some still-very-easy algorithm for parsing things like infix operators or does code-as-data depend on using the facilities of the language.
Edit: I can see Julia does this by reflection and macros. But I'm still curious about the general issues and algorithms involved here.
You would be interested in the shunting-yard algorithm[1], to start with.
Rebol is very easy to parse. Here is a Rebol parser in 10 lines of Rebol:
parse text blk-rule: [
some [
str:
newline |
#";" [thru newline | to end] new: (probe copy/part str new) |
[#"[" | #"("] blk-rule |
[#"]" | #")"] break |
skip (set [value new] load/next str probe :value) :new
]
]
ref: http://www.rebol.net/cookbook/recipes/0042.htmlBut after mentally parsing that, it seems all this is doing separating blocks. What one would want to also do is to also scan operators, if one was evaluating code or transforming it into an abstract syntax tree.
Everything in Rebol is just blocks of words, where (in general) expressions are evaluated from left to right; however, within each expression evaluation occurs from right to left [1].
So (infix) operators are also just words and have no precedence order so they just evaluate left to right (like Smalltalk) when parsed [2]...
>> 1 + 2 * 3
== 9
To enforce any precedence you use paren! blocks [3], which are blocks that get evaluated immediately. >> 1 + (2 * 3)
== 7
refs:[1] http://www.rebol.com/r3/docs/guide/code-eval.html
[2] http://www.rebol.com/r3/docs/concepts/math-precedence.html
But more seriously, it seems like once one starts expanding the definition, homoiconicity gets to be in the eye of the beholder.
"In a homoiconic language the primary representation of programs is also a data structure in a primitive type of the language itself."
So you can take a monster language (at least any one with an eval command - Perl5 say), expand it's syntactical definition and get a "homoiconic language".
In my examples I think only Perl6 is stretching the definition of homoiconicity, NB. are Perl6 Grammars == data structure/primitive ??
However Rebol (blocks & words) & Io/Smalltalk (objects and messages) do fully meet the definition you give above for being an homoiconic language.