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