POV-Ray : Newsgroups : povray.programming : Why not generate parser with Bison & Flex? : Re: Why not generate parser with Bison & Flex? Server Time
29 Jul 2024 08:16:32 EDT (-0400)
  Re: Why not generate parser with Bison & Flex?  
From: Alexander Enzmann
Date: 5 Jan 1999 08:10:58
Message: <01be38ac$233a3460$89d45381@aenzmann.mitre.org>
Ronald L. Parker <par### [at] mailfwicom> wrote in article
<36916860.164025814@news.povray.org>...
> On Mon, 04 Jan 1999 22:54:42 +0100, "Thorsten Froehlich"
> <fro### [at] charliecnsiitedu> wrote:
> 
> >Yes, you are right that the parsing part does not build anything, but
please pay
> >attention to this little detail:
> >Look at the lines you did not mark, what do they do?  They reduce the
memory usage!
> ...
> >All these lines of code would have to be written inside the grammar
file, wouldn't
> >they? And this would make the grammar file a total nightmare!!!  Or how
would you
> >solve this problem, maybe I am totally wrong!?!
> 
> You just call a function that contains the elided bits of code using
> the parameters you've parsed out.  It still happens at parse time. 
> I'm not too quick on the Bison grammar specification language myself,
> but I believe you would just pass the parsed vector into the
> "do_scale" function, defined somewhere else, and be on your way.  Yes,
> you might have to store the vector somewhere temporarily, but you will
> only need to store one such vector for a scale command, and it can
> even be in a global variable.


PMJI, but having programmed on POV-Ray, as well as building a renderer
using LEX/YACC for the grammar, I believe that using Flex/Bison for parsing
POV-Ray would be quite a reasonable thing to do.

The assertion that the stack gets too deep as a result of object modifiers
like scale is pretty easily dealt with.  Below is a sample of how I handled
object definition/modification in Polyray.  [Note that ACTION() is a C
#define that checks to see if we are actually creating geometry, or if we
are just reading the file - it was a useful way to put "if () else ..."
type statements into the language.]

In general you only need a line or two of C/C++ for each rule.  Typically
this code calls support routines.

Note that building from within an IDE is also quite easy - for example
Visual C++ allows quite flexible pre and post build steps, as well as the
typical ability to manage dependencies.

The big advantage of biting the bullet and using LEX/YACC is that it forces
you to develop a regular gammar.  OTOH, a recursive descent parser (like
POV-Ray uses) is a really easy thing to write and manage.  I'm not sure
there's a compelling reason for the POV-Ray team to change.

Sample LEX/YACC code for parsing an object & it's modifiers:

object
   : OBJECT '{'
      { ACTION(Object_Stack = push_object(Object_Stack, object_action1());)
}
     object_decls '}'
      { ACTION($<obj>$ = pop_object(&Object_Stack);) }
   | OBJECT_SYM
      { ACTION($<obj>$ = object_action2($<name>1);) }
   | OBJECT_SYM '{'
      { ACTION(Object_Stack =
               push_object(Object_Stack, object_action2($<name>1));) }
     object_modifier_decls '}'
      { ACTION($<obj>$ = pop_object(&Object_Stack);) }
   ;

object_modifier_decls
   : object_modifier_decl
   | object_modifier_decls object_modifier_decl
   ;

object_modifier_decl
   : texture
      { ACTION(if (Object_Stack->element->o_texture != NULL)
                        TextureDelete(Object_Stack->element->o_texture);
                     Object_Stack->element->o_texture = $<text>1;) }
   | transform
      { ACTION(TransformObject(Object_Stack->element, $<trns>1);
               polyray_free($<trns>1);) }
   | ROTATE point
      { ACTION(RotateObject(Object_Stack->element, $<vec>2);) }
   | ROTATE point ',' fexper
      { ACTION(RotateAxisObject(Object_Stack->element, $<vec>2, $<flt>4);)
}
   | SHEAR fexper ',' fexper ',' fexper ',' fexper ','
           fexper ',' fexper
      { ACTION(ShearObject(Object_Stack->element, $<flt>2, $<flt>4,
                           $<flt>6, $<flt>8, $<flt>10, $<flt>12);) }
   | TRANSLATE point
      { ACTION(TranslateObject(Object_Stack->element, $<vec>2);) }
   | SCALE point
      { ACTION(ScaleObject(Object_Stack->element, $<vec>2);) }
   | uv_information
   | SHADING_FLAGS fexper
      { ACTION(Object_Stack->element->o_sflag = (int)$<flt>2;) }
   | DITHER fexper
      { ACTION(Object_Stack->element->o_dither = $<flt>2;) }
   | BOUNDING_BOX point ',' point
     { ACTION(VecCopy($<vec>2, Object_Stack->element->o_bnd.lower_left);
              VecCopy($<vec>4, Object_Stack->element->o_bnd.lengths);
              VecSub(Object_Stack->element->o_bnd.lengths,
                     Object_Stack->element->o_bnd.lower_left,
                     Object_Stack->element->o_bnd.lengths);) }
   | root_solver
   | DISPLACE expression
      { ACTION(Object_Stack->element->o_displace = $<exper>2;) }
   ;


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.