home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Stars of Shareware: Raytrace & Morphing
/
SOS-RAYTRACE.ISO
/
programm
/
source
/
rayce27s
/
rayparse.y
< prev
next >
Encoding:
Amiga
Atari
Commodore
DOS
FM Towns/JPY
Macintosh
Macintosh JP
Macintosh to JP
NeXTSTEP
RISC OS/Acorn
Shift JIS
UTF-8
Wrap
Lex Description
|
1994-01-26
|
34.5 KB
|
1,272 lines
%{
/* rayparse.y -- a Bison definition file for the Rayce language.
*
* (c) 1993,94 by Han-Wen Nienhuys, <hanwen@stack.urc.tue.nl>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation,
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* August 1993
*
* How does it work??
*
* I dunno, Bison does the difficult stuff.
*
* most of the elements of a PoV/Rayce file consist of an keyword xxx and
* some info enclosed in {}. In my grammar, this is called a xxx_block,
* which has the value of a pointer to an xxx. The pointer has space
* alloced, so it suffices to copy the pointer, not it's contents.
*
* Stuff enclosed in the { } of a xxx_block is called the xxx_body.
*/
#include <stdio.h>
#include "ray.h"
#include "proto.h"
#include "parse.h"
#include "extern.h"
#ifdef DEBUG
#define YYDEBUG 1
#endif
PRIVATE void kill_alloca(void);
#ifdef __TURBOC__
#define FIXALLOCA
#endif
#ifdef FIXALLOCA
#define alloca allocaa /* some compilers dosn't have alloca(), allocaa() is bugfix */
void *allocaa(size_t size);
#endif
#define YYINITDEPTH 50
PRIVATE void polycodenext(void);
PRIVATE struct poly_instruction *poly_code;
PRIVATE int code_p, current_maxcode = 1;
%}
%union {
color colorval;
double doubleval;
vector vectorval;
struct texture_data *textureval;
char stringval[200];
int intval;
struct declare_tab *dectabptr;
struct camera *cameraval;
object *objectval;
struct image_map *imageval;
}
/*tokens */
%token INCLUDE
%token OPTIONS
%token DEFAULTTEXT
%token BACKGROUND ANTIALIAS
%token TOLERANCE DEPTH
%token TIME ITERATIONS CUTOFF
%token OBJECT
%token COMPOSITE_T
%token COLOR RGB
%token RED GREEN BLUE ALPHA
%token ATMOSPHERE FOG
%token TRANSLATE ROTATE SCALE
%token TEXTURE
%token AMBIENT DIFFUSE BRILLIANCE
%token ROUGHNESS SPECULAR
%token IOR
%token REFRACTION REFLECTION
%token REFRACT_ANGLE REFLECT_ANGLE
%token TARGA GIF
%token IMAGE_MAP MAPTYPE ONCE INTERPOLATE USENORMAL
%token UVRANGE UVOFFSET UVSWAP
%token SPHERE_T PLANE_T QUADRIC_T BOX_T LIGHT_SOURCE_T
%token TRIANGLE_T TORUS_T ALGEBRAIC_T POLYGON_T SMOOTH_TRIANGLE_T
%token SUPERQ_T EXTRUSION_T CYLINDER_T DISC_T
%token OPEN
%token BOUNDED_BY CLIPPED_BY
%token SPEED
%token CAMERA_T
%token DIRECTION LOCATION
%token SKY FOV
%token LOOK_AT ASPECT
%token DECLARE
%token X_T
%token Y_T
%token Z_T
%token RADIUS ATTENUATION
%token SPOTLIGHT TIGHTNESS POINT_AT
%token INVERSE INTERSECTION UNION
%token STURM CLOSEDCURVE
%token <doubleval> FLOAT_CONST
%token <dectabptr> FLOAT_IDENTIFIER IDENTIFIER QUADRIC_IDENTIFIER
%token <dectabptr> COLOR_IDENTIFIER TEXTURE_IDENTIFIER SPHERE_IDENTIFIER
%token <dectabptr> PLANE_IDENTIFIER LIGHT_IDENTIFIER SMOOTH_TRIANGLE_IDENTIFIER
%token <dectabptr> BOX_IDENTIFIER VECTOR_IDENTIFIER COMPOSITE_IDENTIFIER
%token <dectabptr> CAMERA_IDENTIFIER TRIANGLE_IDENTIFIER UNION_IDENTIFIER
%token <dectabptr> INTERSECTION_IDENTIFIER TORUS_IDENTIFIER DISK_IDENTIFIER
%token <dectabptr> ALGEBRAIC_IDENTIFIER SUPERQ_IDENTIFIER EXTRUSION_IDENTIFIER
%token <dectabptr> POLYGON_IDENTIFIER DISC_IDENTIFIER
%token <dectabptr> OBJECT_IDENTIFIER
%token <dectabptr> IMAGEMAP_IDENTIFIER
%token <stringval> STRING
/* grammar elements */
%type <dectabptr> any_identifier old_identifier shape_identifier
%type <colorval> color_spec
%type <doubleval> pfloat
%type <vectorval> vexp
%type <doubleval> fexp
%type <vectorval> scale_stuff
%type <textureval> texture_block
%type <textureval> texture_body
%type <cameraval> camera_block
%type <cameraval> camera_body
%type <objectval> bounded_by clipped_by bounded_body
%type <objectval> sphere_body sphere_block
%type <objectval> plane_body plane_block
%type <objectval> quadric_block quadric_body
%type <objectval> box_body box_block
%type <objectval> light_block light_body
%type <objectval> triangle_body triangle_block
%type <objectval> disc_body disc_block
%type <objectval> union_body union_block
%type <objectval> intersection_block intersection_body
%type <objectval> csg_shape_block
%type <objectval> composite_body composite_block
%type <objectval> torus_body torus_block
%type <objectval> algebraic_block algebraic_body
%type <objectval> superq_block superq_body
%type <objectval> polygon_block polygon_defn polygon_body
%type <objectval> smooth_triangle_block smooth_triangle_body
%type <objectval> extrusion_block extrusion_body
%type <objectval> cylinder_block cylinder_body
%type <objectval> object_block object_body
%type <objectval> shape_block
%type <imageval> image_map_body image_map_block
/* precedences */
%nonassoc '='
%left '-' '+'
%left '*' '/'
%right '^' /* exponentiation */
%left NEG /* negation--unary minus */
%left VNEG /* vector negation. needed for reduce/reduce conflicts */
%%
/****************************************************************
GRAMMAR
****************************************************************/
/* GLOBAL PARTS */
/* frame is the start token */
frame: /* empty */ { }
| frame shape_block { /* read an object at top-level */
noo++;
add_to_composite (thescene, $2);
}
| frame composite_block { /* composite */
noo++;
add_to_composite(thescene, $2);
}
| frame object_block {
noo++;
add_to_composite(thescene, $2);
}
| frame camera_block { /* the scene camera */
free_camera(thecamera);
thecamera = $2;
}
| frame declare_block { } /* a declaration */
| frame options_block { } /* options {} */
| frame default_text_block { }
| frame atmosphere_block { }
;
default_text_block: DEFAULTTEXT '{' texture_body '}' { free_texture(thescene->text); thescene->text = $3; }
;
options_body: /* empty */ { }
| options_body TIME fexp ',' fexp {
time1 = $3; time2 = $5;
}
| options_body BACKGROUND vexp color_spec {
bggradient = $3;
background_color = $4;
}
| options_body BACKGROUND color_spec {
setvector(bggradient,0,0,0);
background_color = $3;
}
| options_body TOLERANCE fexp {
tolerance = $3;
}
| options_body ITERATIONS fexp {
if (!iter_override) /* commandline override? */
tries = (int) $3; /* No, use $3 */
}
| options_body DEPTH fexp { max_trace_level = (int) $3; }
| options_body ANTIALIAS fexp { Aalias_width = $3; }
| options_body CUTOFF fexp { depth_cutoff = $3; }
;
options_block: OPTIONS '{' options_body '}' { /*empty*/ }
;
camera_body:/* empty */ {
$$ = get_new_camera();
}
| CAMERA_IDENTIFIER {
$$ = get_new_camera();
copy_camera($$, (struct camera *) $1->data);
}
| camera_body ASPECT fexp { $$->aspect = $3; }
| camera_body LOOK_AT vexp { point_camera($$, $3); }
| camera_body LOCATION vexp { $$->eye = $3; }
| camera_body DIRECTION vexp { $$->eye_dir = $3; }
| camera_body SKY vexp { $$->sky = $3; }
| camera_body FOV fexp { $$->fov = to_fov_coeff($$, $3); }
| camera_body TRANSLATE vexp { translate_camera($$, $3); }
| camera_body ROTATE vexp { matrix rm; make_rotation_matrix(rm,$3);rotate_camera($$, rm); }
| camera_body scale_stuff { scale_camera($$, $2); }
;
camera_block: CAMERA_T '{' camera_body '}' { $$ = $3; }
;
atmosphere_block: ATMOSPHERE '{' atmosphere_body '}' { }
;
atmosphere_body: AMBIENT color_spec { ambient_light = $2; }
;
/****************************************************************
BASICS
****************************************************************/
pfloat: FLOAT_CONST { $$ = $1; }
| FLOAT_IDENTIFIER { $$ = * (double *) $1->data; }
;
vexp: '<' fexp ',' fexp ',' fexp '>' { setvector($$, $2, $4, $6); }
| '<' fexp '>' { setvector($$, $2, $2, $2); }
| VECTOR_IDENTIFIER { $$ = *(vector *) $1->data; }
| X_T { setvector($$,1,0,0); }
| Y_T { setvector($$,0,1,0); }
| Z_T { setvector($$,0,0,1); }
| '<' color_spec '>' { setvector($$,$2.r, $2.g, $2.b); }
| vexp '+' vexp { vadd($$, $1, $3); }
| '-' vexp %prec NEG { vneg($$, $2); }
| vexp '-' vexp { vsub($$, $1, $3); }
| fexp '*' vexp { svproduct($$, $1, $3); }
| vexp '*' fexp { svproduct($$, $3, $1); }
| vexp '^' vexp { vcross ($$, $1, $3); }
| vexp '/' fexp {
if ($3 == 0.0)
errormsg("division by zero");
svproduct($$, 1/$3, $1);
}
| '(' vexp ')' { $$ = $2; }
;
fexp: '-' fexp %prec VNEG { $$ = -$2; }
| pfloat { $$ = $1; }
| '(' vexp ',' vexp ')' { $$ = vdot($2,$4); }
| fexp '+' fexp { $$ = $1 + $3; }
| fexp '*'fexp { $$ = $1 * $3; }
| fexp '-' fexp { $$ = $1 - $3; }
| '(' fexp ')' { $$ = $2; }
| fexp '/' fexp {
if ($3 == 0.0)
errormsg("division by zero");
$$ = $1 / $3;
}
| fexp '^' fexp {
$$ = pow($1, $3);
}
;
scale_stuff:
SCALE vexp { $$ = $2; }
;
/***************************************************************************
* TEXTURES *
***************************************************************************/
/* stricly speaking, "color" for specifying black is correct. ugh */
color_spec: COLOR { $$.r = $$.g = $$.b = 0.0; }
| color_spec RED fexp { $$.r = $3 }
| color_spec GREEN fexp { $$.g = $3 }
| color_spec BLUE fexp { $$.b = $3 }
| color_spec COLOR_IDENTIFIER { $$ = *(color *) $2->data }
| color_spec ALPHA fexp { }
| color_spec RGB vexp { $$.r = $3.x; $$.g = $3.y; $$.b = $3.z; }
;
image_map_body:
TARGA STRING {
$$ = get_new_image_map();
$$->pic = get_TGA_pixels($2);
}
| GIF STRING {
$$ = get_new_image_map();
$$->pic = get_GIF_pixels($2);
}
| IMAGEMAP_IDENTIFIER {
$$ = get_new_image_map();
copy_image_map($$, $1->data);
}
| image_map_body MAPTYPE fexp {
switch((int) $3) {
case 0: $$->inv_map = inverse_planemap; break;
case 1: $$->inv_map = inverse_spheremap; break;
case 2: $$->inv_map = inverse_cylindermap; break;
case 3: $$->inv_map = inverse_torusmap; break;
default: errormsg("unknown maptype");
}
}
| image_map_body INTERPOLATE fexp {
$$->interpolated = (bool) $3;
}
| image_map_body USENORMAL { $$->usenormal = TRUE; }
| image_map_body ONCE { $$->once = TRUE; }
| image_map_body UVRANGE fexp ',' fexp { $$->u_range = $3; $$->v_range = $5; }
| image_map_body UVOFFSET fexp ',' fexp { $$->u_offs = $3; $$->v_offs = $5; }
| image_map_body UVSWAP { $$->uvswap = TRUE; }
;
image_map_block: IMAGE_MAP '{' image_map_body '}' { $$ = $3; }
;
texture_body: /* empty */
{
$$ = get_new_texture(); /* first, alloc ourself a texture */
}
| TEXTURE_IDENTIFIER {
$$ = get_new_texture();
copy_texture($$, (struct texture_data*) $1->data);
}
| texture_body color_spec { /* PoV compatibility */
$$->PoVcolor = get_new_color(); copy_color($$->PoVcolor, &$2);
setcolor ($$->ambient, .2,.2,.2);
setcolor ($$->diffuse, .6,.6,.6);
}
| texture_body AMBIENT color_spec { $$->ambient = $3 }
| texture_body AMBIENT fexp {
if ($$->PoVcolor != NULL)
setcolor($$->ambient , $3, $3, $3);
else
scale_color(&$$->ambient,$3);
}
| texture_body DIFFUSE color_spec { $$->diffuse = $3 }
| texture_body DIFFUSE fexp {
if ($$->PoVcolor != NULL)
setcolor($$->diffuse , $3, $3, $3);
else
scale_color(&$$->diffuse,$3);
}
| texture_body ROUGHNESS fexp { $$->roughness = $3; }
| texture_body SPECULAR color_spec { $$->specular = $3; }
| texture_body SPECULAR fexp {
if ($$->PoVcolor != NULL)
setcolor($$->specular , $3, $3, $3);
else
scale_color(&$$->specular,$3);
}
| texture_body IOR fexp { $$->index = $3; }
| texture_body BRILLIANCE fexp { $$->brilliance = $3; }
| texture_body REFLECTION color_spec { $$->refl_color = $3; }
| texture_body REFLECTION fexp {
if ($$->PoVcolor != NULL)
setcolor($$->refl_color , $3, $3, $3);
else
scale_color(&$$->refl_color,$3);
}
| texture_body REFRACTION color_spec { $$->refr_color = $3; }
| texture_body REFRACTION fexp {
if ($$->PoVcolor != NULL)
setcolor($$->refr_color, $3, $3, $3);
else
scale_color(&$$->refr_color,$3);
}
| texture_body REFRACT_ANGLE fexp { $$->refr_diffuse = degtorad($3); }
| texture_body REFLECT_ANGLE fexp { $$->refl_diffuse = degtorad($3); }
| texture_body image_map_block { $$->type = T_IMAGEMAP; $$->exttext.image = $2; }
| texture_body scale_stuff { scale_texture($$, $2); }
| texture_body TRANSLATE vexp { translate_texture($$, $3); }
| texture_body ROTATE vexp { matrix rm; make_rotation_matrix(rm,$3);rotate_texture($$, rm); }
;
texture_block: TEXTURE '{' texture_body '}' { $$ = $3; }
;
/***************************************************************************
* SHAPES *
***************************************************************************/
sphere_body: vexp ',' fexp {
$$ = get_new_sphere_object();
$$->data.sphere->center = $1;
$$->data.sphere->radius = ABS($3);
}
| SPHERE_IDENTIFIER {
$$ = get_new_sphere_object();
copy_object($$, (object *) $1->data);
}
| sphere_body TRANSLATE vexp { translate_object($$, $3); }
| sphere_body ROTATE vexp { matrix rm; make_rotation_matrix(rm,$3);rotate_object($$, rm); }
| sphere_body scale_stuff { scale_object($$, $2); }
| sphere_body INVERSE { $$->inverted = !$$->inverted; }
| sphere_body texture_block { $$->text = $2; }
;
sphere_block: SPHERE_T '{' sphere_body '}' { $$ = $3; }
;
/* flat and infinite plane : */
plane_body: vexp ',' fexp {
$$ = get_new_plane_object();
$$->data.plane->n = $1; $$->data.plane->mov = $3;
}
| PLANE_IDENTIFIER {
$$ = get_new_plane_object();
copy_object($$, (object *) $1->data);
}
| plane_body TRANSLATE vexp { translate_object($$, $3); }
| plane_body ROTATE vexp { matrix rm; make_rotation_matrix(rm,$3);rotate_object($$, rm); }
| plane_body scale_stuff { scale_object($$, $2); }
| plane_body INVERSE { $$->inverted = !$$->inverted; }
| plane_body texture_block { $$->text = $2; }
;
plane_block: PLANE_T '{' plane_body '}' { $$ = $3 }
;
quadric_body:
vexp ',' vexp ',' vexp ',' fexp {
{
struct quadric_data *q;
$$ = get_new_quadric_object();
q = $$->data.quadric;
q->xx = $1.x; q->yy = $1.y; q->zz = $1.z;
q->xy = $3.x; q->yz = $3.y; q->xz = $3.z;
q->x0 = $5.x; q->y0 = $5.y; q->z0 = $5.z;
q->a = $7;
}
}
| QUADRIC_IDENTIFIER {
$$ = get_new_quadric_object();
copy_object ($$, (object *) $1->data);
}
| quadric_body TRANSLATE vexp { translate_object($$, $3); }
| quadric_body ROTATE vexp { matrix rm; make_rotation_matrix(rm,$3);rotate_object($$, rm); }
| quadric_body scale_stuff { scale_object($$, $2); }
| quadric_body INVERSE { $$->inverted = !$$->inverted; }
| quadric_body texture_block { $$->text = $2; }
| quadric_body CLOSEDCURVE { $$->data.quadric->isclosed = TRUE; }
;
quadric_block: QUADRIC_T '{' quadric_body '}' { $$ = $3; }
;
box_body: vexp ',' vexp {
$$ = get_new_box_object();
$$->data.box->p1 = $1; $$->data.box->p2 = $3;
}
| BOX_IDENTIFIER {
$$ = get_new_box_object();
copy_object($$, (object *) $1->data);
}
| box_body TRANSLATE vexp { translate_object($$, $3); }
| box_body ROTATE vexp { matrix rm; make_rotation_matrix(rm,$3);rotate_object($$, rm); }
| box_body scale_stuff { scale_object($$, $2); }
| box_body INVERSE { $$->inverted = !$$->inverted; }
| box_body texture_block { $$->text = $2; }
;
box_block: BOX_T '{' box_body '}' { $$ = $3; }
;
light_body: vexp color_spec {
$$ = get_new_light_object();
$$->data.light->org = $1;
$$->data.light->lcolor = $2;
}
| LIGHT_IDENTIFIER {
$$ = get_new_light_object();
copy_object($$, (object *) $1->data);
}
| light_body RADIUS fexp { $$->data.light->radius = $3; }
| light_body ATTENUATION fexp {
$$->data.light->attenuation_exp = $3;
}
| light_body SPOTLIGHT POINT_AT vexp TIGHTNESS fexp {
struct light_data *l;
l = $$->data.light;
vsub(l->direction, $4,l->org);
norm(l->direction, l->direction);
l->tightness = $6;
l->spotlight = TRUE;
}
| light_body TRANSLATE vexp { translate_object($$, $3); }
| light_body ROTATE vexp { matrix rm; make_rotation_matrix(rm,$3);rotate_object($$, rm); }
| light_body scale_stuff { scale_object($$, $2); }
;
light_block: LIGHT_SOURCE_T '{' light_body '}' { $$ = $3; }
;
triangle_body:
vexp ',' vexp ',' vexp {
struct triangle_data *s;
$$ = get_new_triangle_object();
s = $$->data.triangle;
s->vertices[0] = $1;
s->vertices[1] = $3;
s->vertices[2] = $5;
}
| TRIANGLE_IDENTIFIER {
$$ = get_new_triangle_object();
copy_object($$, (object *) $1->data);
}
| triangle_body TRANSLATE vexp { translate_object($$, $3);}
| triangle_body ROTATE vexp { matrix rm; make_rotation_matrix(rm,$3);rotate_object($$, rm); }
| triangle_body scale_stuff { scale_object($$, $2); }
| triangle_body texture_block { $$->text = $2; }
;
triangle_block: TRIANGLE_T '{' triangle_body '}' { $$ =$3; }
;
smooth_triangle_body:
vexp ',' vexp ',' vexp ',' vexp ',' vexp ',' vexp {
struct triangle_data *s;
$$ = get_new_smooth_triangle_object();
s = $$->data.triangle;
s->vertices[0] = $1;
s->normals[0] = $3;
s->vertices[1] = $5;
s->normals[1] = $7;
s->vertices[2] = $9;
s->normals[2] = $11;
}
| SMOOTH_TRIANGLE_IDENTIFIER {
$$ = get_new_smooth_triangle_object();
copy_object($$, (object *) $1->data);
}
| smooth_triangle_body TRANSLATE vexp { translate_object($$, $3);}
| smooth_triangle_body ROTATE vexp { matrix rm; make_rotation_matrix(rm,$3);rotate_object($$, rm); }
| smooth_triangle_body scale_stuff { scale_object($$, $2); }
| smooth_triangle_body texture_block { $$->text = $2; }
;
smooth_triangle_block: SMOOTH_TRIANGLE_T '{' smooth_triangle_body '}' { $$ =$3; }
;
torus_body:
fexp ',' fexp {
$$ = get_new_torus_object();
$$->data.torus->Rad = $1; $$->data.torus->rad = $3;
}
| TORUS_IDENTIFIER {
$$ = get_new_torus_object();
copy_object( $$, (object *) $1->data);
}
| torus_body TRANSLATE vexp { translate_object($$, $3); }
| torus_body ROTATE vexp { matrix rm; make_rotation_matrix(rm,$3);rotate_object($$, rm); }
| torus_body scale_stuff { scale_object($$, $2); }
| torus_body INVERSE { $$->inverted = !$$->inverted; }
| torus_body STURM { $$->data.torus->use_sturm = TRUE }
| torus_body texture_block { $$->text = $2; }
;
torus_block: TORUS_T '{' torus_body '}' { $$ =$3; }
;
/* a nonempty sequence of vectors */
polygon_defn:
vexp {
$$ = get_new_polygon_object();
add_vertex_to_polygon($$, $1);
}
| polygon_defn ',' vexp {
add_vertex_to_polygon($$, $3);
}
;
polygon_body:
polygon_defn {
$$ = $1;
}
| POLYGON_IDENTIFIER {
$$ = get_new_polygon_object();
copy_object($$, $1->data);
}
| polygon_body TRANSLATE vexp { translate_object($$, $3); }
| polygon_body ROTATE vexp { matrix rm; make_rotation_matrix(rm,$3);rotate_object($$, rm); }
| polygon_body scale_stuff { scale_object($$, $2); }
| polygon_body texture_block { $$->text = $2; }
;
polygon_block: POLYGON_T '{' polygon_body '}' { $$= $3; }
;
disc_body:
vexp ',' vexp ',' fexp {
struct disc_data *d;
$$ = get_new_disc_object();
d = $$->data.disc;
d->center = $1; d->n = $3; d->R = $5;
}
| vexp ',' vexp ',' fexp ',' fexp {
struct disc_data *d;
$$ = get_new_disc_object();
d = $$->data.disc;
d->center = $1; d->n = $3; d->R = $5; d->r = $7;
}
| DISC_IDENTIFIER { $$ = get_new_disc_object(); copy_object($$, $1->data); }
| disc_body TRANSLATE vexp { translate_object($$, $3); }
| disc_body ROTATE vexp { matrix rm; make_rotation_matrix(rm,$3);rotate_object($$, rm); }
| disc_body scale_stuff { scale_object($$, $2); }
| disc_body texture_block { $$->text = $2; }
;
disc_block: DISC_T '{' disc_body '}' { $$ = $3;}
superq_block: SUPERQ_T '{' superq_body '}' { $$ = $3; }
;
superq_body: vexp { $$ = get_new_superq_object(); $$->data.superq->powvect = $1; }
| SUPERQ_IDENTIFIER { $$ = get_new_superq_object(); copy_object($$, $1->data); }
| superq_body TRANSLATE vexp { translate_object($$, $3); }
| superq_body ROTATE vexp { matrix rm; make_rotation_matrix(rm,$3);rotate_object($$, rm); }
| superq_body scale_stuff { scale_object($$, $2); }
| superq_body texture_block { $$->text = $2; }
;
extrusion_block: EXTRUSION_T '{' extrusion_body '}' { $$ = $3; }
;
extrusion_body: fexp shape_block {
$$ = get_new_extrusion_object();
($$->data.extrusion->shape = $2)->daddy = $$;
$$->data.extrusion->height = $1;
}
| extrusion_body OPEN fexp {
int i = (int) $3;
$$->data.extrusion->locap = (i & 0x01);
$$->data.extrusion->hicap = (i & 0x02);
}
| EXTRUSION_IDENTIFIER {
$$ = get_new_extrusion_object();
copy_object($$, $1->data);
}
| extrusion_body TRANSLATE vexp { translate_object($$, $3); }
| extrusion_body ROTATE vexp { matrix rm; make_rotation_matrix(rm,$3);rotate_object($$, rm); }
| extrusion_body scale_stuff { scale_object($$, $2); }
| extrusion_body texture_block { $$->text = $2; }
;
cylinder_block: CYLINDER_T '{' cylinder_body '}' { $$ = $3; }
;
cylinder_body: vexp ',' vexp ',' fexp {
$$ = make_cylinder_object($1, $3, $5);
}
| EXTRUSION_IDENTIFIER {
$$ = get_new_extrusion_object();
copy_object($$, $1->data);
}
| cylinder_body TRANSLATE vexp { translate_object($$, $3); }
| cylinder_body ROTATE vexp { matrix rm; make_rotation_matrix(rm,$3);rotate_object($$, rm); }
| cylinder_body scale_stuff { scale_object($$, $2); }
| cylinder_body texture_block { $$->text = $2; }
;
/*****************************************************************
* algebraic surfaces.
*****************************************************************/
algebraic_block: ALGEBRAIC_T '{' algebraic_body '}' { $$ = $3; }
;
algebraic_body:
poly_decl {
int i;
struct algebraic_data *a;
$$ = get_new_algebraic_object();
a = $$->data.algebraic;
i = code_p * sizeof(struct poly_instruction);
a->code = (struct poly_instruction *) malloc(i);
CHECK_MEM(a->code, "poly instructions");
a->codesize = code_p;
for (i = 0; i < code_p; i++)
*(a->code + i) = poly_code[i];
}
| ALGEBRAIC_IDENTIFIER {
$$ = get_new_algebraic_object();
copy_object( $$, (object *) $1->data);
}
| algebraic_body ROTATE vexp { matrix rm; make_rotation_matrix(rm,$3);rotate_object($$, rm); }
| algebraic_body scale_stuff { scale_object($$,$2); }
| algebraic_body TRANSLATE vexp { translate_object ($$, $3); }
| algebraic_body INVERSE { $$->inverted = !$$->inverted; }
| algebraic_body STURM { $$->data.algebraic->usesturm = TRUE; }
| algebraic_body CLOSEDCURVE { $$->data.algebraic->isclosed = TRUE; }
| algebraic_body texture_block { $$->text = $2; }
;
poly_decl: poly_start poly3 poly_end { }
;
/* start of poly. Needed to clean old code */
poly_start: '$' { code_p = 0; }
;
poly_end: '$' { }
;
/*
parse a polynomial, translate it into code for a stack oriented
machine. See Kernighan and Pike, the Unix Programming Environment.
*/
poly3:
pfloat {
poly_code[code_p].type = POLY_CONS;
poly_code[code_p].data.factor = $1;
polycodenext();
}
| '(' poly3 ')' {
/* nothing. */
}
| X_T {
poly_code[code_p].type = POLY_X;
polycodenext();
}
| Y_T {
poly_code[code_p].type = POLY_Y;
polycodenext();
}
| Z_T {
poly_code[code_p].type = POLY_Z;
polycodenext();
}
| poly3 '+' poly3 {
poly_code[code_p].type = POLY_OP;
poly_code[code_p].data.op = '+';
polycodenext();
}
| poly3 '-' poly3 {
poly_code[code_p].type = POLY_OP;
poly_code[code_p].data.op = '-';
polycodenext();
}
| '-' poly3 %prec NEG {
poly_code[code_p].type = POLY_OP;
poly_code[code_p].data.op = 'n';
polycodenext();
}
| poly3 '*' poly3 {
poly_code[code_p].type = POLY_OP;
poly_code[code_p].data.op = '*';
polycodenext();
}
| poly3 '^' poly3 {
if (poly_code[code_p-1].type != POLY_CONS)
errormsg("^ must have integer");
poly_code[code_p].type = POLY_OP;
poly_code[code_p].data.op = '^';
polycodenext();
}
| poly3 '=' poly3 {
poly_code[code_p].type = POLY_OP;
poly_code[code_p].data.op = '-';
polycodenext();
}
;
/***************************************************************************
* CSG *
***************************************************************************/
intersection_body:
csg_shape_block {
$$ = get_new_CSGinter_object();
add_to_CSG($$, $1);
}
| INTERSECTION_IDENTIFIER {
$$ = get_new_CSGinter_object();
copy_object($$, (object *) $1->data);
}
| intersection_body csg_shape_block { add_to_CSG($$, $2); }
| intersection_body INVERSE { $$->inverted = !$$->inverted }
| intersection_body scale_stuff { scale_object($$, $2); }
| intersection_body ROTATE vexp { matrix rm; make_rotation_matrix(rm,$3);rotate_object($$, rm); }
| intersection_body TRANSLATE vexp { translate_object($$, $3); }
| intersection_body texture_block { $$->text = $2; }
;
union_body:
csg_shape_block {
$$ = get_new_CSGunion_object();
add_to_CSG($$, $1);
}
| UNION_IDENTIFIER {
$$ = get_new_CSGunion_object();
copy_object($$, (object *) $1->data);
}
| union_body csg_shape_block { add_to_CSG($$, $2); }
| union_body TRANSLATE vexp { translate_object($$, $3); }
| union_body ROTATE vexp { matrix rm; make_rotation_matrix(rm,$3);rotate_object($$, rm); }
| union_body scale_stuff { scale_object($$, $2); }
| union_body INVERSE { $$->inverted = !$$->inverted; }
| union_body texture_block { $$->text = $2; }
;
intersection_block: INTERSECTION '{' intersection_body '}' { $$ = $3; }
;
union_block: UNION '{' union_body '}' { $$ = $3; }
;
/*
* GENERIC OBJECTS
*/
csg_shape_block:
sphere_block { $$ = $1; }
| plane_block { $$ = $1; }
| quadric_block { $$ = $1; }
| torus_block { $$ = $1; }
| box_block { $$ = $1; }
| intersection_block { $$ = $1; }
| union_block { $$ = $1; }
| algebraic_block { $$ = $1; }
| superq_block { $$ = $1; }
| extrusion_block { $$ = $1; }
| cylinder_block { $$ = $1; }
;
shape_block:
csg_shape_block {
$$ = $1;
}
| polygon_block { $$ = $1; }
| light_block { $$ = $1; }
| triangle_block { $$ = $1; }
| smooth_triangle_block { $$ = $1; }
| disc_block { $$ = $1; }
;
bounded_body:
csg_shape_block { $$ = $1; }
| bounded_body csg_shape_block {
append_to_object_list($$, $2);
}
;
clipped_by: CLIPPED_BY '{' bounded_body '}' { $$ = $3; }
;
bounded_by: BOUNDED_BY '{' bounded_body '}' { $$ = $3; }
;
composite_block: COMPOSITE_T '{' composite_body '}' { $$ = $3; }
;
composite_body: /* empty */ {
$$ = get_new_composite_object();
}
| COMPOSITE_IDENTIFIER {
$$ = get_new_composite_object();
copy_object($$, (object *) $1->data);
}
| composite_body composite_block {
add_to_composite($$, $2);
}
| composite_body shape_block {
add_to_composite($$, $2);
}
| composite_body object_block {
add_to_composite($$, $2);
}
| composite_body bounded_by {
$$->bound = $2;
}
| composite_body clipped_by {
$$->clip = $2;
}
| composite_body clipped_by_bound {
add_bounds_to_clip($$);
}
| composite_body TRANSLATE vexp { translate_object($$, $3); }
| composite_body ROTATE vexp { matrix rm; make_rotation_matrix(rm,$3);rotate_object($$, rm); }
| composite_body scale_stuff { scale_object($$, $2); }
| composite_body texture_block { $$->text = $2; }
| composite_body SPEED vexp { speed_composite($$, $3); }
;
clipped_by_bound: CLIPPED_BY '{' BOUNDED_BY '}' { }
;
object_block: OBJECT '{' object_body '}' { $$ = $3; }
;
object_body: shape_identifier {
$$ = get_new_object();
copy_object($$, (object *) $1->data);
}
| shape_block { $$ = $1; }
| object_body TRANSLATE vexp { translate_object($$, $3); }
| object_body scale_stuff { scale_object($$,$2); }
| object_body ROTATE vexp { matrix rm; make_rotation_matrix(rm,$3); rotate_object($$, rm); }
| object_body bounded_by {
$$->bound = $2;
}
| object_body clipped_by {
$$->clip = $2;
}
| object_body clipped_by_bound {
add_bounds_to_clip($$);
}
| object_body SPEED vexp { vadd($$->speed, $$->speed, $3); }
| object_body texture_block { $$->text = $2; }
;
/***************************************************************************
* DECLARATIONS *
***************************************************************************/
/* an assignment will be done to this thing. */
any_identifier:
IDENTIFIER { $$ = $1; }
| old_identifier { warning("redeclaration of %s", $1->name); $$ = $1; }
;
shape_identifier:
QUADRIC_IDENTIFIER { $$ = $1; }
| SPHERE_IDENTIFIER { $$ = $1; }
| PLANE_IDENTIFIER { $$ = $1; }
| LIGHT_IDENTIFIER { $$ = $1; }
| BOX_IDENTIFIER { $$ = $1; }
| TRIANGLE_IDENTIFIER { $$ = $1; }
| SMOOTH_TRIANGLE_IDENTIFIER { $$ = $1; }
| INTERSECTION_IDENTIFIER { $$ = $1; }
| UNION_IDENTIFIER { $$ = $1; }
| TORUS_IDENTIFIER { $$ = $1; }
| ALGEBRAIC_IDENTIFIER { $$ = $1; }
| SUPERQ_IDENTIFIER { $$ = $1; }
| OBJECT_IDENTIFIER { $$ = $1; }
| COMPOSITE_IDENTIFIER { $$ = $1; }
;
/* an old identifier is reused. free up the space it used. */
old_identifier:
FLOAT_IDENTIFIER { free_float((double *) $1->data); $$ = $1; }
| shape_identifier { free_object($1->data); $$ = $1; }
| VECTOR_IDENTIFIER { free_vector((vector *) $1->data); $$ = $1; }
| CAMERA_IDENTIFIER { free_camera ((struct camera *) $1->data); $$ = $1; }
| TEXTURE_IDENTIFIER { free_texture ((struct texture_data *) $1->data); $$ = $1; }
| COLOR_IDENTIFIER { free_color($1->data); $$ = $1; }
| IMAGEMAP_IDENTIFIER { free_image_map($1->data); $$ = $1; }
;
declare_block:
DECLARE any_identifier '=' object_block {
$2->data = (void *) $4;
$2->type = OBJECT_IDENTIFIER;
}
| DECLARE any_identifier '=' composite_block {
$2->data= (void *) $4;
$2->type = COMPOSITE_IDENTIFIER;
}
| DECLARE any_identifier '=' sphere_block {
$2->data= (void *) $4;
$2->type = SPHERE_IDENTIFIER;
}
| DECLARE any_identifier '=' light_block {
$2->data= (void *) $4;
$2->type = LIGHT_IDENTIFIER;
}
| DECLARE any_identifier '=' plane_block {
$2->data= (void *) $4;
$2->type = PLANE_IDENTIFIER;
}
| DECLARE any_identifier '=' quadric_block {
$2->data= (void *) $4;
$2->type = QUADRIC_IDENTIFIER;
}
| DECLARE any_identifier '=' box_block {
$2->data= (void *) $4;
$2->type = BOX_IDENTIFIER;
}
| DECLARE any_identifier '=' torus_block {
$2->data = (void *) $4;
$2->type = TORUS_IDENTIFIER;
}
| DECLARE any_identifier '=' algebraic_block {
$2->data = (void*) $4;
$2->type = ALGEBRAIC_IDENTIFIER;
}
| DECLARE any_identifier '=' superq_block {
$2->data = (void*) $4;
$2->type = SUPERQ_IDENTIFIER;
}
| DECLARE any_identifier '=' polygon_block {
$2->data = (void*) $4;
$2->type = POLYGON_IDENTIFIER;
}
| DECLARE any_identifier '=' triangle_block {
$2->data = (void*) $4;
$2->type = TRIANGLE_IDENTIFIER;
}
| DECLARE any_identifier '=' disc_block {
$2->data = (void*) $4;
$2->type = DISC_IDENTIFIER;
}
| DECLARE any_identifier '=' smooth_triangle_block {
$2->data = (void*) $4;
$2->type = SMOOTH_TRIANGLE_IDENTIFIER;
}
| DECLARE any_identifier '=' extrusion_block {
$2->data = (void*) $4;
$2->type = EXTRUSION_IDENTIFIER;
}
| DECLARE any_identifier '=' cylinder_block {
$2->data = (void*) $4;
$2->type = EXTRUSION_IDENTIFIER;
}
| DECLARE any_identifier '=' union_block {
$2->data = (void *) $4;
$2->type = UNION_IDENTIFIER;
}
| DECLARE any_identifier '=' intersection_block {
$2->data = (void *) $4;
$2->type = INTERSECTION_IDENTIFIER;
}
| DECLARE any_identifier '=' texture_block {
$2->data= (void *) $4;
$2->type = TEXTURE_IDENTIFIER;
}
| DECLARE any_identifier '=' image_map_block {
$2->data = (void*) $4;
$2->type = IMAGEMAP_IDENTIFIER;
}
| DECLARE any_identifier '=' color_spec {
color *p;
p = get_new_color();
$2->data = (void *) p;
$2->type = COLOR_IDENTIFIER;
*p = $4;
}
| DECLARE any_identifier '=' camera_block {
$2->data= (void *) $4;
$2->type = CAMERA_IDENTIFIER;
}
| DECLARE any_identifier '=' vexp {
vector *p;
$2->data = p = get_new_vector();
copy_vector(p, &$4);
$2->type = VECTOR_IDENTIFIER;
}
| DECLARE any_identifier '=' fexp {
double *p;
p = get_new_float();
$2->data= (void *) p;
$2->type = FLOAT_IDENTIFIER;
*p = $4;
}
;
/****************************************************************
END OF GRAMMAR
****************************************************************/
%%
PUBLIC void
print_interior(void)
{
printf("-------------------INTERIOR------------------------\n");
print_camera(thecamera);
printf("t1 %lf, t2 %lf, tolerance %lf\n", time1, time2, tolerance);
printf("frames %d\n", tries);
print_v("background gradient", bggradient);
printf("cutoff %lf\nantialias %lf\n", depth_cutoff, Aalias_width);
printf("\n=================SCENE ELEMENTS==================\n");
print_object(thescene);
printf("\n==================LIGHT LIST=====================\n");
print_light_list();
printf("\n=================DECLARATIONS====================\n");
print_dectab();
}
PUBLIC void
yyerror(char *s)
{
errormsg("%s", s);
}
#ifdef FIXALLOCA
PRIVATE void *alloca_ptr[300];
PRIVATE int alloca_idx = 0;
void *allocaa(size_t size)
{
void *p;
if (alloca_idx++ >= 300)
errormsg("Get a life!");
p = malloc(size);
CHECK_MEM(p, "allocaa");
return alloca_ptr[alloca_idx] = p;
}
#endif
PRIVATE void kill_alloca(void)
{
#ifdef FIXALLOCA
while (alloca_idx --)
free(alloca_ptr[alloca_idx]);
#endif
}
/* increment code pointer, and do a realloc if necessary */
PRIVATE void
polycodenext(void)
{
if (++code_p >= current_maxcode) {
current_maxcode *= 2;
poly_code = realloc(poly_code, current_maxcode*sizeof(struct poly_instruction));
if (poly_code == NULL)
alloc_err("input polycode instructions.");
poly_code[code_p].data.factor = 1.0;
}
}
PUBLIC void
readfile(char *fn)
{
set_input(fn); /* set the input */
poly_code = malloc(current_maxcode * sizeof(struct poly_instruction));
CHECK_MEM(poly_code, "poly code");
#ifdef DEBUG
if (debug_options & DEBUGPARS)
yydebug = TRUE;
else
yydebug = FALSE;
#endif
yyparse();
make_light_list(thescene); /* set up the light_source list */
if (Aalias_width < 0)
Aalias_width = 1.0 - 1/(double) tries;
precompute_object(thescene);
#ifdef DEBUG
if (debug_options & DEBUGDECL)
print_interior();
#endif
close_input();
kill_alloca();
free(poly_code);
}