added function calls to scene files

git-svn-id: svn://anubis/fart/trunk@361 7f9b0f55-74a9-4bce-be96-3c2cd072584d
This commit is contained in:
Josh Holtrop 2010-10-07 18:53:42 +00:00
parent eca2335fb2
commit 654be9058d
4 changed files with 136 additions and 1 deletions

View File

@ -1,14 +1,53 @@
#include <stdlib.h> #include <stdlib.h>
#include <math.h>
#include <vector> #include <vector>
#include <iostream> #include <iostream>
#include <typeinfo> #include <typeinfo>
#include <map>
#include "nodes.h" #include "nodes.h"
using namespace std; using namespace std;
typedef NodeRef (*Function)(NodeRef args);
NodeRef CosFunction(NodeRef args);
NodeRef SinFunction(NodeRef args);
NodeRef SqrtFunction(NodeRef args);
NodeRef AbsFunction(NodeRef args);
static const struct {
const char * fn_name;
Function fn;
} functions[] = {
{"cos", CosFunction},
{"sin", SinFunction},
{"sqrt", SqrtFunction},
{"abs", AbsFunction}
};
class FunctionMap : public map<string, Function>
{
public:
FunctionMap()
{
for (unsigned int i = 0;
i < sizeof(functions)/sizeof(functions[0]);
i++)
{
(*this)[functions[i].fn_name] = functions[i].fn;
}
}
bool contains(const string & key)
{
return find(key) != end();
}
};
static FunctionMap function_map;
void Node::evaluateChildren(refptr<Node> parent) void Node::evaluateChildren(refptr<Node> parent)
{ {
/* recursively evaluate all children nodes */ /* recursively evaluate all children nodes */
@ -169,3 +208,59 @@ NodeRef ElseNode::evaluate()
evaluateChildren(eval); evaluateChildren(eval);
return eval; return eval;
} }
NodeRef FunctionCallNode::evaluate()
{
if (function_map.contains(m_name->getString()))
{
return function_map[m_name->getString()](m_parameters);
}
cerr << "Error: no function \"" << m_name->getString() << "\" defined!"
<< endl;
exit(4);
}
/**************************************************************************
* Scene file functions *
*************************************************************************/
NodeRef CosFunction(NodeRef args)
{
if (args->getChildren().size() != 1)
{
cerr << "Error: cos function requires 1 argument" << endl;
exit(4);
}
return new NumberNode(cos(args->getChildren()[0]->evaluate()->getNumber()));
}
NodeRef SinFunction(NodeRef args)
{
if (args->getChildren().size() != 1)
{
cerr << "Error: sin function requires 1 argument" << endl;
exit(4);
}
return new NumberNode(sin(args->getChildren()[0]->evaluate()->getNumber()));
}
NodeRef SqrtFunction(NodeRef args)
{
if (args->getChildren().size() != 1)
{
cerr << "Error: sqrt function requires 1 argument" << endl;
exit(4);
}
return new NumberNode(sqrt(args->getChildren()[0]->evaluate()->getNumber()));
}
NodeRef AbsFunction(NodeRef args)
{
if (args->getChildren().size() != 1)
{
cerr << "Error: abs function requires 1 argument" << endl;
exit(4);
}
return new NumberNode(fabs(args->getChildren()[0]->evaluate()->getNumber()));
}

View File

@ -750,6 +750,19 @@ class ElseNode : public Node
virtual NodeRef evaluate(); virtual NodeRef evaluate();
}; };
class FunctionCallNode : public Node
{
public:
FunctionCallNode(NodeRef name, NodeRef parameters)
{
m_name = name;
m_parameters = parameters;
}
virtual NodeRef evaluate();
protected:
NodeRef m_name, m_parameters;
};
/* this class is only used to hold a set of items coming out of a class's /* this class is only used to hold a set of items coming out of a class's
* evaluate() from above. the evaluateChildren() top-level method will * evaluate() from above. the evaluateChildren() top-level method will
* propagate children of this class up to the level of their parent */ * propagate children of this class up to the level of their parent */

View File

@ -358,6 +358,7 @@ expression: term { $$ = $1; }
$$ = new BinOpNode('-', new NumberNode(0.0), $2); $$ = new BinOpNode('-', new NumberNode(0.0), $2);
} }
| stmt_expression { $$ = $1; } | stmt_expression { $$ = $1; }
| function_call { $$ = $1; }
; ;
maybe_expression: /* empty */ maybe_expression: /* empty */
@ -439,6 +440,28 @@ if_more: /* empty */
$$->addChildren($3); $$->addChildren($3);
} }
; ;
function_call: IDENTIFIER LPAREN function_call_parameters RPAREN {
$$ = new FunctionCallNode($1, $3);
}
;
function_call_parameters: /* empty */
| expression function_call_more_parameters {
$$ = new ItemsNode();
$$->addChild($1);
$$->addChildren($2);
}
;
function_call_more_parameters: /* empty */
| COMMA expression function_call_more_parameters {
$$ = new ItemsNode();
$$->addChild($2);
$$->addChildren($3);
}
;
%% %%
refptr<Node> parse(const char * fileName, refptr<Scope> scope) refptr<Node> parse(const char * fileName, refptr<Scope> scope)

View File

@ -44,7 +44,11 @@ scene
} }
else else
{ {
material mat3 material
{
color <1, 0, 0>
transparency abs($x / 120)
}
} }
} }
$m := $m + 1 $m := $m + 1