Wednesday, August 21, 2013

Express yourself, August 21, 2013

Today has been off to a slow start.  Mostly it has been reading a bunch of lighting papers and experimenting with an expression parser.

Oh, and I made a RenderCubeComponent to complement the RenderSphereComponent from yesterday (settle down, let's not get too excited).

I've been missing having a good expression parser, particularly with the heavily data-driven design I'm going with right now.  I noticed that after doing all of the shader constant binding stuff yesterday that I need to specify that certain shader constants are bound to things that aren't actually constant (say, the camera View transform, for example).

I was using Lua to do expression parsing type things, but... let's say I've fallen out of love with Lua.  It's a cute language, but I found it was taking a lot of effort to bind everything to Lua, and ultimatley the lack of strict type checking meant that nothing ever worked the first time.  Ever.  With C++, if it compiles, at least you stand a fair chance of finding out you're an idiot before running the game it working.

So, I've been spending the day trying to write a good expression parser.  I want to basically just use a parse tree rather than some bytecode compiled thing.  That basically means that you have a base class that looks something like:

class cExpr
{
public:
    virtual void Eval(cResult &result) = 0;
};


and then a bunch of values or operators that derive from that:

class cBinOp : public cExpr
{
public:
    cBinOp(cExpr *lhs, cExpr *rhs) : mLHS(lhs), mRHS(rhs) { }
    cExpr *mLHS;
    cExpr *mRHS;
};


class cMulOp : public cBinOp
{
public:
    cMulOp(cExpr *lhs, cExpr *rhs) : cBinOp(lhs, rhs) { }
    virtual void Eval(cResult &result) { cResult lhs; cResult rhs; mLHS->Eval(lhs); mRHS->Eval(rhs); result = lhs * rhs; }
};


OK, the details are bit more complex than that, particularly when you're talking about multiple types, and especially if you want to do any sort of assignment operations.  But basically, once you've built a whole tree of operations, you just do one function call, a bunch of virtual function calls happen, and you get a result.

This can be expanded to execute a full language by making loop and flow control nodes as well - I'm not going to be doing that today.

No comments:

Post a Comment