Xah:
The printing is easy:
(de print-with-brackets (x)
(cond ((atom? x) (display " ") (display x))
(else (print-with-brackets (car x))
(display " [")
(for-each (lambda (i) (print-with-brackets i)) (cdr x))
(display " ]"))))
To parse such bracketed expressions, it's most advisable to start out
with a simple BNF-Grammar, eg:
G ::= expr
expr ::= atom | call
call ::= expr "[" expr expr... "]"
from which a so called "recursive descent parser" programme follows
almost mechanically:
(de parse-with-brackets (x)
(de eof? () (null? x))
(de head () (or (eof?) (car x)))
(de next () (pop x))
(de syntax-error (where expected)
(error where
"~s expected, offending: `~s'"
expected
(head)))
(de expect (what? where expected)
(unless (what?) (syntax-error where "<expr>")))
(de args-begin? () (equal? '[ (head)))
(de args-end? () (equal? '] (head)))
(de atom-begin? ()
(and (not (eof?)) (not (args-begin?)) (not (args-end?))))
(de expr-begin? () (atom-begin?))
(de parse-atom () (prog1 (head) (next)))
(de parse-args ()
(let ((a '()))
(next)
(expect expr-begin? 'parse-args "<expr>")
(push a (parse-expr))
(while (expr-begin?) (push a (parse-expr)))
(expect args-end? 'parse-args "]")
(next)
(reverse a)))
(de parse-expr ()
(de p (h) (if (args-begin?) (p (cons h (parse-args))) h))
(p (parse-atom)))
(expect expr-begin? 'parse "<expr>")
(prog1 (parse-expr) (expect eof? 'parse "<eof>")))
Examples:
-> (parse-with-brackets '(f [ 1 19 ] [ f2 g [ h 2 [ 5 9 ] 3 ] ]))
((f 1 19) f2 (g h (2 5 9) 3))
-> (parse-with-brackets '(f [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ] [ 8 ]))
((((((((f 1) 2) 3) 4) 5) 6) 7) 8)
-> (print-with-brackets (parse-with-brackets '(1 [ 2 [ 3 4 ] 5 [ 6 7 ] ])))
1 [ 2 [ 3 4 ] 5 [ 6 7 ] ]
Took me about an hour. To insert the extra-spaces I'd actually prefer
to engage some external tool in a pre-pass ("sed" or sum such), instead
of messing around with the reader.
Hope this helps - Wolfgang.
--
"Xah" <ยทยทยท@best.com> wrote:
> This question is similar to the "parsing html" thread, except that I'm new
> in both Scheme and Perl, but the problem seems much simpler.
>
> -------
>
> Is it feasible to use Perl to parse Lisp expression?
>
> For simplicity, let's say all atoms are just alphanumerics. Here is a sample
> expression,
>
> ((f 1 19) f2 (g h (2 5 9) 3))
>
> I want to bring out any of such expression's head outside the parenthesis
> and then change the paren to brackets, e.g. (f 1 2 3) becomes f[1 2 3]. The
> above sample becomes
>
> f[1 19][f2 g[h 2[5 9] 3]]
>
> and I also want to do the reverse operation. I'm wondering if it's feasible,
> say, by a Perl guru in a week? If not, is there in general a tool which I
> can do this?
>
> I don't know any parser or compiler theory. Is it possible for me to learn
> something like lex/yacc to be able to do what I want? All I need is to
> transform the *string*. For the curious, I am doing this to explore tree
> forms between Scheme and Mathematica.
>
> Thanks in advance for any help.