00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 %{
00025 #include "api.h"
00026 #include "pbrt.h"
00027 #include "paramset.h"
00028 #include <stdarg.h>
00029
00030 extern int yylex( void );
00031 int line_num = 0;
00032 string current_file;
00033
00034 #define YYMAXDEPTH 100000000
00035
00036 void yyerror( char *str ) {
00037 Severe( "Parsing error: %s", str);
00038 }
00039
00040 void ParseError( const char *format, ... ) PRINTF_FUNC;
00041
00042 void ParseError( const char *format, ... ) {
00043 char error[4096];
00044 va_list args;
00045 va_start( args, format );
00046 vsnprintf(error, 4096, format, args);
00047 yyerror(error);
00048 va_end( args );
00049 }
00050
00051 int cur_paramlist_allocated = 0;
00052 int cur_paramlist_size = 0;
00053 const char **cur_paramlist_tokens = NULL;
00054 void **cur_paramlist_args = NULL;
00055 int *cur_paramlist_sizes = NULL;
00056 bool *cur_paramlist_texture_helper = NULL;
00057
00058 #define CPS cur_paramlist_size
00059 #define CPT cur_paramlist_tokens
00060 #define CPA cur_paramlist_args
00061 #define CPTH cur_paramlist_texture_helper
00062 #define CPSZ cur_paramlist_sizes
00063
00064 typedef struct ParamArray {
00065 int element_size;
00066 int allocated;
00067 int nelems;
00068 void *array;
00069 } ParamArray;
00070
00071 ParamArray *cur_array = NULL;
00072 bool array_is_single_string = false;
00073
00074 #define NA(r) ((float *) r->array)
00075 #define SA(r) ((const char **) r->array)
00076
00077 void AddArrayElement( void *elem ) {
00078 if (cur_array->nelems >= cur_array->allocated) {
00079 cur_array->allocated = 2*cur_array->allocated + 1;
00080 cur_array->array = realloc( cur_array->array,
00081 cur_array->allocated*cur_array->element_size );
00082 }
00083 char *next = ((char *)cur_array->array) + cur_array->nelems *
00084 cur_array->element_size;
00085 memcpy( next, elem, cur_array->element_size );
00086 cur_array->nelems++;
00087 }
00088
00089 ParamArray *ArrayDup( ParamArray *ra )
00090 {
00091 ParamArray *ret = new ParamArray;
00092 ret->element_size = ra->element_size;
00093 ret->allocated = ra->allocated;
00094 ret->nelems = ra->nelems;
00095 ret->array = malloc(ra->nelems * ra->element_size);
00096 memcpy( ret->array, ra->array, ra->nelems * ra->element_size );
00097 return ret;
00098 }
00099
00100 void ArrayFree( ParamArray *ra )
00101 {
00102 free(ra->array);
00103 delete ra;
00104 }
00105
00106 void FreeArgs()
00107 {
00108 for (int i = 0; i < cur_paramlist_size; ++i)
00109 delete[] ((char *)cur_paramlist_args[i]);
00110 }
00111
00112 static bool VerifyArrayLength( ParamArray *arr, int required,
00113 const char *command ) {
00114 if (arr->nelems != required) {
00115 ParseError( "%s requires a(n) %d element array!", command, required);
00116 return false;
00117 }
00118 return true;
00119 }
00120 enum { PARAM_TYPE_INT, PARAM_TYPE_BOOL, PARAM_TYPE_FLOAT, PARAM_TYPE_POINT,
00121 PARAM_TYPE_VECTOR, PARAM_TYPE_NORMAL, PARAM_TYPE_COLOR,
00122 PARAM_TYPE_STRING, PARAM_TYPE_TEXTURE };
00123 static void InitParamSet(ParamSet &ps, int count, const char **tokens,
00124 void **args, int *sizes, bool *texture_helper);
00125 static bool lookupType(const char *token, int *type, string &name);
00126 #define YYPRINT(file, type, value) \
00127 { \
00128 if ((type) == ID || (type) == STRING) \
00129 fprintf ((file), " %s", (value).string); \
00130 else if ((type) == NUM) \
00131 fprintf ((file), " %f", (value).num); \
00132 }
00133 %}
00134
00135 %union {
00136 char string[1024];
00137 float num;
00138 ParamArray *ribarray;
00139 }
00140 %token <string> STRING ID
00141 %token <num> NUM
00142 %token LBRACK RBRACK
00143
00144 %token ACCELERATOR AREALIGHTSOURCE ATTRIBUTEBEGIN ATTRIBUTEEND
00145 %token CAMERA CONCATTRANSFORM COORDINATESYSTEM COORDSYSTRANSFORM
00146 %token FILM IDENTITY LIGHTSOURCE LOOKAT MATERIAL
00147 %token OBJECTBEGIN OBJECTEND OBJECTINSTANCE
00148 %token PIXELFILTER REVERSEORIENTATION ROTATE SAMPLER SCALE
00149 %token SEARCHPATH SHAPE SURFACEINTEGRATOR TEXTURE TRANSFORMBEGIN TRANSFORMEND
00150 %token TRANSFORM TRANSLATE VOLUME VOLUMEINTEGRATOR WORLDBEGIN WORLDEND
00151
00152 %token HIGH_PRECEDENCE
00153
00154 %type<ribarray> array num_array string_array
00155 %type<ribarray> real_num_array real_string_array
00156 %%
00157 start: ri_stmt_list
00158 {
00159 };
00160
00161 array_init: %prec HIGH_PRECEDENCE
00162 {
00163 if (cur_array) ArrayFree( cur_array );
00164 cur_array = new ParamArray;
00165 cur_array->allocated = 0;
00166 cur_array->nelems = 0;
00167 cur_array->array = NULL;
00168 array_is_single_string = false;
00169 };
00170
00171 string_array_init: %prec HIGH_PRECEDENCE
00172 {
00173 cur_array->element_size = sizeof( const char * );
00174 };
00175
00176 num_array_init: %prec HIGH_PRECEDENCE
00177 {
00178 cur_array->element_size = sizeof( float );
00179 };
00180
00181 array: string_array
00182 {
00183 $$ = $1;
00184 }
00185 | num_array
00186 {
00187 $$ = $1;
00188 };
00189
00190 string_array: real_string_array
00191 {
00192 $$ = $1;
00193 }
00194 | single_element_string_array
00195 {
00196 $$ = ArrayDup(cur_array);
00197 array_is_single_string = true;
00198 };
00199
00200 real_string_array: array_init LBRACK string_list RBRACK
00201 {
00202 $$ = ArrayDup(cur_array);
00203 };
00204
00205 single_element_string_array: array_init string_list_entry
00206 {
00207 };
00208
00209 string_list: string_list string_list_entry
00210 {
00211 }
00212 | string_list_entry
00213 {
00214 };
00215
00216 string_list_entry: string_array_init STRING
00217 {
00218 char *to_add = strdup($2);
00219 AddArrayElement( &to_add );
00220 };
00221
00222 num_array: real_num_array
00223 {
00224 $$ = $1;
00225 }
00226 | single_element_num_array
00227 {
00228 $$ = ArrayDup(cur_array);
00229 };
00230
00231 real_num_array: array_init LBRACK num_list RBRACK
00232 {
00233 $$ = ArrayDup(cur_array);
00234 };
00235
00236 single_element_num_array: array_init num_list_entry
00237 {
00238 };
00239
00240 num_list: num_list num_list_entry
00241 {
00242 }
00243 | num_list_entry
00244 {
00245 };
00246
00247 num_list_entry: num_array_init NUM
00248 {
00249 float to_add = $2;
00250 AddArrayElement( &to_add );
00251 };
00252
00253 paramlist: paramlist_init paramlist_contents
00254 {
00255 };
00256
00257 paramlist_init: %prec HIGH_PRECEDENCE
00258 {
00259 cur_paramlist_size = 0;
00260 };
00261
00262 paramlist_contents: paramlist_entry paramlist_contents
00263 {
00264 }
00265 |
00266 {
00267 };
00268
00269 paramlist_entry: STRING array
00270 {
00271 void *arg = new char[ $2->nelems * $2->element_size ];
00272 memcpy(arg, $2->array, $2->nelems * $2->element_size);
00273 if (cur_paramlist_size >= cur_paramlist_allocated) {
00274 cur_paramlist_allocated = 2*cur_paramlist_allocated + 1;
00275 cur_paramlist_tokens = (const char **) realloc(cur_paramlist_tokens, cur_paramlist_allocated*sizeof(const char *) );
00276 cur_paramlist_args = (void * *) realloc( cur_paramlist_args, cur_paramlist_allocated*sizeof(void *) );
00277 cur_paramlist_sizes = (int *) realloc( cur_paramlist_sizes, cur_paramlist_allocated*sizeof(int) );
00278 cur_paramlist_texture_helper = (bool *) realloc( cur_paramlist_texture_helper, cur_paramlist_allocated*sizeof(bool) );
00279 }
00280 cur_paramlist_tokens[cur_paramlist_size] = $1;
00281 cur_paramlist_sizes[cur_paramlist_size] = $2->nelems;
00282 cur_paramlist_texture_helper[cur_paramlist_size] = array_is_single_string;
00283 cur_paramlist_args[cur_paramlist_size++] = arg;
00284 ArrayFree( $2 );
00285 };
00286
00287 ri_stmt_list: ri_stmt_list ri_stmt
00288 {
00289 }
00290 | ri_stmt
00291 {
00292 };
00293
00294 ri_stmt: ACCELERATOR STRING paramlist
00295 {
00296 ParamSet params;
00297 InitParamSet(params, CPS, CPT, CPA, CPSZ, CPTH);
00298 pbrtAccelerator($2, params);
00299 FreeArgs();
00300 }
00301 | AREALIGHTSOURCE STRING paramlist
00302 {
00303 ParamSet params;
00304 InitParamSet(params, CPS, CPT, CPA, CPSZ, CPTH);
00305 pbrtAreaLightSource($2, params);
00306 FreeArgs();
00307 }
00308 | ATTRIBUTEBEGIN
00309 {
00310 pbrtAttributeBegin();
00311 }
00312 | ATTRIBUTEEND
00313 {
00314 pbrtAttributeEnd();
00315 }
00316 | CAMERA STRING paramlist
00317 {
00318 ParamSet params;
00319 InitParamSet(params, CPS, CPT, CPA, CPSZ, CPTH);
00320 pbrtCamera($2, params);
00321 FreeArgs();
00322 }
00323 | CONCATTRANSFORM num_array
00324 {
00325 if (VerifyArrayLength( $2, 16, "ConcatTransform" ))
00326 pbrtConcatTransform( (float *) $2->array );
00327 ArrayFree( $2 );
00328 }
00329 | COORDINATESYSTEM STRING
00330 {
00331 pbrtCoordinateSystem( $2 );
00332 }
00333 | COORDSYSTRANSFORM STRING
00334 {
00335 pbrtCoordSysTransform( $2 );
00336 }
00337 | FILM STRING paramlist
00338 {
00339 ParamSet params;
00340 InitParamSet(params, CPS, CPT, CPA, CPSZ, CPTH);
00341 pbrtFilm($2, params);
00342 FreeArgs();
00343 }
00344 | IDENTITY
00345 {
00346 pbrtIdentity();
00347 }
00348 | LIGHTSOURCE STRING paramlist
00349 {
00350 ParamSet params;
00351 InitParamSet(params, CPS, CPT, CPA, CPSZ, CPTH);
00352 pbrtLightSource($2, params);
00353 FreeArgs();
00354 }
00355 | LOOKAT NUM NUM NUM NUM NUM NUM NUM NUM NUM
00356 {
00357 pbrtLookAt($2, $3, $4, $5, $6, $7, $8, $9, $10);
00358 }
00359 | MATERIAL STRING paramlist
00360 {
00361 ParamSet params;
00362 InitParamSet(params, CPS, CPT, CPA, CPSZ, CPTH);
00363 pbrtMaterial($2, params);
00364 FreeArgs();
00365 }
00366 | OBJECTBEGIN STRING
00367 {
00368 pbrtObjectBegin($2);
00369 }
00370 | OBJECTEND
00371 {
00372 pbrtObjectEnd();
00373 }
00374 | OBJECTINSTANCE STRING
00375 {
00376 pbrtObjectInstance($2);
00377 }
00378 | PIXELFILTER STRING paramlist
00379 {
00380 ParamSet params;
00381 InitParamSet(params, CPS, CPT, CPA, CPSZ, CPTH);
00382 pbrtPixelFilter($2, params);
00383 FreeArgs();
00384 }
00385 | REVERSEORIENTATION
00386 {
00387 pbrtReverseOrientation();
00388 }
00389 | ROTATE NUM NUM NUM NUM
00390 {
00391 pbrtRotate($2, $3, $4, $5);
00392 }
00393 | SAMPLER STRING paramlist
00394 {
00395 ParamSet params;
00396 InitParamSet(params, CPS, CPT, CPA, CPSZ, CPTH);
00397 pbrtSampler($2, params);
00398 FreeArgs();
00399 }
00400 | SCALE NUM NUM NUM
00401 {
00402 pbrtScale($2, $3, $4);
00403 }
00404 | SEARCHPATH STRING
00405 {
00406 pbrtSearchPath($2);
00407 }
00408 | SHAPE STRING paramlist
00409 {
00410 ParamSet params;
00411 InitParamSet(params, CPS, CPT, CPA, CPSZ, CPTH);
00412 pbrtShape($2, params);
00413 FreeArgs();
00414 }
00415 | SURFACEINTEGRATOR STRING paramlist
00416 {
00417 ParamSet params;
00418 InitParamSet(params, CPS, CPT, CPA, CPSZ, CPTH);
00419 pbrtSurfaceIntegrator($2, params);
00420 FreeArgs();
00421 }
00422 | TEXTURE STRING STRING STRING paramlist
00423 {
00424 ParamSet params;
00425 InitParamSet(params, CPS, CPT, CPA, CPSZ, CPTH);
00426 pbrtTexture($2, $3, $4, params);
00427 FreeArgs();
00428 }
00429 | TRANSFORMBEGIN
00430 {
00431 pbrtTransformBegin();
00432 }
00433 | TRANSFORMEND
00434 {
00435 pbrtTransformEnd();
00436 }
00437 | TRANSFORM real_num_array
00438 {
00439 if (VerifyArrayLength( $2, 16, "Transform" ))
00440 pbrtTransform( (float *) $2->array );
00441 ArrayFree( $2 );
00442 }
00443 | TRANSLATE NUM NUM NUM
00444 {
00445 pbrtTranslate($2, $3, $4);
00446 }
00447 | VOLUMEINTEGRATOR STRING paramlist
00448 {
00449 ParamSet params;
00450 InitParamSet(params, CPS, CPT, CPA, CPSZ, CPTH);
00451 pbrtVolumeIntegrator($2, params);
00452 FreeArgs();
00453 }
00454 | VOLUME STRING paramlist
00455 {
00456 ParamSet params;
00457 InitParamSet(params, CPS, CPT, CPA, CPSZ, CPTH);
00458 pbrtVolume($2, params);
00459 FreeArgs();
00460 }
00461 | WORLDBEGIN
00462 {
00463 pbrtWorldBegin();
00464 }
00465 | WORLDEND
00466 {
00467 pbrtWorldEnd();
00468 };
00469 %%
00470 static void InitParamSet(ParamSet &ps, int count, const char **tokens,
00471 void **args, int *sizes, bool *texture_helper) {
00472 ps.Clear();
00473 for (int i = 0; i < count; ++i) {
00474 int type;
00475 string name;
00476 if (lookupType(tokens[i], &type, name)) {
00477 if (texture_helper && texture_helper[i] && type != PARAM_TYPE_TEXTURE && type != PARAM_TYPE_STRING)
00478 {
00479 Warning( "Bad type for %s. Changing it to a texture.", name.c_str());
00480 type = PARAM_TYPE_TEXTURE;
00481 }
00482 void *data = args[i];
00483 int nItems = sizes[i];
00484 if (type == PARAM_TYPE_INT) {
00485
00486 int nAlloc = sizes[i];
00487 int *idata = new int[nAlloc];
00488 float *fdata = (float *)data;
00489 for (int j = 0; j < nAlloc; ++j)
00490 idata[j] = int(fdata[j]);
00491 ps.AddInt(name, idata, nItems);
00492 delete[] idata;
00493 }
00494 else if (type == PARAM_TYPE_BOOL) {
00495
00496 int nAlloc = sizes[i];
00497 bool *bdata = new bool[nAlloc];
00498 for (int j = 0; j < nAlloc; ++j) {
00499 string s(*((const char **)data));
00500 if (s == "true") bdata[j] = true;
00501 else if (s == "false") bdata[j] = false;
00502 else {
00503 Warning("Value \"%s\" unknown for boolean parameter \"%s\"."
00504 "Using \"false\".", s.c_str(), tokens[i]);
00505 bdata[j] = false;
00506 }
00507 }
00508 ps.AddBool(name, bdata, nItems);
00509 delete[] bdata;
00510 }
00511 else if (type == PARAM_TYPE_FLOAT) {
00512 ps.AddFloat(name, (float *)data, nItems);
00513 } else if (type == PARAM_TYPE_POINT) {
00514 ps.AddPoint(name, (Point *)data, nItems / 3);
00515 } else if (type == PARAM_TYPE_VECTOR) {
00516 ps.AddVector(name, (Vector *)data, nItems / 3);
00517 } else if (type == PARAM_TYPE_NORMAL) {
00518 ps.AddNormal(name, (Normal *)data, nItems / 3);
00519 } else if (type == PARAM_TYPE_COLOR) {
00520 ps.AddSpectrum(name, (Spectrum *)data, nItems / COLOR_SAMPLES);
00521 } else if (type == PARAM_TYPE_STRING) {
00522 string *strings = new string[nItems];
00523 for (int j = 0; j < nItems; ++j)
00524 strings[j] = string(*((const char **)data+j));
00525 ps.AddString(name, strings, nItems);
00526 delete[] strings;
00527 }
00528 else if (type == PARAM_TYPE_TEXTURE) {
00529 if (nItems == 1) {
00530 string val(*((const char **)data));
00531 ps.AddTexture(name, val);
00532 }
00533 else
00534 Error("Only one string allowed for \"texture\" parameter \"%s\"",
00535 name.c_str());
00536 }
00537 }
00538 else
00539 Warning("Type of parameter \"%s\" is unknown",
00540 tokens[i]);
00541 }
00542 }
00543 static bool lookupType(const char *token, int *type, string &name) {
00544 Assert(token != NULL);
00545 *type = 0;
00546 const char *strp = token;
00547 while (*strp && isspace(*strp))
00548 ++strp;
00549 if (!*strp) {
00550 Error("Parameter \"%s\" doesn't have a type declaration?!", token);
00551 return false;
00552 }
00553 #define TRY_DECODING_TYPE(name, mask) \
00554 if (strncmp(name, strp, strlen(name)) == 0) { \
00555 *type = mask; strp += strlen(name); \
00556 }
00557 TRY_DECODING_TYPE("float", PARAM_TYPE_FLOAT)
00558 else TRY_DECODING_TYPE("integer", PARAM_TYPE_INT)
00559 else TRY_DECODING_TYPE("bool", PARAM_TYPE_BOOL)
00560 else TRY_DECODING_TYPE("point", PARAM_TYPE_POINT)
00561 else TRY_DECODING_TYPE("vector", PARAM_TYPE_VECTOR)
00562 else TRY_DECODING_TYPE("normal", PARAM_TYPE_NORMAL)
00563 else TRY_DECODING_TYPE("string", PARAM_TYPE_STRING)
00564 else TRY_DECODING_TYPE("texture", PARAM_TYPE_TEXTURE)
00565 else TRY_DECODING_TYPE("color", PARAM_TYPE_COLOR)
00566 else {
00567 Error("Unable to decode type for token \"%s\"", token);
00568 return false;
00569 }
00570 while (*strp && isspace(*strp))
00571 ++strp;
00572 name = string(strp);
00573 return true;
00574 }