From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-0.9 required=5.0 tests=BAYES_00,FORGED_GMAIL_RCVD, FREEMAIL_FROM autolearn=no autolearn_force=no version=3.4.4 X-Google-Thread: 103376,50e705cdf2767cc6 X-Google-NewGroupId: yes X-Google-Attributes: gida07f3367d7,domainid0,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news1.google.com!news3.google.com!feeder.news-service.com!85.214.198.2.MISMATCH!eternal-september.org!feeder.eternal-september.org!.POSTED!not-for-mail From: Natasha Kerensikova Newsgroups: comp.lang.ada Subject: Re: Parser interface design Date: Thu, 7 Apr 2011 19:44:22 +0000 (UTC) Organization: A noiseless patient Spider Message-ID: References: <4d9c8c19$0$6769$9b4e6d93@newsspool3.arcor-online.net> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Injection-Date: Thu, 7 Apr 2011 19:44:22 +0000 (UTC) Injection-Info: mx03.eternal-september.org; posting-host="Mda950WjNwNLAFOE7yJXQw"; logging-data="14404"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+02I2IeDzW0briEqVyavlH" User-Agent: slrn/0.9.9p1 (FreeBSD) Cancel-Lock: sha1:LCMszr0rbQAp33+AQ9qwufnMad8= Xref: g2news1.google.com comp.lang.ada:18710 Date: 2011-04-07T19:44:22+00:00 List-Id: Hello, On 2011-04-06, Georg Bauhaus 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