home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Photo CD Demo 1
/
Demo.bin
/
graphtal
/
yacc.y
< prev
next >
Wrap
Text File
|
1992-11-02
|
22KB
|
835 lines
%{
/*
* yacc.y - parser for graphtal.
*
* Copyright (C) 1992, Christoph Streit (streit@iam.unibe.ch)
* All rights reserved.
*
* This software may be freely copied, modified, and redistributed
* provided that this copyright notice is preserved on all copies.
*
* You may not distribute this software, in whole or in part, as part of
* any commercial product without the express consent of the authors.
*
* There is no warranty or other guarantee of fitness of this software
* for any purpose. It is provided solely "as is".
*
*/
// #ifdef _AIX
// #pragma alloca
// # include <malloc.h>
// # include <unistd.h>
// #else
# include <unistd.h>
# ifndef alloca
# include <malloc.h>
# ifndef alloca
# define alloca
# endif
# endif
// #endif
#include <stdlib.h>
#include <iostream.h>
#include "yyerror.h"
#include "rcString.h"
#include "LSystem.h"
#include "Expression.h"
#include "ExprItems.h"
#include "table.h"
#include "Color.h"
#include "Options.h"
#include "Primitives.h"
#include "Hull.h"
#include "Interpreter.h"
extern int yylex();
LSystem* lsystem = NULL;
declareTable(ExprSymtab, rcString, ExpressionPtr);
implementTable(ExprSymtab, rcString, ExpressionPtr);
declareTable(IntSymtab, rcString, int);
implementTable(IntSymtab, rcString, int);
declareTable(TableSymtab, rcString, TablePtr)
implementTable(TableSymtab, rcString, TablePtr)
static ExprSymtab GlobalConst(503);
static ExprSymtab* LocalConst = new ExprSymtab(503);
static IntSymtab* FormalParam = new IntSymtab(17);
static HullSymtab* theHulls = new HullSymtab(17);
static TableSymtab theTables(17);
static int definingLocalConst = 0;
static int nthParam = 0;
static ProdModuleList* axiom = NULL;
static DerivationList* derivation = NULL;
%}
%union { double realnumber;
int intnumber;
Vector* vector;
TransMatrix* trans;
GeoObject* geoObject;
Hull* hull;
DerivationList* derivations;
TableList* table_list;
Table* table;
ProductionList* prod_list;
Production* production;
Predecessor* predecessor;
NameList* name_list;
SuccessorList* succ_list;
Successor* successor;
ProdModuleList* module_list;
ProdModule* module;
ExpressionList* expr_list;
Expression* expr;
Value* value;
rcString* name;
};
%type <realnumber> number
%type <vector> vector
%type <trans> transforms transformation
%type <hull> primitives
%type <geoObject> primitive
%type <derivations> derivations
%type <table_list> tables
%type <table> table
%type <prod_list> productions
%type <production> production
%type <predecessor> predecessor
%type <succ_list> successors
%type <successor> successor
%type <module_list> modules
%type <module> module
%type <name_list> arguments parameters
%type <name> name
%type <expr_list> expr_list
%type <expr> expression condition no_argument one_argument
%type <realnumber> probability
%type <intnumber> steps
%token <value> tVALUE
%token <name> tNAME
%token <name> tCONSTANT
%token tLSYSTEM tTABLE tCONST
%token tATTRIBUTES tDERIVATION tAXIOM tPITCH tROLL tTURN tANGLE
%token tFORWARD tRANDOMIZE tINFINITY tTROPISM tWEIGHT
%token tEYE tLOOKAT tUP tFOV
%token tCONERES tSPHERERES
%token tHULL tSPHERE tTRIANGLE tPLANE tCYLINDER tCONE
%token tTRANSLATE tROTATE tSCALE tTRANSFORM
%token tSIN tCOS tTAN tASIN tACOS tATAN tABS tSQRT tEXP tLOG tLOG10 tRAND
%token tGAUSS
%token tIF tTURTLEX tTURTLEY tTURTLEZ
%token tSCOPE /* :: */
%token tAND /* && */
%token tOR /* || */
%token '!'
%token tEQ /* == */
%token tNEQ /* != */
%token tGEQ /* >= */
%token tLEQ /* <= */
%token '<'
%token '>'
%token tARROW /* -> */
%token tPOW /* ** */
%token '+' '-' '*' '/' '%' '^'
%left tOR
%left tAND
%nonassoc tNEQ tEQ
%nonassoc tGEQ tLEQ '<' '>'
%left '+' '-'
%left '*' '/' '%'
%left tUMINUS '!'
%right tPOW '^'
%left tSCOPE
%%
lgrammar : tLSYSTEM tNAME sc
global_const hulls tables attributes
{
if (!axiom)
yyerror("no axiom defined");
if (!derivation)
yyerror("no derivation list defined");
lsystem = new LSystem(Name($2), $6, axiom, derivation);
theOptions.hulls = theHulls;
delete $2;
}
;
global_const : constant_def
{ definingLocalConst = 1; }
;
constant_def : /* empty */
| tCONST constants
;
constants : constant
| constants constant
;
constant : tCONSTANT '=' expression sc
{
if (definingLocalConst) {
if (!LocalConst->insert(*$1, $3->simplify()))
yyerror("Constant " + *$1 + " already defined");
}
else {
if (!GlobalConst.insert(*$1, $3->simplify()))
yyerror("Constant " + *$1 + " already defined");
}
delete $1;
}
;
hulls : /* empty */
| hulls hull
;
hull : tHULL tNAME '{' primitives '}' sc
{
if (!theHulls->insert(*$2, $4))
yyerror("hull " + *$2 + " already defined");
delete $2;
}
;
primitives : primitive
{
$$ = new Hull;
$$->addPrimitive($1);
}
| primitive transforms
{
if (!$1->setTransform($2))
yyerror("singular matrix");
$$ = new Hull;
$$->addPrimitive($1);
}
| primitives primitive
{
$$ = $1;
$$->addPrimitive($2);
}
| primitives primitive transforms
{
if (!$2->setTransform($3))
yyerror("singular matrix");
$$ = $1;
$$->addPrimitive($2);
}
;
primitive : tSPHERE number vector
{
if (($$ = Sphere::create($2, *$3)) == NULL)
yyerror("degenerate sphere");
delete $3;
}
| tTRIANGLE vector vector vector
{
if (($$ = Triangle::create(*$2, *$3, *$4)) == NULL)
yyerror("degenerate triangle");
delete $2;
delete $3;
delete $4;
}
| tPLANE vector vector
{
if (($$ = Plane::create(*$2, *$3)) == NULL)
yyerror("degenerate plane normal");
delete $2;
delete $3;
}
| tCYLINDER number vector vector
{
if (($$ = Cylinder::create($2, *$3, *$4)) == NULL)
yyerror("degenerate cylinder");
delete $3;
delete $4;
}
| tCONE number vector number vector
{
if (($$ = Cone::create($2, *$3, $4, *$5)) == NULL)
yyerror("degenerate cone");
delete $3;
delete $5;
}
;
vector : number number number
{
$$ = new Vector($1, $2, $3);
}
;
number : tVALUE
{
$$ = *$1;
delete $1;
}
| '-' tVALUE
{
$$ = *$2;
$$ = -$$;
delete $2;
}
| '+' tVALUE
{
$$ = *$2;
delete $2;
}
| tNAME
{
Expression *expr;
if (!GlobalConst.lookup(*$1, expr))
yyerror(*$1 + " unknown");
else
$$ = expr->evaluate();
delete $1;
}
;
transforms : transformation
{
$$ = $1;
}
| transforms transformation
{
(*$1) *= (*$2);
$$ = $1;
delete $2;
}
;
transformation : tTRANSLATE vector
{
$$ = new TransMatrix;
$$->translate(*$2);
delete $2;
}
| tSCALE number number number
{
$$ = new TransMatrix;
$$->scale($2, $3, $4);
}
| tROTATE vector number
{
$$ = new TransMatrix;
$$->rotate(*$2, dtor($3));
delete $2;
}
| tTRANSFORM vector vector vector
{
$$ = new TransMatrix(*$2, *$3, *$4);
delete $2;
delete $3;
delete $4;
}
| tTRANSFORM vector vector vector vector
{
$$ = new TransMatrix(*$2, *$3, *$4, *$5);
delete $2;
delete $3;
delete $4;
delete $5;
}
;
tables : table
{
$$ = new TableList(1);
$$->append($1);
}
| tables table
{
$$ = $1;
$$->append($2);
}
;
table : tTABLE tNAME '{' constant_def productions '}' sc
{
Table *table = new Table(Name($2), $5);
if (!theTables.insert(*$2, table))
yyerror("Table " + *$2 + " already defined");
else {
// delete current local constants
delete LocalConst;
LocalConst = new ExprSymtab(503);
$$ = table;
}
delete $2;
}
;
productions : production
{
nthParam = 0;
$$ = new ProductionList;
$$->append($1);
}
| productions production
{
nthParam = 0;
$$ = $1;
$$->append($2);
}
;
production : predecessor successors sc
{
$$ = new Production($1, NULL, $2);
if ($$->cumulateProbability())
yyerror("Sum of production probabilities is > 1");
delete FormalParam;
FormalParam = new IntSymtab(17);
}
| predecessor condition successors sc
{
$$ = new Production($1, $2, $3);
if ($$->cumulateProbability())
yyerror("Sum of production probabilities is > 1");
delete FormalParam;
FormalParam = new IntSymtab(17);
}
;
predecessor : name
{
$$ = new Predecessor(Name($1), NULL);
delete $1;
}
| name arguments
{
$$ = new Predecessor(Name($1), $2);
delete $1;
}
;
name : '{'
{ $$ = new rcString("{"); }
| '}'
{ $$ = new rcString("}"); }
| '['
{ $$ = new rcString("["); }
| ']'
{ $$ = new rcString("]"); }
| '^'
{ $$ = new rcString("^"); }
| '&'
{ $$ = new rcString("&"); }
| '+'
{ $$ = new rcString("+"); }
| '-'
{ $$ = new rcString("-"); }
| '\\'
{ $$ = new rcString("\\"); }
| '/'
{ $$ = new rcString("/"); }
| '|'
{ $$ = new rcString("|"); }
| '$'
{ $$ = new rcString("$"); }
| '.'
{ $$ = new rcString("."); }
| '%'
{ $$ = new rcString("~"); }
| tNAME
{ $$ = $1; }
;
arguments : '(' parameters rp
{ $$ = $2; }
;
parameters : tNAME
{
$$ = new NameList(1);
$$->append(new Name($1));
if (!FormalParam->insert(*$1, nthParam++))
yyerror("Parameter " + *$1 + " already used");
delete $1;
}
| parameters ',' tNAME
{
$$ = $1;
$$->append(new Name($3));
if (!FormalParam->insert(*$3, nthParam++))
yyerror("Parameter " + *$3 + " already used");
delete $3;
}
;
condition : ':' expression
{ $$ = $2->simplify(); }
;
successors : successor
{
$$ = new SuccessorList(1);
$$->append($1);
}
| successors successor
{
$$ = $1;
$$->append($2);
}
;
successor : tARROW probability modules
{
$$ = new Successor($2, $3);
}
| tARROW probability
{
$$ = new Successor($2, NULL);
}
;
probability : /* empty */ { $$ = 1.0; }
| '(' tVALUE ')' { $$ = *$2;
delete $2;
}
;
modules : module
{
$$ = new ProdModuleList(1);
$$->append($1);
}
| modules module
{
$$ = $1;
$$->append($2);
}
;
module : name
{
$$ = new ProdModule(Name($1), NULL);
delete $1;
}
| name '(' expr_list rp
{
$$ = new ProdModule(Name($1), $3);
delete $1;
}
;
expr_list : expression
{
$$ = new ExpressionList(1);
$$->append($1->simplify());
}
| expr_list ',' expression
{
$1->append($3->simplify());
$$ = $1;
}
;
expression : tVALUE { $$ = new Expression(new ValueItem($1));
delete $1;
}
| tTURTLEX
{ $$ = new Expression(new Variable(Name("tx"),
Interpreter::getTx()));
}
| tTURTLEY
{ $$ = new Expression(new Variable(Name("ty"),
Interpreter::getTy())); }
| tTURTLEZ
{ $$ = new Expression(new Variable(Name("tz"),
Interpreter::getTz())); }
| tNAME
{ Expression *expr;
int nth;
// a formal parameter, local or global constant ?
if (!FormalParam->lookup(*$1, nth)) {
if (!LocalConst->lookup(*$1, expr)) {
if (!GlobalConst.lookup(*$1, expr))
yyerror("`" + *$1 + "' unknown");
else
$$ = new Expression(*expr);
}
else
$$ = new Expression(*expr);
}
else
$$ = new Expression(new Variable(Name($1),
Formals(nth)));
delete $1;
}
| tSCOPE tNAME
{
Expression *expr;
if (!GlobalConst.lookup(*$2, expr))
yyerror("::" + *$2 + " unknown");
else
$$ = new Expression(*expr);
delete $2;
}
| expression tOR expression
{ $$ = new Expression(new Or, $1, $3); }
| expression tAND expression
{ $$ = new Expression(new And, $1, $3); }
| expression tEQ expression
{ $$ = new Expression(new Eq, $1, $3); }
| expression tNEQ expression
{ $$ = new Expression(new Neq, $1, $3); }
| expression tGEQ expression
{ $$ = new Expression(new Geq, $1, $3); }
| expression tLEQ expression
{ $$ = new Expression(new Leq, $1, $3); }
| expression '>' expression
{ $$ = new Expression(new Gt, $1, $3); }
| expression '<' expression
{ $$ = new Expression(new Lt, $1, $3); }
| '!' expression
{ $$ = new Expression(new Not, $2); }
| expression '+' expression
{ $$ = new Expression(new Add, $1, $3); }
| expression '-' expression
{ $$ = new Expression(new Sub, $1, $3); }
| expression '*' expression
{ $$ = new Expression(new Mul, $1, $3); }
| expression '/' expression
{ $$ = new Expression(new Div, $1, $3); }
| expression '%' expression
{ $$ = new Expression(new Mod, $1, $3); }
| expression tPOW expression
{ $$ = new Expression(new Pow, $1, $3); }
| expression '^' expression
{ $$ = new Expression(new Pow, $1, $3); }
| '-' expression %prec tUMINUS
{ $$ = new Expression(new Uminus, $2); }
| tSIN one_argument
{ $$ = new Expression(new Sin, $2); }
| tCOS one_argument
{ $$ = new Expression(new Cos, $2); }
| tTAN one_argument
{ $$ = new Expression(new Tan, $2); }
| tASIN one_argument
{ $$ = new Expression(new Asin, $2); }
| tACOS one_argument
{ $$ = new Expression(new Acos, $2); }
| tATAN one_argument
{ $$ = new Expression(new Atan, $2); }
| tABS one_argument
{ $$ = new Expression(new Abs, $2); }
| tSQRT one_argument
{ $$ = new Expression(new Sqrt, $2); }
| tEXP one_argument
{ $$ = new Expression(new Exp, $2); }
| tLOG one_argument
{ $$ = new Expression(new Log, $2); }
| tLOG10 one_argument
{ $$ = new Expression(new Log, $2); }
| tRAND no_argument
{ $$ = new Expression(new Rand); }
| tGAUSS no_argument
{ $$ = new Expression(new Gauss); }
| tIF '(' expression ',' expression ',' expression rp
{ $$ = new Expression(new If, $3, $5, $7); }
| tNAME no_argument
{
yyerror("Function " + *$1 + "() unknown");
}
| tNAME '(' expr_list rp
{
yyerror("Function " + *$1 + "(arguments) unknown");
}
| '(' expression rp
{ $$ = $2; }
;
no_argument : '(' rp
{ $$ = NULL; }
;
one_argument : '(' expression rp
{ $$ = $2->simplify(); }
;
attributes : tATTRIBUTES '{' attr_list '}' sc
;
attr_list : /* empty */
| attr_list attr_item
;
attr_item : tDERIVATION derivations sc
{ derivation = $2; }
| tAXIOM modules sc
{ axiom = $2; }
| tPITCH expression sc
{
theOptions.defaultPitch = dtor($2->evaluate());
delete $2;
}
| tROLL expression sc
{ theOptions.defaultRoll = dtor($2->evaluate());
delete $2;
}
| tTURN expression sc
{
theOptions.defaultTurn = dtor($2->evaluate());
delete $2;
}
| tANGLE expression sc
{
theOptions.defaultPitch =
theOptions.defaultRoll =
theOptions.defaultTurn = dtor($2->evaluate());
delete $2;
}
| tFORWARD expression sc
{
theOptions.defaultForward = $2->evaluate();
delete $2;
}
| tRANDOMIZE sc
{
long now;
// #if defined(_AIX)
// stime(&now);
//#elif defined(__DECCXX)
#if defined(__DECCXX)
now = getpid();
#else
time(&now);
#endif
if (theOptions.verbose)
cerr << "randomize " << now << "\n";
srand48(now);
}
| tRANDOMIZE expression sc
{
srand48((long)$2->evaluate());
delete $2;
}
| tTROPISM expression ',' expression ',' expression sc
{
theOptions.tropismX = $2->simplify();
theOptions.tropismY = $4->simplify();
theOptions.tropismZ = $6->simplify();
}
| tWEIGHT expression sc
{
theOptions.weight = $2->simplify();
}
| tEYE expression ',' expression ',' expression sc
{
theOptions.autoscale = 0;
theOptions.eye =
Vector($2->evaluate(), $4->evaluate(), $6->evaluate());
delete $2; delete $4; delete $6;
}
| tLOOKAT expression ',' expression ',' expression sc
{
theOptions.autoscale = 0;
theOptions.lookat =
Vector($2->evaluate(), $4->evaluate(), $6->evaluate());
delete $2; delete $4; delete $6;
}
| tUP expression ',' expression ',' expression sc
{
theOptions.up =
Vector($2->evaluate(), $4->evaluate(), $6->evaluate());
delete $2; delete $4; delete $6;
}
| tFOV expression sc
{
theOptions.fov = $2->evaluate();
delete $2;
}
| tCONERES tVALUE sc
{
theOptions.coneResolution = (int) *$2;
delete $2;
}
| tSPHERERES tVALUE sc
{
theOptions.sphereResolution = (int) *$2;
delete $2;
}
;
derivations : tNAME steps
{ Table *t;
if (!theTables.lookup(*$1, t))
yyerror("Unknown table " + *$1);
else {
$$ = new DerivationList(1);
$$->append(new DerivationItem(t,$2));
}
delete $1;
}
| derivations ',' tNAME steps
{ Table *t;
$$ = $1;
if (!theTables.lookup(*$3, t))
yyerror("Unknown table " + *$3);
else
$$->append(new DerivationItem(t,$4));
delete $3;
}
;
steps : /* empty */
{ $$ = 1; }
| '(' expression rp
{ $$ = (int) real($2->evaluate());
delete $2;
}
| '(' tINFINITY rp
{ $$ = -1; }
;
sc : ';' { yyerrok; } ;
rp : ')' { yyerrok; } ;
%%