%token BEGIN_ POINTS POLYGONS BACKGROUND VIEWPOINT VIEWMATRIX END %token <long_val> INT_CONST %token <float_val> FLOAT_CONST %token <string> IDENTIFIERlegt die Tokens fest.
%start scenelegt fest, welche Regel den Startpunkt bildet.
scene : BEGIN_ IDENTIFIER { PR("reading scene : %s\n", $2); }
sections END IDENTIFIER { PR("done : %s\n", $6); }
;
Die ganze Szene besteht aus dem Token BEGIN_, einem Identifier,
den sections, dem Token END und wiederum dem Identifier.
PR bewirkt die Ausgabe einer Meldung.
sections : point_section poly_section background viewpoint
| point_section poly_section background viewpoint viewmatrix
;
Die Regel sections beschreibt die einzelnen Abschnitte der Szene:
Punkte, Polygone, Hintergrundfarbe, Viewpunkt oder Punkte, Polygone,
Hintergrundfarbe, Viewpunkt und Viewmatrix.
point_section: POINTS INT_CONST
{
number_of_points = $2;
PR("-> points : Number_of_points = %d\n", number_of_points );
Points = (struct point_struct *)malloc((number_of_points+
MAX_EXTRA_POINTS)*sizeof(struct point_struct));
assert(Points);
the_point_datas = (struct point_data_struct *)
malloc((number_of_points+MAX_EXTRA_POINTS)
*sizeof(struct point_data_struct));
assert(the_point_datas);
point_nr = 0;
}
point_datas
{ if (point_nr < number_of_points)
p_error("Syntax error or too few points."); }
;
Die Punktesektion besteht aus dem Token POINTS, einer
Integerkonstanten (Anzahl Punkte) und der Untersektion
point_datas. Hier wird der Speicher reserviert für die Punktestruktur.
point_datas : /* none */
| point_datas float_or_int float_or_int float_or_int
{
if (point_nr >= number_of_points) p_error("Too many points.");
Points[point_nr].x_world = $2;
Points[point_nr].y_world = $3;
Points[point_nr].z_world = $4;
Points[point_nr].Number_of_Polygons = 0;
Points[point_nr].Polygons = 0L;
Points[point_nr].flags = 0;
Points[point_nr].p = the_point_datas++;
point_nr++;
}
;
Regel für beliebig viele Punktdaten (rekursiver Aufruf).
poly_section : POLYGONS INT_CONST
{
number_of_polys = $2;
PR("-> polygons : Number_of_polygons = %d\n", number_of_polys );
Polygons = (struct polygon_struct *) malloc(number_of_polys*
sizeof(struct polygon_struct));
assert(Polygons);
the_poly_datas = (struct polygon_data_struct *)malloc(number_of_polys*
sizeof(struct polygon_data_struct));
assert(the_poly_datas);
poly_nr = 0;
}
poly_datas
{ if (poly_nr < number_of_polys)
p_error("Syntax error or too few polygons."); }
;
poly_datas : /* none */
| poly_datas INT_CONST
{
if (poly_nr >= number_of_polys) p_error("Too many polygons.");
Polygons[poly_nr].Number_of_Points = $2;
Polygons[poly_nr].Points = (struct point_struct **)
malloc(Polygons[poly_nr].Number_of_Points
*sizeof(struct point_struct *));
assert(Polygons[poly_nr].Points);
Polygons[poly_nr].Old_Number_of_Points = 0;
Polygons[poly_nr].Old_Points = 0L;
Polygons[poly_nr].flags = 0;
Polygons[poly_nr].p = the_poly_datas++;
poly_point_nr = 0;
}
poly_points ','
INT_CONST INT_CONST INT_CONST INT_CONST
{
if (poly_point_nr <Polygons[poly_nr].Number_of_Points)
p_error("Too few polygon points.");
Polygons[poly_nr].RGB_color = $6 + 256*$7 + 256*256*$8;
Polygons[poly_nr].RGB = Polygons[poly_nr].RGB_color;
Polygons[poly_nr].flags = $9;
}
poly_points : /* none */
| poly_points INT_CONST
{
if (poly_point_nr >= Polygons[poly_nr].Number_of_Points)
p_error("Too many polygon points.");
Polygons[poly_nr].Points[poly_point_nr] = &Points[$2]; poly_point_nr++;
}
;
Regel für die Polygonsektion, analog zu den Punktdaten.
background : BACKGROUND INT_CONST INT_CONST INT_CONST
{ backgroundColor = $2 + 256*$3 + 256*256*$4; }
;
Regel für die Hintergrundfarbe.
viewpoint : VIEWPOINT
float_or_int float_or_int float_or_int
float_or_int float_or_int float_or_int
float_or_int
float_or_int
{
MFLOAT cx,cy,cz,fx,fy,fz,phi;
Views = (struct view_struct *) malloc(sizeof(struct view_struct));
assert(Views);
cx = $2; cy = $3; cz = $4;
fx = $5; fy = $6; fz = $7;
phi = $8; Views->Distance_to_screen = $9;
calc_view_matrix(cx, cy, cz, fx, fy, fz, phi, Views->Object_to_World);
}
;
Regel für den Viewpunkt.
viewmatrix : VIEWMATRIX
float_or_int float_or_int float_or_int float_or_int
float_or_int float_or_int float_or_int float_or_int
float_or_int float_or_int float_or_int float_or_int
float_or_int float_or_int float_or_int float_or_int
{
assert(Views);
#define view Views->Object_to_World
view[0][0] = $2; view[0][1] = $3; view[0][2] = $4; view[0][3] = $5;
view[1][0] = $6; view[1][1] = $7; view[1][2] = $8; view[1][3] = $9;
view[2][0] = $10; view[2][1] = $11; view[2][2] = $12; view[2][3] = $13;
view[3][0] = $14; view[3][1] = $15; view[3][2] = $16; view[3][3] = $17;
#undef view
}
;
Regel für die Viewmatrix, die den Viewpunkt überschreibt.
float_or_int : FLOAT_CONST { $$ = $1; }
| INT_CONST { $$ = (float)$1; };
;
Regel float_or_int bewirkt, dass alle Koordinaten auch als
Integerwerte angegeben werden können.
Die Funktion parse öffnet die Datei Scene_filename und
ruft die Funktion yyparse, die von Yacc generiert wurde, auf.
Schliesslich kopiert sich in der View-Struktur Object_to_world
nach Object_to_world_begin. Abbildung 5.1 auf
Seite
zeigt den Pseudocode.
27
Abbildung 5.1: Pseudocode der Funktion parse