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