diff --git a/Rez/CMakeLists.txt b/Rez/CMakeLists.txt index c5e070d5ca..4b59cb4f7b 100644 --- a/Rez/CMakeLists.txt +++ b/Rez/CMakeLists.txt @@ -44,8 +44,17 @@ add_executable(Rez RezLexerWaveToken.h RezLexerNextToken.cc + RezWorld.cc + RezWorld.h + ResourceDefinitions.cc ResourceDefinitions.h + + Expression.cc + Expression.h + + ResourceCompiler.cc + ResourceCompiler.h ) target_link_libraries(Rez ${Boost_LIBRARIES}) diff --git a/Rez/Expression.cc b/Rez/Expression.cc new file mode 100644 index 0000000000..dfa3208764 --- /dev/null +++ b/Rez/Expression.cc @@ -0,0 +1,87 @@ +#include "Expression.h" + + + +int Expression::evaluateInt(Context *ctx) +{ + throw TypeError(); +} + +Expression::~Expression() +{ +} + + +StringExpr::~StringExpr() +{ +} + + +IntExpr::~IntExpr() +{ +} + +int IntExpr::evaluateInt(Context *ctx) +{ + return val; +} + + +void CompoundExpr::addItem(ExprPtr item) +{ + items.push_back(item); +} + +CompoundExpr::~CompoundExpr() +{ +} + + +BinaryExpr::~BinaryExpr() +{ +} + +int BinaryExpr::evaluateInt(Context *ctx) +{ + switch(op) + { + case BinaryOp::XOR: + return a->evaluateInt(ctx) ^ b->evaluateInt(ctx); + case BinaryOp::OR: + return a->evaluateInt(ctx) | b->evaluateInt(ctx); + case BinaryOp::AND: + return a->evaluateInt(ctx) & b->evaluateInt(ctx); + case BinaryOp::SHIFTLEFT: + return a->evaluateInt(ctx) << b->evaluateInt(ctx); + case BinaryOp::SHIFTRIGHT: + return a->evaluateInt(ctx) >> b->evaluateInt(ctx); + case BinaryOp::EQUAL: + return a->evaluateInt(ctx) == b->evaluateInt(ctx); + case BinaryOp::NOTEQUAL: + return a->evaluateInt(ctx) != b->evaluateInt(ctx); + case BinaryOp::PLUS: + return a->evaluateInt(ctx) + b->evaluateInt(ctx); + case BinaryOp::MINUS: + return a->evaluateInt(ctx) - b->evaluateInt(ctx); + case BinaryOp::MULTIPLY: + return a->evaluateInt(ctx) * b->evaluateInt(ctx); + case BinaryOp::DIVIDE: + return a->evaluateInt(ctx) / b->evaluateInt(ctx); + } +} + + +UnaryExpr::~UnaryExpr() +{ +} + +int UnaryExpr::evaluateInt(Context *ctx) +{ + switch(op) + { + case UnaryOp::MINUS: + return -a->evaluateInt(ctx); + case UnaryOp::COMPLEMENT: + return ~a->evaluateInt(ctx); + } +} diff --git a/Rez/Expression.h b/Rez/Expression.h new file mode 100644 index 0000000000..072b634a82 --- /dev/null +++ b/Rez/Expression.h @@ -0,0 +1,94 @@ +#ifndef EXPRESSION_H +#define EXPRESSION_H + +#include +#include + +class Context +{ + +}; + + + +class Expression; +class CompoundExpr; +typedef std::shared_ptr ExprPtr; +typedef std::shared_ptr CompoundExprPtr; + + +enum class BinaryOp +{ + XOR, OR, AND, SHIFTLEFT, SHIFTRIGHT, EQUAL, NOTEQUAL, PLUS, MINUS, MULTIPLY, DIVIDE +}; + +enum class UnaryOp +{ + MINUS, COMPLEMENT +}; + +class TypeError +{ +}; + +class Expression +{ +public: + virtual int evaluateInt(Context *ctx); + virtual ~Expression(); +}; + +class StringExpr : public Expression +{ + std::string str; +public: + StringExpr(const std::string& str) : str(str) {} + ~StringExpr(); +}; + +class IntExpr : public Expression +{ + int val; +public: + IntExpr(int val) : val(val) {} + ~IntExpr(); + + virtual int evaluateInt(Context *ctx); +}; + +class CompoundExpr : public Expression +{ + std::vector items; +public: + void addItem(ExprPtr item); + ExprPtr getItem(int i) { return items[i]; } + ~CompoundExpr(); +}; + +class BinaryExpr : public Expression +{ + BinaryOp op; + ExprPtr a, b; +public: + BinaryExpr(BinaryOp op, ExprPtr a, ExprPtr b) + : op(op), a(a), b(b) {} + ~BinaryExpr(); + + virtual int evaluateInt(Context *ctx); +}; + +class UnaryExpr : public Expression +{ + UnaryOp op; + ExprPtr a; +public: + UnaryExpr(UnaryOp op, ExprPtr a) + : op(op), a(a) {} + ~UnaryExpr(); + + virtual int evaluateInt(Context *ctx); +}; + + + +#endif // EXPRESSION_H diff --git a/Rez/ResourceCompiler.cc b/Rez/ResourceCompiler.cc new file mode 100644 index 0000000000..533624448f --- /dev/null +++ b/Rez/ResourceCompiler.cc @@ -0,0 +1,11 @@ +#include "ResourceCompiler.h" +#include + +ResourceCompiler::ResourceCompiler() +{ +} + +void ResourceCompiler::write(int nBits, int value) +{ + std::cout << "[" << nBits << " bits] = " << std::hex << value << std::dec << std::endl; +} diff --git a/Rez/ResourceCompiler.h b/Rez/ResourceCompiler.h new file mode 100644 index 0000000000..4523557183 --- /dev/null +++ b/Rez/ResourceCompiler.h @@ -0,0 +1,15 @@ +#ifndef RESOURCECOMPILER_H +#define RESOURCECOMPILER_H + +#include "Expression.h" + +class ResourceCompiler : public Context +{ +public: + ResourceCompiler(); + + void reserve(int nBits) { write(nBits, 0); } + void write(int nBits, int value); +}; + +#endif // RESOURCECOMPILER_H diff --git a/Rez/ResourceDefinitions.cc b/Rez/ResourceDefinitions.cc index 6d0e481485..695419627a 100644 --- a/Rez/ResourceDefinitions.cc +++ b/Rez/ResourceDefinitions.cc @@ -1,11 +1,8 @@ #include "ResourceDefinitions.h" #include +#include -ResourceDefinitions::ResourceDefinitions() -{ -} - - +#include "ResourceCompiler.h" std::ostream &operator<<(std::ostream &out, ResType t) { @@ -25,3 +22,82 @@ std::ostream &operator<<(std::ostream &out, TypeSpec ts) out << " (" << ts.getID() << ")"; return out; } + + +FieldList::~FieldList() +{ + +} + +void FieldList::addField(FieldPtr field) +{ + fields.push_back(field); +} + +void FieldList::addLabel(std::string name) +{ + // ### TODO +} + +void FieldList::compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass) +{ + CompoundExprPtr compound = std::dynamic_pointer_cast(expr); + assert(compound); + + int i = 0; + for(FieldPtr f : fields) + { + if(f->needsValue()) + f->compile(compound->getItem(i++), compiler, prePass); + else + f->compile(nullptr, compiler, prePass); + } +} + + + + +bool SimpleField::needsValue() +{ + return !value; +} + +void SimpleField::compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass) +{ + int bitSize; + + switch(type) + { + case Type::bitstring: + bitSize = arrayCount->evaluateInt(compiler); + break; + case Type::boolean: + bitSize = 1; + break; + case Type::byte: + bitSize = 8; + break; + case Type::integer: + bitSize = 16; + break; + case Type::longint: + bitSize = 32; + break; + } + + int actualValue = 0; + if(!prePass) + { + if(value) + { + actualValue = value->evaluateInt(compiler); + } + else + { + // TODO: add alternatives to context + actualValue = expr->evaluateInt(compiler); + } + } + + compiler->write(bitSize, actualValue); +} diff --git a/Rez/ResourceDefinitions.h b/Rez/ResourceDefinitions.h index 06c239c4e5..a19985b341 100644 --- a/Rez/ResourceDefinitions.h +++ b/Rez/ResourceDefinitions.h @@ -5,6 +5,8 @@ #include #include +#include "Expression.h" + class ResType { int x; @@ -12,6 +14,7 @@ public: ResType() : x(0) {} ResType(int x) : x(x) {} operator int() const { return x; } + bool operator<(ResType y) const { return x < y.x; } }; std::ostream& operator<<(std::ostream& out, ResType t); @@ -31,42 +34,29 @@ public: int getID() const { return id; } bool hasID() const { return id != noID; } + + bool operator<(TypeSpec y) const + { + if(type < y.type) + return true; + else if(y.type < type) + return false; + else + return id < y.id; + } }; std::ostream& operator<<(std::ostream& out, TypeSpec ts); -class Context -{ -}; - -class Expression -{ -public: - //virtual int evaluateInt(Context *ctx); - -}; - -class StringExpr : public Expression -{ - std::string str; -public: - StringExpr(const std::string& str) : str(str) {} -}; - -class IntExpr : public Expression -{ - int val; -public: - IntExpr(int val) : val(val) {} -}; - -typedef std::shared_ptr ExprPtr; +class ResourceCompiler; class Field { public: virtual bool needsValue() { return true; } + + virtual void compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass) = 0; }; typedef std::shared_ptr FieldPtr; @@ -93,6 +83,9 @@ public: void addNamedValue(std::string n) {} void addNamedValue(std::string n, ExprPtr val) {} + + virtual bool needsValue(); + virtual void compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass); }; typedef std::shared_ptr SimpleFieldPtr; @@ -102,11 +95,22 @@ inline SimpleField::Attrs operator|(SimpleField::Attrs a, SimpleField::Attrs b) return SimpleField::Attrs( int(a) | int(b) ); } - -class ResourceDefinitions +class FieldList : public Field { +protected: + std::vector fields; public: - ResourceDefinitions(); + virtual ~FieldList(); + void addField(FieldPtr field); + void addLabel(std::string name); + + virtual void compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass); }; +typedef std::shared_ptr FieldListPtr; + +class TypeDefinition : public FieldList +{ +}; +typedef std::shared_ptr TypeDefinitionPtr; #endif // RESOURCEDEFINITIONS_H diff --git a/Rez/Rez.cc b/Rez/Rez.cc index 91560796d7..ee617ec62d 100644 --- a/Rez/Rez.cc +++ b/Rez/Rez.cc @@ -4,64 +4,15 @@ #include "RezParser.generated.hh" #include "RezLexer.h" - +#include "RezWorld.h" int main() { //RezLexer lexer("/home/wolfgang/Projects/Retro68/RIncludes/Types.r"); RezLexer lexer("/home/wolfgang/Projects/Retro68/Rez/Test.r"); - - RezParser parser(lexer); + RezWorld world; + RezParser parser(lexer, world); parser.parse(); - - /* - // The following preprocesses a given input file. - // Open the file and read it into a string variable - std::ifstream instream("/home/wolfgang/Projects/Retro68/RIncludes/Types.r"); - - std::string input( - std::istreambuf_iterator(instream.rdbuf()), - std::istreambuf_iterator()); - - context_type ctx(input.begin(), input.end(), "Types.r"); - - // At this point you may want to set the parameters of the - // preprocessing as include paths and/or predefined macros. - ctx.add_include_path("/home/wolfgang/Projects/Retro68/RIncludes"); - // ctx.add_macro_definition(...); - - auto first = ctx.begin(); - auto last = ctx.end(); - - std::ostringstream out; - - try - { - while(first != last) - { - out << (*first).get_value(); - ++first; - } - } - catch(boost::wave::preprocess_exception& e) - { - std::cout << e.file_name() << ":" << e.line_no() << ": "; - std::cout << e.description() << std::endl; - } - - std::string str = out.str(); - - - std::cout << str.substr(0,100) << std::endl;*/ - -/* - int i = 0; - while (first != last) { - std::cout << i << ": " << get_token_name(token_id(*first)) << " <<" << (*first).get_value() << ">>\n"; - ++first; - if(++i > 10) - break; - }*/ return 0; } diff --git a/Rez/RezParser.yy b/Rez/RezParser.yy index d8005168ca..c2ec800ff1 100644 --- a/Rez/RezParser.yy +++ b/Rez/RezParser.yy @@ -81,12 +81,15 @@ */ %param { RezLexer& lexer } +%param { RezWorld& world } %code requires { #include "ResourceDefinitions.h" + #include "Expression.h" #define YY_NULLPTR nullptr class RezLexer; + class RezWorld; } %code provides { @@ -103,7 +106,10 @@ %code { #include "RezLexer.h" - static yy::RezParser::symbol_type yylex(RezLexer& lexer) + #include "RezWorld.h" + #include "ResourceCompiler.h" + + static yy::RezParser::symbol_type yylex(RezLexer& lexer, RezWorld&) { return lexer.nextToken(); } @@ -122,9 +128,14 @@ rez : %empty | rez resource ";" ; - -type_definition : "type" type_spec "{" field_definitions "}" - { std::cout << "TYPE " << $2 << std::endl; } +type_definition : "type" type_spec + { + TypeDefinitionPtr td = std::make_shared(); + world.addTypeDefinition($type_spec, td); + world.fieldLists.push(td); + } + "{" field_definitions "}" + { world.fieldLists.pop(); std::cout << "TYPE " << $2 << std::endl; } | "type" type_spec "as" type_spec { std::cout << "TYPE " << $2 << std::endl; } ; @@ -138,16 +149,18 @@ type_spec : res_type { $$ = TypeSpec($res_type); } ; field_definitions : %empty - | field_definitions IDENTIFIER ":" + | field_definitions IDENTIFIER ":" { world.fieldLists.top()->addLabel($2); } | field_definitions ";" - | field_definitions field_definition ";" ; + | field_definitions field_definition ";" { world.fieldLists.top()->addField($2); } + ; %type field_definition; field_definition: simple_field_definition { $$ = $1; } - | array_definition - | switch_definition - | fill_statement - | align_statement; + | array_definition { $$ = nullptr; } + | switch_definition { $$ = nullptr; } + | fill_statement { $$ = nullptr; } + | align_statement { $$ = nullptr; } + ; %type simple_field_definition; simple_field_definition: field_attributes simpletype array_count_opt value_spec_opt @@ -168,10 +181,10 @@ simple_field_definition: field_attributes simpletype array_count_opt value_spec_ { $$ = $1; $$->addNamedValue($IDENTIFIER, $value); } ; -%type array_count array_count_opt value_spec_opt value ; +%type array_count array_count_opt value_spec_opt value resource_item; %type expression expression1 expression2 ; -%type expression3 expression4 expression5 expression6; -%type expression7 expression8; +%type expression3 expression4 expression5 ; +%type expression6 expression7 expression8; value_spec_opt : %empty { $$ = nullptr; } | "=" value { $$ = $2; } ; @@ -223,70 +236,52 @@ switch_cases : %empty | switch_cases switch_case ; switch_case : "case" IDENTIFIER ":" field_definitions ; -/* -expression - | expression "^" expression - | expression "&" expression - | expression "|" expression - | "~" expression - | expression "==" expression - | expression "!=" expression - | expression ">>" expression - | expression "<<" expression - | expression "+" expression - | expression "-" expression - | "-" expression - | expression "/" expression - | expression "*" expression - ; -*/ - -value : expression - | "{" resource_body "}" +value : expression { $$ = $1; } + | "{" resource_body "}" { $$ = $2; } | STRINGLIT { $$ = std::make_shared($1); } ; -expression : expression1 - | expression "^" expression1 +expression : expression1 { $$ = $1; } + | expression "^" expression1 { $$ = std::make_shared(BinaryOp::XOR, $1, $3); } ; -expression1 : expression2 - | expression1 "&" expression2 +expression1 : expression2 { $$ = $1; } + | expression1 "&" expression2 { $$ = std::make_shared(BinaryOp::AND, $1, $3); } ; -expression2 : expression3 - | expression2 "|" expression3 +expression2 : expression3 { $$ = $1; } + | expression2 "|" expression3 { $$ = std::make_shared(BinaryOp::OR, $1, $3); } ; -expression3 : expression4 - | expression3 "==" expression4 - | expression3 "!=" expression4 +expression3 : expression4 { $$ = $1; } + | expression3 "==" expression4 { $$ = std::make_shared(BinaryOp::EQUAL, $1, $3); } + | expression3 "!=" expression4 { $$ = std::make_shared(BinaryOp::NOTEQUAL, $1, $3); } ; -expression4 : expression5 - | expression4 ">>" expression5 - | expression4 "<<" expression5 +expression4 : expression5 { $$ = $1; } + | expression4 ">>" expression5 { $$ = std::make_shared(BinaryOp::SHIFTRIGHT, $1, $3); } + | expression4 "<<" expression5 { $$ = std::make_shared(BinaryOp::SHIFTLEFT, $1, $3); } ; -expression5 : expression6 - | expression5 "+" expression6 - | expression5 "-" expression6 +expression5 : expression6 { $$ = $1; } + | expression5 "+" expression6 { $$ = std::make_shared(BinaryOp::PLUS, $1, $3); } + | expression5 "-" expression6 { $$ = std::make_shared(BinaryOp::MINUS, $1, $3); } ; -expression6 : expression7 - | expression6 "*" expression7 - | expression6 "/" expression7 +expression6 : expression7 { $$ = $1; } + | expression6 "*" expression7 { $$ = std::make_shared(BinaryOp::MULTIPLY, $1, $3); } + | expression6 "/" expression7 { $$ = std::make_shared(BinaryOp::DIVIDE, $1, $3); } ; -expression7 : expression8 - | "-" expression7 - | "+" expression7 - | "~" expression7 +expression7 : expression8 { $$ = $1; } + | "-" expression7 { $$ = std::make_shared(UnaryOp::MINUS, $2); } + | "+" expression7 { $$ = $2; } + | "~" expression7 { $$ = std::make_shared(UnaryOp::COMPLEMENT, $2); } ; expression8 : INTLIT { $$ = std::make_shared($1); } | CHARLIT { $$ = std::make_shared($1); } - | IDENTIFIER + | IDENTIFIER /* ### */ | IDENTIFIER "(" function_argument_list ")" | IDENTIFIER "[" function_argument_list1 "]" | "(" expression ")" { $$ = $2; } @@ -296,16 +291,38 @@ expression8 : INTLIT { $$ = std::make_shared($1); } function_argument_list : %empty | function_argument_list1 ; function_argument_list1 : expression | function_argument_list "," expression ; -resource: "resource" res_type "(" function_argument_list ")" "{" resource_body "}" - { std::cout << "RESOURCE " << $2 << std::endl; } +resource : "resource" res_type "(" expression resource_attributes ")" "{" resource_body "}" + { + int id = $expression->evaluateInt(nullptr); + std::cout << "RESOURCE " << $2 << "(" << id << ")" << std::endl; + TypeDefinitionPtr type = world.getTypeDefinition($res_type, id); + ResourceCompiler compiler; + std::cout << "(first pass)\n"; + type->compile($resource_body, &compiler, true); + std::cout << "(second pass)\n"; + type->compile($resource_body, &compiler, false); + std::cout << "(done)\n"; + } + ; -resource_body : %empty | resource_body1 ; -resource_body1 : resource_item - | resource_body1 "," resource_item - | resource_body1 ";" resource_item - | resource_body1 ";" +%type resource_attributes resource_attribute; +resource_attributes : %empty { $$ = 0; } + | resource_attributes "," resource_attribute { $$ = $1 | $3; } + ; +resource_attribute : IDENTIFIER { $$ = 0; } /* ### */ + +%type resource_body resource_body1; +resource_body : %empty { $$ = std::make_shared(); } + | resource_body1 { $$ = $1; } + ; +resource_body1 : resource_item { $$ = std::make_shared(); $$->addItem($1); } + | resource_body1 "," resource_item { $$ = $1; $$->addItem($3); } + | resource_body1 ";" resource_item { $$ = $1; $$->addItem($3); } + | resource_body1 ";" { $$ = $1; } ; -resource_item : value | IDENTIFIER "{" resource_body "}" ; +resource_item : value { $$ = $1; } + | IDENTIFIER "{" resource_body "}" // ### + ; %% diff --git a/Rez/RezWorld.cc b/Rez/RezWorld.cc new file mode 100644 index 0000000000..90e6148b1a --- /dev/null +++ b/Rez/RezWorld.cc @@ -0,0 +1,22 @@ +#include "RezWorld.h" + +RezWorld::RezWorld() +{ +} + +void RezWorld::addTypeDefinition(TypeSpec spec, TypeDefinitionPtr type) +{ + types[spec] = type; +} + +TypeDefinitionPtr RezWorld::getTypeDefinition(ResType type, int id) +{ + auto p = types.find(TypeSpec(type, id)); + if(p != types.end()) + return p->second; + p = types.find(TypeSpec(type)); + if(p != types.end()) + return p->second; + + return nullptr; +} diff --git a/Rez/RezWorld.h b/Rez/RezWorld.h new file mode 100644 index 0000000000..63f205bcfb --- /dev/null +++ b/Rez/RezWorld.h @@ -0,0 +1,23 @@ +#ifndef REZWORLD_H +#define REZWORLD_H + +#include +#include +#include "ResourceDefinitions.h" +#include "Expression.h" + +class RezWorld +{ + friend class RezParser; + + std::map types; + std::stack fieldLists; +public: + RezWorld(); + void addTypeDefinition(TypeSpec spec, TypeDefinitionPtr type); + + TypeDefinitionPtr getTypeDefinition(ResType type, int id); +}; + + +#endif // REZWORLD_H