From: Wolfgang Hukriede
Subject: Re: parsing scheme expr
Date: 
Message-ID: <67evv9$4tr@gutemine.informatik.uni-kiel.de>
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.