chicken-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Chicken-users] Mutual recursion w/ comparse


From: Matt Gushee
Subject: [Chicken-users] Mutual recursion w/ comparse
Date: Wed, 27 May 2015 18:30:41 -0600

Hello--

I'm trying to write my first real parser with comparse, but I'm running into some difficulty with mutual recursion. Here's the problematic portion of my code:

    (define-values (dict dict-content dict-entry dict-value)
      (let ()
        (define dict~
          (enclosed-by (is #\{) dict-content~ (is #\})))
        (define dict-content~
          (sequence (maybe whitespace)
                    (maybe (sequence dict-entry~
                                     (zero-or-more (sequence separator
                                                             dict-entry~))))
                    (maybe whitespace)))
        (define dict-entry~
          (sequence dict-key
                    (maybe whitespace)
                    (is #\:)
                    (maybe whitespace)
                    dict-value~))
        (define dict-value~
          (any-of integer float number boolean string~ list~ dict~))
        (values dict~ dict-content~ dict-entry~ dict-value~)))

But when I try to use these parsers, e.g.

     (with-input-from-file "examples/basic.rsc"
         (lambda ()
              (let-values (((result rest)
                  (parse dict-content (read-all (current-input-port))))))))

I get this error:

Error: call of non-procedure: #<unspecified>

    Call history:

    rascl-parser.scm:166: comparse#sequence     
    rascl-parser.scm:166: comparse#zero-or-more     
    rascl-parser.scm:165: comparse#sequence     
    rascl-parser.scm:165: comparse#maybe     
    rascl-parser.scm:168: comparse#maybe     
    rascl-parser.scm:164: comparse#sequence     
    rascl-parser.scm:171: comparse#maybe     
    rascl-parser.scm:172: comparse#is     
    rascl-parser.scm:173: comparse#maybe     
    rascl-parser.scm:170: comparse#sequence     
    rascl-parser.scm:176: comparse#any-of     
    rascl-parser.scm:177: values     
    parse-basic.scm:13: with-input-from-file     
    parse-basic.scm:14: ##sys#call-with-values     
    parse-basic.scm:16: read-all     
    parse-basic.scm:16: comparse#parse         

I'm pretty sure the cause is not any of the individual parsers, but rather the way I'm trying to implement mutual recursion. I tried a version with

        (define dict-value
          (any-of integer float number boolean string~ list~))

i.e., non-recursive, with all parsers defined with a simple sequence of top-level (define)s, and it worked fine.

However, the actual grammar I'm trying to parse is similar, but not identical, to JSON, and calls for nested dictionaries. I looked at the medea source code and tried the approach used there (or as close as I could come), and several other variations, but I always get the same error, or else this one:

    Error: bad argument count - received 1 but expected 0: #<procedure (rascl-parser#dict-content)>.

Obviously I'm doing something wrong, but I can't see what.

BTW, I have a closely related but more general question:

At first I tried to use top-level defines for all the parsers, and that didn't work at all. I was surprised because I have used mutually recursive procedures many times. But I think I understand now. I think it's because in

    (define (NAME ARG ...)  BODY ...)

the BODY expressions are evaluated at runtime, while in

    (define NAME BODY ...)

[which is the form typically used to define comparse parsers], the BODY expressions are evaluated at compile time; thus any symbols referenced in BODY must be previously (in lexical order) defined. Have I got that right?

Thanks for any help.

--
Matt Gushee

reply via email to

[Prev in Thread] Current Thread [Next in Thread]