comp.lang.ada
 help / color / mirror / Atom feed
From: Natasha Kerensikova <lithiumcat@gmail.com>
Subject: Re: Parser interface design
Date: Thu, 7 Apr 2011 19:44:22 +0000 (UTC)
Date: 2011-04-07T19:44:22+00:00	[thread overview]
Message-ID: <slrnips50m.2fnq.lithiumcat@sigil.instinctive.eu> (raw)
In-Reply-To: 4d9c8c19$0$6769$9b4e6d93@newsspool3.arcor-online.net

Hello,

On 2011-04-06, Georg Bauhaus <rm.dash-bauhaus@futureapps.de> wrote:
> On 06.04.11 12:11, Natasha Kerensikova wrote:
>
>> 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.
>
> Can be done, and one example is given further below.
>
> Another way is to use "generic interfaces" for callback
> communication, a more traditional way I think. For example,

I have trouble abstracting concept out of your examples, so if you don't
mind I will provide my own, which I understand, and maybe we can work
out a common ground that I understand from there.

The direct transposition of my C implementation would be something like

   type Renderer_Callbacks is record
      Emphasis:    access function (Contents: String) return String;
      Normal_Text: access function (Contents: String) return String;
      Paragraph:   access function (Contents: String) return String;
   end record;

   function Parser (Renderer: Renderer_Callbacks; Input: String)
     return String;

(except with 19 callbacks instead of 3)

Now at least I understand the idea of using generics instead:

   generic
      with function Emphasis (Contents: String) return String is <>;
      with function Normal_Text (Contents: String) return String is <>;
      with function Paragraph (Contents: String) return String is <>;
   function Parser (Renderer: Renderer_Callbacks; Input: String)
     return String;

However I am a bit skeptical about whether or not generics is actually a
better approach than the record of accesses. Generics is certainly a
higher-level feature than record and access, but I don't think that's
enough to prefer one over the other. On the other hand, I understand the
criticism of generics posted here (with my apologies for not remember
who had which arguments), with all the problems caused by the function
not actually existing until it's instanced.

I believe such generics to be a lesser evil than generic types, and
similarly I believe access to subprograms to be lesser evils than access
to data. However I wouldn't be surprised if parser instantiation means
duplicating the code for each parser. Even if it's the compiler that
actually performs the code duplication, I'm not very at ease with it.

All in all, I can't find any argument in favor of replacing the record
of accesses with the generic approach.

> Anyway, here is another approach, probably not very original,
> certainly lacking proper modularization and other things
> that I did't see, sorry, but if offers another idea.  There aren't
> any generics in it.
>
> But there is a procedure
>
>     procedure Print (Item : Token'Class;
>                      Output : in out Format'Class);
>
> The idea is that given any token, Print renders the token
> Item into any format passed for Output.

I genuinely read several times your example, and I can't figure out what
thing performs what.

Here are things that I do understand: there is a parser, which reads the
input data, there a renderer, which outputs the formatted data, and
there is a client, which provides the input data and does something
useful with the formatted data. I don't really see where in that picture
that Print procedure can be found.

In the example above, thing are simple enough for me to understand: the
client hands over control to the parser, along with a reference to the
renderer and the input data. From there, the parser hands over control
to the renderer through callbacks for specific semantic units.

For example, imagine the input "foo *bar* baz". The parser would be
implemented so that the following callback sequence happens:

   part1 = Normal_Text("foo ");
   subpart2 = Normal_Text("bar");
   part2 = Emphasis(subpart2);
   part3 = Normal_Text(" bar");
   result = Paragraph(part1 & part2 & part3);

I mentioned in another post that I used NULL callbacks to turn off a
feature; using this example, if Emphasis is NULL, the star becomes an
inactive character, and the parser would trigger the following callback
sequence instead:

   part = Normal_Text("foo *bar* baz");
   result = Paragraph(part);

So this is the boxes I know of, and a design I'm familiar with.

Do you think you can base on that an explanation of your example that
that dumb C-brain-washed little me can understand?


Thanks in advance,
Natasha



  reply	other threads:[~2011-04-07 19:44 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-04-06 10:11 Parser interface design Natasha Kerensikova
2011-04-06 12:17 ` 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 [this message]
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