caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Markus Mottl <mottl@miss.wu-wien.ac.at>
To: skaller@maxtal.com.au (skaller)
Cc: caml-list@inria.fr (OCAML)
Subject: Re: ocamlyacc/lex reentrancy
Date: Mon, 3 Jan 2000 10:46:34 +0100 (MET)	[thread overview]
Message-ID: <200001030946.KAA03180@miss.wu-wien.ac.at> (raw)
In-Reply-To: <386BADF3.80F07395@maxtal.com.au> from "skaller" at Dec 31, 99 06:09:39 am

> > And, when invoking a lexer function or entry point,  you need to pass the
> > additionnal argument, a in
> >   somerule lexbuf lexdata

There is another way to get a similar behaviour with some syntactic sugar.
Use the following implementation of a "flow" (hm, just invented this name),
which is actually just a queue with some additional operators:

---------------------------------------------------------------------------
type 'a flow = Nil | Cons of 'a * 'a flow ref

type 'a t = { mutable head: 'a flow; mutable tail: 'a flow }

let create () = { head = Nil; tail = Nil }

let add fl x = match fl.tail with
  | Nil -> let c = Cons (x, ref Nil) in fl.head <- c; fl.tail <- c
  | Cons (_, last_ref) -> let c = Cons (x, ref Nil) in
                          last_ref := c; fl.tail <- c

let append fl1 fl2 = match fl1.tail with
  | Nil -> fl1.head <- fl2.head; fl1.tail <- fl2.tail
  | Cons (_, last_ref) -> last_ref := fl2.head; fl1.tail <- fl2.tail

let rec iter_aux f = function Nil -> () | Cons (x, t) -> f x; iter_aux f !t
let iter f q = iter_aux f q.head

let (%) fl el = add fl el; fl
let (!%) el = create () % el
let (%@) fl1 fl2 = append fl1 fl2; fl1
---------------------------------------------------------------------------

I use this in ocamlyacc files as follows:

---------------------------------------------------------------------------
%{ open Semantics.Impl
   open Flow
%}

... some tokens ...

%start main
%type <Semantics.Impl.cmd Flow.t> main

%%

actions_or_paths
  : action_or_path                          { $1 }
  | actions_or_paths useless action_or_path { $1 %@ $3 }

action_or_path : path { $1 } | action { !% $1 }

action
  : POP_PATH         { pop_dir }
  | EMPTY_PATH_STACK { clear_dir_stack }
  | AT ID            { dir_stack_at $2 }

path : op_rel_path { $1 % push_dir } | cl_rel_path { $1 % top_dir }

op_rel_path
  : cl_rel_path SLASH       { $1 }
  | op_el                   { !% (cd $1) }
  | cl_rel_path SLASH op_el { $1 % (cd $3) }

cl_rel_path
  : cl_el                    { !% (cd $1) }
  | set_el                   { !% (dir_set $1) }
  | cl_rel_path SLASH cl_el  { $1 % (cd $3) }
  | cl_rel_path SLASH set_el { $1 % (dir_set $3) }

---------------------------------------------------------------------------

This should lead to very compact and readable specifications. The result of
parsing is a "flow" (queue) of commands (functions) that transform state.
See below for an interface of Semantics.Impl:

---------------------------------------------------------------------------
...
  type state
  type cmd = state -> state
  
  val fresh : state
  val cd : Dir.Spec.el -> cmd
  val cd_root : cmd
  val cd_up : cmd
  val apply_flow : cmd Flow.t -> cmd
...
---------------------------------------------------------------------------

"apply_flow parse_result fresh" will apply all the state transformations of
the "flow" to a "fresh" state. Here the implementation of this function:

  let apply_stream strm s =
    let s' = ref s in Flow.iter (fun f -> s' := f !s') strm; !s'

Maybe someone else will also find it useful.

Regards,
Markus Mottl

-- 
Markus Mottl, mottl@miss.wu-wien.ac.at, http://miss.wu-wien.ac.at/~mottl




      reply	other threads:[~2000-01-03 16:47 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1999-12-24 21:31 skaller
1999-12-30 18:30 ` Francois Rouaix
1999-12-30 19:09   ` skaller
2000-01-03  9:46     ` Markus Mottl [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200001030946.KAA03180@miss.wu-wien.ac.at \
    --to=mottl@miss.wu-wien.ac.at \
    --cc=caml-list@inria.fr \
    --cc=skaller@maxtal.com.au \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).