Rez: switch

This commit is contained in:
Wolfgang Thaller 2014-10-08 01:17:17 +02:00
parent a02d56ba1c
commit 399131a8a6
6 changed files with 68 additions and 5 deletions

View File

@ -125,3 +125,9 @@ int IdentifierExpr::evaluateInt(ResourceCompiler *ctx)
return val->evaluateInt(ctx);
}
}
CaseExpr::CaseExpr(const std::string &tag, CompoundExprPtr expr)
: tag(tag), expr(expr)
{
}

View File

@ -9,9 +9,11 @@ class ResourceCompiler;
class Expression;
class CompoundExpr;
class IdentifierExpr;
class CaseExpr;
typedef std::shared_ptr<Expression> ExprPtr;
typedef std::shared_ptr<CompoundExpr> CompoundExprPtr;
typedef std::shared_ptr<IdentifierExpr> IdentifierExprPtr;
typedef std::shared_ptr<CaseExpr> CaseExprPtr;
enum class BinaryOp
@ -64,6 +66,15 @@ public:
~CompoundExpr();
};
class CaseExpr : public Expression
{
std::string tag;
CompoundExprPtr expr;
friend class SwitchField;
public:
CaseExpr(const std::string& tag, CompoundExprPtr expr);
};
class BinaryExpr : public Expression
{
BinaryOp op;

View File

@ -181,3 +181,20 @@ void LabelField::compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass)
{
compiler->defineLabel(name);
}
void SwitchField::addCase(const std::string name, FieldListPtr alternative)
{
cases[name] = alternative;
}
void SwitchField::compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass)
{
CaseExprPtr caseExpr = std::dynamic_pointer_cast<CaseExpr>(expr);
assert(caseExpr);
FieldListPtr caseDefinition = cases[caseExpr->tag];
assert(caseDefinition);
caseDefinition->compile(caseExpr->expr, compiler, prePass);
}

View File

@ -137,6 +137,16 @@ public:
};
typedef std::shared_ptr<ArrayField> ArrayFieldPtr;
class SwitchField : public Field
{
std::map<std::string, FieldListPtr> cases;
public:
void addCase(const std::string name, FieldListPtr alternative);
virtual void compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass);
};
typedef std::shared_ptr<SwitchField> SwitchFieldPtr;
class TypeDefinition : public FieldList
{
};

View File

@ -157,7 +157,7 @@ field_definitions : %empty
%type <FieldPtr> field_definition;
field_definition: simple_field_definition { $$ = $1; }
| array_definition { $$ = $1; }
| switch_definition { $$ = nullptr; }
| switch_definition { $$ = $1; }
| fill_statement { $$ = nullptr; }
| align_statement { $$ = nullptr; }
;
@ -240,13 +240,31 @@ field_attribute : "hex" { $$ = SimpleField::Attrs::hex; }
| "literal" { $$ = SimpleField::Attrs::literal; }
;
switch_definition: "switch" "{"
%type <FieldPtr> switch_definition;
switch_definition:
"switch"
{ world.switches.push(std::make_shared<SwitchField>()); }
"{"
switch_cases
"}" ;
"}"
{
$$ = world.switches.top();
world.switches.pop();
}
;
switch_cases : %empty | switch_cases switch_case ;
switch_case : "case" IDENTIFIER ":" field_definitions ;
switch_case : "case" IDENTIFIER ":"
{
world.fieldLists.push(std::make_shared<FieldList>());
}
field_definitions
{
world.switches.top()->addCase($IDENTIFIER, world.fieldLists.top());
world.fieldLists.pop();
}
;
value : expression { $$ = $1; }
| "{" resource_body "}" { $$ = $2; }
@ -340,7 +358,7 @@ resource_body1 : resource_item { $$ = std::make_shared<CompoundExpr>(); $$->addI
;
resource_item : value { $$ = $1; }
| IDENTIFIER "{" resource_body "}" // ###
| IDENTIFIER "{" resource_body "}" { $$ = std::make_shared<CaseExpr>($IDENTIFIER, $resource_body); }
;
%%

View File

@ -13,6 +13,7 @@ class RezWorld
std::map<TypeSpec, TypeDefinitionPtr> types;
std::stack<FieldListPtr> fieldLists;
std::stack<IdentifierExprPtr> functionCalls;
std::stack<SwitchFieldPtr> switches;
public:
RezWorld();
void addTypeDefinition(TypeSpec spec, TypeDefinitionPtr type);