string concat, $$read function; make function names keywords

This commit is contained in:
Wolfgang Thaller 2014-10-12 19:16:02 +02:00
parent df0e042120
commit 3aed54a672
4 changed files with 149 additions and 47 deletions

View File

@ -2,6 +2,7 @@
#include "ResourceCompiler.h"
#include <cassert>
#include <iostream>
#include <fstream>
int Expression::evaluateInt(ResourceCompiler *ctx)
{
@ -78,6 +79,21 @@ int BinaryExpr::evaluateInt(ResourceCompiler *ctx)
return a->evaluateInt(ctx) * b->evaluateInt(ctx);
case BinaryOp::DIVIDE:
return a->evaluateInt(ctx) / b->evaluateInt(ctx);
default:
throw TypeError();
break;
}
}
std::string BinaryExpr::evaluateString(ResourceCompiler *ctx)
{
switch(op)
{
case BinaryOp::CONCAT:
return a->evaluateString(ctx) + b->evaluateString(ctx);
default:
throw TypeError();
break;
}
}
@ -98,8 +114,8 @@ int UnaryExpr::evaluateInt(ResourceCompiler *ctx)
}
IdentifierExpr::IdentifierExpr(std::string id, bool isFunction)
: id(id), isFunction(isFunction)
IdentifierExpr::IdentifierExpr(std::string id)
: id(id)
{
}
@ -120,33 +136,11 @@ ExprPtr IdentifierExpr::lookup(ResourceCompiler *ctx)
int IdentifierExpr::evaluateInt(ResourceCompiler *ctx)
{
if(isFunction)
{
if(id == "$$countof" || id == "$$arrayindex")
{
assert(arguments.size() == 1);
IdentifierExprPtr arr = std::dynamic_pointer_cast<IdentifierExpr>(arguments[0]);
assert(arr);
if(id == "$$countof")
return ctx->getArrayCount(arr->id);
else
return ctx->getArrayIndex(arr->id);
}
else
{
std::cout << id << std::endl;
assert(false);
}
}
else
{
return lookup(ctx)->evaluateInt(ctx);
}
return lookup(ctx)->evaluateInt(ctx);
}
std::string IdentifierExpr::evaluateString(ResourceCompiler *ctx)
{
assert(!isFunction);
return lookup(ctx)->evaluateString(ctx);
}
@ -155,3 +149,40 @@ CaseExpr::CaseExpr(const std::string &tag, CompoundExprPtr expr)
: tag(tag), expr(expr)
{
}
int CountOfExpr::evaluateInt(ResourceCompiler *ctx)
{
assert(arg->arguments.size() == 0);
return ctx->getArrayCount(arg->id);
}
int ArrayIndexExpr::evaluateInt(ResourceCompiler *ctx)
{
assert(arg->arguments.size() == 0);
return ctx->getArrayIndex(arg->id);
}
std::string ReadExpr::evaluateString(ResourceCompiler *ctx)
{
std::string filename = arg->evaluateString(ctx);
std::ifstream instream(filename);
// ### TODO: check error
return std::string(std::istreambuf_iterator<char>(instream.rdbuf()),
std::istreambuf_iterator<char>());
}
int UnimplementedExpr::evaluateInt(ResourceCompiler *ctx)
{
std::cerr << msg << std::endl;
return 0;
}
std::string UnimplementedExpr::evaluateString(ResourceCompiler *ctx)
{
std::cerr << msg << std::endl;
return "";
}

View File

@ -18,7 +18,7 @@ typedef std::shared_ptr<CaseExpr> CaseExprPtr;
enum class BinaryOp
{
XOR, OR, AND, SHIFTLEFT, SHIFTRIGHT, EQUAL, NOTEQUAL, PLUS, MINUS, MULTIPLY, DIVIDE
XOR, OR, AND, SHIFTLEFT, SHIFTRIGHT, EQUAL, NOTEQUAL, PLUS, MINUS, MULTIPLY, DIVIDE, CONCAT
};
enum class UnaryOp
@ -87,6 +87,7 @@ public:
~BinaryExpr();
virtual int evaluateInt(ResourceCompiler *ctx);
virtual std::string evaluateString(ResourceCompiler *ctx);
};
class UnaryExpr : public Expression
@ -103,11 +104,10 @@ public:
class IdentifierExpr : public Expression
{
public:
std::string id;
std::vector<ExprPtr> arguments;
bool isFunction;
public:
IdentifierExpr(std::string id, bool isFunction = false);
IdentifierExpr(std::string id);
void addArgument(ExprPtr e);
ExprPtr lookup(ResourceCompiler *ctx);
@ -115,4 +115,38 @@ public:
virtual std::string evaluateString(ResourceCompiler *ctx);
};
class CountOfExpr : public Expression
{
IdentifierExprPtr arg;
public:
CountOfExpr(IdentifierExprPtr arg) : arg(arg) {}
virtual int evaluateInt(ResourceCompiler *ctx);
};
class ArrayIndexExpr : public Expression
{
IdentifierExprPtr arg;
public:
ArrayIndexExpr(IdentifierExprPtr arg) : arg(arg) {}
virtual int evaluateInt(ResourceCompiler *ctx);
};
class ReadExpr : public Expression
{
ExprPtr arg;
public:
ReadExpr(ExprPtr arg) : arg(arg) {}
virtual std::string evaluateString(ResourceCompiler *ctx);
};
class UnimplementedExpr : public Expression
{
std::string msg;
public:
UnimplementedExpr(std::string msg) : msg(msg) {}
virtual int evaluateInt(ResourceCompiler *ctx);
virtual std::string evaluateString(ResourceCompiler *ctx);
};
#endif // EXPRESSION_H

View File

@ -198,7 +198,15 @@ RezSymbol RezLexer::nextToken()
KEYWORD(BITSTRING, "bitstring"),
KEYWORD(INTEGER, "int"),
KEYWORD(DOLLAR, "$")
KEYWORD(DOLLAR, "$"),
KEYWORD(FUN_COUNTOF, "$$countof"),
KEYWORD(FUN_ARRAYINDEX, "$$arrayindex"),
KEYWORD(FUN_READ, "$$read"),
KEYWORD(FUN_BITFIELD, "$$bitfield"),
KEYWORD(FUN_WORD, "$$word"),
KEYWORD(FUN_BYTE, "$$byte"),
KEYWORD(FUN_LONG, "$$long"),
};
std::string s = tok.get_value().c_str();

View File

@ -71,6 +71,14 @@
%token RECT "rect";
%token BITSTRING "bitstring";
%token FUN_COUNTOF "$$countof";
%token FUN_ARRAYINDEX "$$arrayindex";
%token FUN_READ "$$read";
%token FUN_BITFIELD "$$bitfield";
%token FUN_WORD "$$word";
%token FUN_BYTE "$$byte";
%token FUN_LONG "$$long";
/*
%left "|";
%left "^";
@ -309,17 +317,10 @@ switch_case : "case" IDENTIFIER ":"
}
;
%type <std::string> string onestring;
string : onestring { $$ = $1; }
| string onestring { $$ = $1 + $2; }
;
onestring : STRINGLIT { $$ = $1; }
| DOLLAR STRINGLIT { $$ = fromHex($2); }
;
value : expression { $$ = $1; }
| "{" resource_body "}" { $$ = $2; }
| string { $$ = std::make_shared<StringExpr>($1); }
| string_expression { $$ = $1; }
;
expression : expression1 { $$ = $1; }
@ -362,19 +363,31 @@ expression7 : expression8 { $$ = $1; }
expression8 : INTLIT { $$ = std::make_shared<IntExpr>($1); }
| CHARLIT { $$ = std::make_shared<IntExpr>($1); }
| IDENTIFIER { $$ = std::make_shared<IdentifierExpr>($1); }
| IDENTIFIER
{ world.functionCalls.push(std::make_shared<IdentifierExpr>($1,true)); }
"(" function_argument_list ")"
{ $$ = world.functionCalls.top(); world.functionCalls.pop(); }
| IDENTIFIER
{ world.functionCalls.push(std::make_shared<IdentifierExpr>($1,false)); }
"[" function_argument_list1 "]"
{ $$ = world.functionCalls.top(); world.functionCalls.pop(); }
| identifier_expression { $$ = $1; }
| "(" expression ")" { $$ = $2; }
| "$$countof" "(" identifier_expression ")"
{ $$ = std::make_shared<CountOfExpr>($identifier_expression); }
| "$$arrayindex" "(" identifier_expression ")"
{ $$ = std::make_shared<ArrayIndexExpr>($identifier_expression); }
| "$$bitfield" "(" expression "," expression "," expression ")"
{ $$ = std::make_shared<UnimplementedExpr>("$$bitfield"); }
| "$$word" "(" expression ")"
{ $$ = std::make_shared<UnimplementedExpr>("$$word"); }
| "$$byte" "(" expression ")"
{ $$ = std::make_shared<UnimplementedExpr>("$$byte"); }
| "$$long" "(" expression ")"
{ $$ = std::make_shared<UnimplementedExpr>("$$long"); }
;
%type <IdentifierExprPtr> identifier_expression;
identifier_expression : IDENTIFIER { $$ = std::make_shared<IdentifierExpr>($1); }
| IDENTIFIER
{ world.functionCalls.push(std::make_shared<IdentifierExpr>($1)); }
"[" function_argument_list1 "]"
{ $$ = world.functionCalls.top(); world.functionCalls.pop(); }
;
function_argument_list : %empty | function_argument_list1 ;
function_argument_list1 : expression
{ world.functionCalls.top()->addArgument($expression); }
@ -382,6 +395,22 @@ function_argument_list1 : expression
{ world.functionCalls.top()->addArgument($expression); }
;
%type <ExprPtr> string_expression string_expression1;
string_expression : string_expression1 { $$ = $1; }
| string_expression string_expression1
{ $$ = std::make_shared<BinaryExpr>(BinaryOp::CONCAT, $1, $2); }
;
%type <std::string> stringlit;
stringlit : STRINGLIT { $$ = $1; }
| DOLLAR STRINGLIT { $$ = fromHex($2); }
;
string_expression1 : stringlit { $$ = std::make_shared<StringExpr>($1); }
| "$$read" "(" string_expression ")"
{ $$ = std::make_shared<ReadExpr>($string_expression); }
;
resource : "resource" res_type "(" expression resource_attributes ")" "{" resource_body "}"
{
int id = $expression->evaluateInt(nullptr);