Short Programming Assignment #4

Additional Notes for the Parser

The parse tables are discussed in Unit 9 Notes, around page 16.

If you’re going to use the parser, each “thing” in our raytracer - - camera, material, plane, sphere, etc (anything with attributes) - - has a parse array associated with it. Each item in the array is a pparm_t (defined in ray.h). A pparm_t has 5 parts:

attrname: the attribute name - such as “pixeldim”

numvals: the number of values - such as 2 if it is pixeldim, or 3 if it is viewpoint, etc

valsize: the size of each value - sizeof(int) for pixeldim, or sizeof(double) for worlddim and viewpoint

fmtstr: the format of the value - such as “%d” or “%lf”

loc: and the starting location - which by default starts out as 0

The parse arrays are at the top of each .ccp file for those things that need it. The material parse array is at the top of material.cpp, which is given to you. The camera parse array is at the top of camera.cpp and looks like this:

pparm_t cam_parse[ ] =

{

{"pixeldim", 2, sizeof(int), "%d", 0},

{"worlddim", 2, sizeof(double), "%lf", 0},

{"viewpoint", 3, sizeof(double), "%lf", 0},

};

#define NUM_ATTRS (sizeof(cam_parse) / sizeof(pparm_t))

where the first one with each part identified:

{"pixeldim", 2, sizeof(int), "%d", 0}

attrname numvals valsize fmtstr loc

The #define NUM_ATTRS (sizeof(cam_parse) / sizeof(pparm_t)) line calculates the number of attributes by dividing the total size of the array by the size of each individual pparm_t which will give the number of pparm_t ‘s, i.e. the number of attributes.

If you don’t use the parser that is provided, then you will have to add the load attribute methods to the class definitions of camera, plane, sphere, etc. And, in the camera.cpp file, and plane.cpp file, and sphere.cpp file, etc, you’ll have to implement those functions also.

What’s cool is that you can use the same parser( ) function for any of the parse_arrays; so 1 parser (given to you) vs several load_attribute functions.


The parser.c file - - which is given to you (you don’t have to write it).

There are 3 functions:

1. parser( ) - - which calls

2. parser_load_attributes( ) - - which calls

3. getndxp( )

1. parser( ) algorithm:

fscans in the attrname (so “pixeldim” gets scanned in the first time)

while loop as long as there is an attrname and it’s not ‘}’

calls parser_load_attributes( ) function, which is what fscans in the next values for that attribute (the for loop) &

returns the ndx

adjust mask according to what the index is (I can explain this part in class, for now, just take it as given in parser.c)

if it’s not time to quit, fscanf the next attrname

return the mask to the constructor method, where it is checked with an assert statement

2. parser_load_attributes( ) algorithm:

calls getndxp( ) function which will return the index of that attribute name

(the parse table is sent in as one of the arguments, so it uses strcmp with attrname until it finds the one it’s looking

for, and returns the index)

initializes the * pce (which is declared at the top to be a pointer to a pparm_t) to point to:

the beginning of the parse table (sent in as an argument) + that index

so *pce will point to that location in the parse table for that particular attribute, whichever attribute it’s on

the * loc (declared at the top of this function) is initialized to point to that location of the parse table at index pce

for loop to go however many times according to the number of values for that attribute

will fill in the attribute values read in from the file

return the ndx back to parser( ), which uses it to adjust the mask

3. getndxp( )

returns the index from the parse array of the attribute that it’s looking for, so a 0 for “pixeldim”, a 1 for “worlddim”,

or a 2 for “viewpt”

cam_parse array in memory:

“pixeldim”
2
sizeof(int)
“%d”
0
“worlddim”
2
sizeof(double)
“%lf”
0
“viewpt”
3
sizeof(double)
“%lf”
0

.attrname

.numvals

[0] .valsize

.fmtstr

.loc

.attrname

.numvals

[1] .valsize

.fmtstr

.loc

.attrname

.numvals

[2] .valsize

.fmtstr

.loc