can layout (but not really compile) resources consisting of integers only

This commit is contained in:
Wolfgang Thaller 2014-10-07 20:15:46 +02:00
parent 2b3e533937
commit e5d2ab752a
11 changed files with 459 additions and 150 deletions

View File

@ -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})

87
Rez/Expression.cc Normal file
View File

@ -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);
}
}

94
Rez/Expression.h Normal file
View File

@ -0,0 +1,94 @@
#ifndef EXPRESSION_H
#define EXPRESSION_H
#include <memory>
#include <vector>
class Context
{
};
class Expression;
class CompoundExpr;
typedef std::shared_ptr<Expression> ExprPtr;
typedef std::shared_ptr<CompoundExpr> 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<ExprPtr> 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

11
Rez/ResourceCompiler.cc Normal file
View File

@ -0,0 +1,11 @@
#include "ResourceCompiler.h"
#include <iostream>
ResourceCompiler::ResourceCompiler()
{
}
void ResourceCompiler::write(int nBits, int value)
{
std::cout << "[" << nBits << " bits] = " << std::hex << value << std::dec << std::endl;
}

15
Rez/ResourceCompiler.h Normal file
View File

@ -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

View File

@ -1,11 +1,8 @@
#include "ResourceDefinitions.h"
#include <ostream>
#include <cassert>
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<CompoundExpr>(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);
}

View File

@ -5,6 +5,8 @@
#include <memory>
#include <map>
#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<Expression> 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<Field> 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<SimpleField> 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<FieldPtr> 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<FieldList> FieldListPtr;
class TypeDefinition : public FieldList
{
};
typedef std::shared_ptr<TypeDefinition> TypeDefinitionPtr;
#endif // RESOURCEDEFINITIONS_H

View File

@ -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<char>(instream.rdbuf()),
std::istreambuf_iterator<char>());
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;
}

View File

@ -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<TypeDefinition>();
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 <FieldPtr> 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 <SimpleFieldPtr> 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 <ExprPtr> array_count array_count_opt value_spec_opt value ;
%type <ExprPtr> array_count array_count_opt value_spec_opt value resource_item;
%type <ExprPtr> expression expression1 expression2 ;
%type <ExprPtr> expression3 expression4 expression5 expression6;
%type <ExprPtr> expression7 expression8;
%type <ExprPtr> expression3 expression4 expression5 ;
%type <ExprPtr> 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<StringExpr>($1); }
;
expression : expression1
| expression "^" expression1
expression : expression1 { $$ = $1; }
| expression "^" expression1 { $$ = std::make_shared<BinaryExpr>(BinaryOp::XOR, $1, $3); }
;
expression1 : expression2
| expression1 "&" expression2
expression1 : expression2 { $$ = $1; }
| expression1 "&" expression2 { $$ = std::make_shared<BinaryExpr>(BinaryOp::AND, $1, $3); }
;
expression2 : expression3
| expression2 "|" expression3
expression2 : expression3 { $$ = $1; }
| expression2 "|" expression3 { $$ = std::make_shared<BinaryExpr>(BinaryOp::OR, $1, $3); }
;
expression3 : expression4
| expression3 "==" expression4
| expression3 "!=" expression4
expression3 : expression4 { $$ = $1; }
| expression3 "==" expression4 { $$ = std::make_shared<BinaryExpr>(BinaryOp::EQUAL, $1, $3); }
| expression3 "!=" expression4 { $$ = std::make_shared<BinaryExpr>(BinaryOp::NOTEQUAL, $1, $3); }
;
expression4 : expression5
| expression4 ">>" expression5
| expression4 "<<" expression5
expression4 : expression5 { $$ = $1; }
| expression4 ">>" expression5 { $$ = std::make_shared<BinaryExpr>(BinaryOp::SHIFTRIGHT, $1, $3); }
| expression4 "<<" expression5 { $$ = std::make_shared<BinaryExpr>(BinaryOp::SHIFTLEFT, $1, $3); }
;
expression5 : expression6
| expression5 "+" expression6
| expression5 "-" expression6
expression5 : expression6 { $$ = $1; }
| expression5 "+" expression6 { $$ = std::make_shared<BinaryExpr>(BinaryOp::PLUS, $1, $3); }
| expression5 "-" expression6 { $$ = std::make_shared<BinaryExpr>(BinaryOp::MINUS, $1, $3); }
;
expression6 : expression7
| expression6 "*" expression7
| expression6 "/" expression7
expression6 : expression7 { $$ = $1; }
| expression6 "*" expression7 { $$ = std::make_shared<BinaryExpr>(BinaryOp::MULTIPLY, $1, $3); }
| expression6 "/" expression7 { $$ = std::make_shared<BinaryExpr>(BinaryOp::DIVIDE, $1, $3); }
;
expression7 : expression8
| "-" expression7
| "+" expression7
| "~" expression7
expression7 : expression8 { $$ = $1; }
| "-" expression7 { $$ = std::make_shared<UnaryExpr>(UnaryOp::MINUS, $2); }
| "+" expression7 { $$ = $2; }
| "~" expression7 { $$ = std::make_shared<UnaryExpr>(UnaryOp::COMPLEMENT, $2); }
;
expression8 : INTLIT { $$ = std::make_shared<IntExpr>($1); }
| CHARLIT { $$ = std::make_shared<IntExpr>($1); }
| IDENTIFIER
| IDENTIFIER /* ### */
| IDENTIFIER "(" function_argument_list ")"
| IDENTIFIER "[" function_argument_list1 "]"
| "(" expression ")" { $$ = $2; }
@ -296,16 +291,38 @@ expression8 : INTLIT { $$ = std::make_shared<IntExpr>($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 <int> resource_attributes resource_attribute;
resource_attributes : %empty { $$ = 0; }
| resource_attributes "," resource_attribute { $$ = $1 | $3; }
;
resource_attribute : IDENTIFIER { $$ = 0; } /* ### */
%type <CompoundExprPtr> resource_body resource_body1;
resource_body : %empty { $$ = std::make_shared<CompoundExpr>(); }
| resource_body1 { $$ = $1; }
;
resource_body1 : resource_item { $$ = std::make_shared<CompoundExpr>(); $$->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 "}" // ###
;
%%

22
Rez/RezWorld.cc Normal file
View File

@ -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;
}

23
Rez/RezWorld.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef REZWORLD_H
#define REZWORLD_H
#include <map>
#include <stack>
#include "ResourceDefinitions.h"
#include "Expression.h"
class RezWorld
{
friend class RezParser;
std::map<TypeSpec, TypeDefinitionPtr> types;
std::stack<FieldListPtr> fieldLists;
public:
RezWorld();
void addTypeDefinition(TypeSpec spec, TypeDefinitionPtr type);
TypeDefinitionPtr getTypeDefinition(ResType type, int id);
};
#endif // REZWORLD_H