guile-devel
[Top][All Lists]
Advanced

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

Re: Defining Functions With Syntax


From: Andy Wingo
Subject: Re: Defining Functions With Syntax
Date: Wed, 21 Sep 2011 10:08:18 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/23.3 (gnu/linux)

Hi Noah,

On Tue 20 Sep 2011 21:00, Noah Lavine <address@hidden> writes:

> what if you build up a PEG grammar at runtime and want to parse
> something with it?

Broadly speaking, you either interpret it or you compile it.  You can do
either using the Scheme compiler, or you can write your own interpreter
or compiler.

First, using the Scheme compiler: being a macro, `define-nonterm'
extends the Scheme compiler with support for PEG grammers.  If you want
to compile at runtime you can call `compile' on your expression.  You
could also call `eval', to interpret at runtime.  I'm not sure which is
the right thing; `compile' will probably be quick (and certainly produce
faster code) but it loads up the compiler, which is a few megabytes of
code I think.

> The PEG documentation recommends doing '(eval `(define-nonterm as body
> ,exp) (interaction-environment))', where 'exp' is whatever your
> s-expression is. This seems like a bad idea to me, because a) it also
> defines a variable 'as', which is not needed and maybe not what you
> want and b) it seems unnecessarily complicated.

Regarding the first, you can `(let () (define-nonterm as body ,exp) as)'
or something, in which the `as' definition doesn't leak beyond that
inner lexical contour.

It is complicated though.  The other option is to write a PEG
interpreter or compiler in Scheme.  An interpreter would interpret the
s-expressions directly, or some simplified form of them.  A compiler
would pre-process the s-expressions to produce a procedure, built from
closures.

For example here is a simple matcher that matches pairs:

  (use-modules (system base pmatch))
  (define (make-pair-matcher pat)
    (pmatch pat
      ((head . tail)
       (let ((hmatch (make-pair-matcher head))
             (tmatch (make-pair-matcher tail)))
         (lambda (x)
           (and (pair? x) (hmatch (car x)) (tmatch (cdr x))))))
      (datum
       (lambda (x) (eq? x datum)))))

  ((make-pair-matcher '(foo . bar)) '(foo . bar))
  => #t

I say that this is "compiled" because the matcher code is wired together
from closures, whose code is compiled, and matching against a datum
doesn't dispatch against the pattern at runtime: that path is computed
(compiled) already by the `make-pair-matcher' procedure.

Does that help any?

Andy
-- 
http://wingolog.org/



reply via email to

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