comp.lang.ada
 help / color / mirror / Atom feed
From: Natasha Kerensikova <lithiumcat@gmail.com>
Subject: Parser interface design
Date: Wed, 6 Apr 2011 10:11:46 +0000 (UTC)
Date: 2011-04-06T10:11:46+00:00	[thread overview]
Message-ID: <slrnipof32.2fnq.lithiumcat@sigil.instinctive.eu> (raw)

Hello,

before wasting too much time of anybody, I want to make it clear that
I'm asking about interface design in Ada which might actually never turn
up into real code. I'm still unsure about ever writing Ada code, and how
bad my previous thread went playing no small part in that. However I'm
still curious about how this particular problem might be solved in Ada.

I wrote a while back a C library to parse Markdown text. I call "parser"
the code that takes a text assumed to be formatted in Markdown as input,
and communicates in a still-to-be-defined way with another component,
which I call "renderer", and which outputs the same text but using
another formatting, for example HTML or PDF.

The problem on which I want your opinion is designing the interface
between the parser and the renderer. The point is to be able to "plug"
may renderer into the parser, and thereby obtain a different kind of
output, with as little code rewrite as possible (hence the idea of
refactoring the "parser" into a re-usable part).

I can see three kinds of interfaces:
  * an "offline" interfacing, where the parser returns an in-memory
    abstract representation of the input, which is then processed by the
renderer to produce its output;
  * an "event-based" interfacing, which is basically an "online"
    renderer-driven interfacing: the parser is first fed the input text,
and then various functions allows to query its state, the current
"event" (an event being "that kind of element has been encountered", or
"the input file is over"), the event parameters, etc.
  * a "callback-based" interfacing, which is an "online" parser-driven
    interfacing, where the parser is provided both the input text and a
set of callback from the renderer.

I can see how to go forward up to a real implementation only for the
third kind, which what I will discuss below. While the different merits
(both intrinsic and with regard to implementing it in Ada) of these
kinds interests me, it's a secondary question compared to the following
one.

Assuming the third kind is chosen, the C interface (which I already
coded a while back) is easy to come up with: a bunch of function
pointers and a void pointer for renderer-defined state, put together in
a struct.

I guess the same thing can be done in Ada, except it would be called a
bunch of access to procedures in a record (and the renderer state has
to come from elsewhere). But is it the best way of doing it?

I thought the most idiomatic way of putting together a bunch of
callbacks in Ada would be to use an Interface, and then rely on dynamic
dispatch. This also provides a nice way to embed the renderer state, in
the tagged type that implement the Interface.

Now when thinking a bit deeper about it, Ada interfaces seemed to have a
few drawbacks compared to the first C-ish record idea, as far as code
re-use goes. It felt like it boiled down to extension vs composition,
but I might be wrong on this and using terms I don't fully understand.

The C implementation I mentioned included a few example renderers, that
targets either HTML or XHTML, and that implement either vanilla
Markdown, or some Discount extensions on top of it, or some personal
extensions on previous Discount extensions.

This means a total of 6 example renderers. Some callbacks are the same
for all of them, some callbacks are specific to HTML or XHTML but used
for all extension sets, some callbacks are specific to an extension set
but independent of the output format, and a few callbacks are specific
to a combination of both target and extension set.

The C or Ada record approaches seem to handle it nicely by defining each
callback once, and then selecting them for each example renderers
depending on the chosen features.

The approach using tagged types implementing an interface seems heavier.
Part of the problem is single inheritance: one hierarchy has to be
chosen between HTML/XHTML or  extension sets, and the non-chosen feature
will be reconstructed independently for each instance of the chosen
feature. This sounds bad as far as code reuse goes, and heavy to write
and to maintain, at least compared to the simple record idea.

However I have the feeling that even with multiple inheritance the
tagged type approach doesn't fare much better, because I can only come
up with clumsy and heavy ways to specify from which parent each of the
callbacks comes (because that is what it boils down to).

I also though of implementing each callback once, as standalone
procedures, and then use tagged procedures to call them, but that seems
very messy too.

So what would be the best approach to interface a parser and a renderer?


Thanks in advance for your ideas,
Natasha



             reply	other threads:[~2011-04-06 10:11 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-04-06 10:11 Natasha Kerensikova [this message]
2011-04-06 12:17 ` Parser interface design Georg Bauhaus
2011-04-07 18:56   ` Natasha Kerensikova
2011-04-08 11:49     ` Stephen Leake
2011-04-06 12:20 ` Dmitry A. Kazakov
2011-04-07 19:14   ` Natasha Kerensikova
2011-04-07 20:31     ` Dmitry A. Kazakov
2011-04-08 13:51       ` Natasha Kerensikova
2011-04-08 14:21         ` Dmitry A. Kazakov
2011-04-12 15:58           ` Natasha Kerensikova
2011-04-12 17:14             ` Dmitry A. Kazakov
2011-04-06 15:51 ` Georg Bauhaus
2011-04-07 19:44   ` Natasha Kerensikova
2011-04-07 20:52     ` Dmitry A. Kazakov
2011-04-07 22:09     ` Simon Wright
2011-04-08 14:03       ` Natasha Kerensikova
2011-04-08 19:06         ` Jeffrey Carter
2011-04-08 19:59         ` Simon Wright
2011-04-12 16:13           ` Natasha Kerensikova
2011-04-12 17:22             ` Dmitry A. Kazakov
2011-04-12 19:02               ` Simon Wright
2011-04-13  8:20                 ` Natasha Kerensikova
2011-04-13  8:37                   ` Dmitry A. Kazakov
2011-04-13 11:06                     ` Georg Bauhaus
2011-04-13 12:46                       ` Dmitry A. Kazakov
2011-04-13 22:33                   ` Randy Brukardt
2011-04-14  6:55                     ` Natasha Kerensikova
2011-04-15  0:22                       ` Randy Brukardt
2011-04-12 21:54               ` Randy Brukardt
2011-04-07 22:13     ` Georg Bauhaus
2011-04-08 15:30       ` Natasha Kerensikova
2011-04-07  0:36 ` Randy Brukardt
2011-04-08 11:16 ` Brian Drummond
2011-04-19  9:08 ` Natasha Kerensikova
2011-04-19 12:35   ` Ludovic Brenta
2011-04-20 10:44     ` Brian Drummond
2011-04-19 17:28   ` Jeffrey Carter
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox