S-expressions: Difference between revisions

→‎{{header|TXR}}: Added explicit parser.
(→‎{{header|TXR}}: Added explicit parser.)
Line 2,739:
However, note that the <code>@</code> character has a special meaning: <code>@#</code> turns into <code>(sys:var #)</code>. TXR's printer right now does not convert this back to <code>@</code> notation upon printing. (The purpose of this notation is to support Lisp code that requires meta-variables: variables distinguished from variables. For instance, logic pattern matching or unification code. Instead of hacks like name-based conventions (for instance <code>x?</code> is a meta-variable, <code>x</code> is ordinary), why not build it into the language: <code>@x</code> is a meta-var, identifiable by special abstract syntax, and <code>x</code> is just an atom, a symbol. There is also <code>@(foo ...)</code> which expands into <code>(sys:expr foo ...)</code>, doing a similar thing for expressions.
 
(TODO:The Afollowing solution will appear here soon which avoids "cheating" in this way with the built-in parser:; it implements a from-scratch S-exp parser which treats <code>!@#</code> as just a symbol. We can beat other languages with our built-in S-exp parser tied behind our back.)
 
The grammar is as follows:
 
<pre>
expr := ws? atom
| ws? ( ws? expr* ws? )
 
atom := float | int | sym | str
 
float := sign? digit+ . digit* exponent?
| sign? digit* . digit+ exponent?
| sign? digit+ exponent
 
int := sign? digit+
 
str := " (\" | anychar )* "
 
sym := sym-char +
 
sym-char := /* non-whitespace, but not ( and not ) */</pre>
 
Code:
 
<lang txr>@(define float (f))@\
@(local (tok))@\
@(cases)@\
@{tok /[+\-]?\d+\.\d*([Ee][+\-]?\d+)?/}@\
@(or)@\
@{tok /[+\-]?\d*\.\d+([Ee][+\-]?\d+)?/}@\
@(or)@\
@{tok /[+\-]?\d+[Ee][+\-]?\d+/}@\
@(end)@\
@(bind f @(flo-str tok))@\
@(end)
@(define int (i))@\
@(local (tok))@\
@{tok /[+\-]?\d+/}@\
@(bind i @(int-str tok))@\
@(end)
@(define sym (s))@\
@(local (tok))@\
@{tok /[^\s()]+/}@\
@(bind s @(intern tok))@\
@(end)
@(define str (s))@\
@(local (tok))@\
@{tok /"(\\"|[^"])*"/}@\
@(bind s @[tok 1..-1])@\
@(end)
@(define atom (a))@\
@(cases)@\
@(float a)@(or)@(int a)@(or)@(str a)@(or)@(sym a)@\
@(end)@\
@(end)
@(define expr (e))@\
@(cases)@\
@/\s*/@(atom e)@\
@(or)@\
@/\s*\(\s*/@(coll :vars (e))@(expr e)@/\s*/@(until))@(end))@\
@(end)@\
@(end)
@(freeform)
@(expr e)@junk
@(output)
expr: @(format nil "~s" e)
junk: @junk
@(end)</lang>
 
Run:
 
<pre>$ txr s-expressions.txr -
()
expr: nil
junk:
$ txr s-expressions.txr -
3e3
expr: 3000.0
junk:
$ txr s-expressions.txr -
+3
expr: 3
junk:
$ txr s-expressions.txr -
abc*
expr: abc*
junk:
$ txr s-expressions.txr -
abc*)
expr: abc*
junk: )
$ txr s-expressions.txr -
((data "quoted data" 123 4.5)
(data (!@# (4.5) "(more" "data)")))
expr: ((data "quoted data" 123 4.5) (data (!@# (4.5) "(more" "data)")))
junk:
</pre>
 
{{omit from|Brlcad}}
543

edits