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