Rez: add some error reporting

This commit is contained in:
Wolfgang Thaller 2014-10-30 02:56:49 +01:00
parent 2a86126dad
commit 3da8beb96f
12 changed files with 202 additions and 96 deletions

View File

@ -56,6 +56,8 @@ add_library(RezLib
ResourceCompiler.h ResourceCompiler.h
ResSpec.h ResSpec.h
Diagnostic.h Diagnostic.cc
) )
target_link_libraries(RezLib ResourceFiles ${Boost_LIBRARIES}) target_link_libraries(RezLib ResourceFiles ${Boost_LIBRARIES})

17
Rez/Diagnostic.cc Normal file
View File

@ -0,0 +1,17 @@
#include "Diagnostic.h"
Diagnostic::Diagnostic()
{
}
Diagnostic::Diagnostic(Severity sev, std::string msg, yy::location loc)
: severity(sev), message(msg), location(loc)
{
}
std::ostream &operator<<(std::ostream &out, const Diagnostic &d)
{
return out << d.location << ": " << d.message;
}

31
Rez/Diagnostic.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef DIAGNOSTIC_H
#define DIAGNOSTIC_H
#include <string>
#include <iosfwd>
#include "location.hh"
class Diagnostic
{
public:
enum Severity
{
warning,
error,
fatalError
};
Diagnostic();
Diagnostic(Severity sev, std::string msg, yy::location loc);
private:
Severity severity;
std::string message;
yy::location location;
friend std::ostream& operator<<(std::ostream&, const Diagnostic&);
};
std::ostream& operator<<(std::ostream&, const Diagnostic&);
#endif // DIAGNOSTIC_H

View File

@ -3,21 +3,29 @@
#include <cassert> #include <cassert>
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include "Diagnostic.h"
int Expression::evaluateInt(ResourceCompiler *ctx) int Expression::evaluateInt(ResourceCompiler *ctx)
{ {
throw TypeError(); error(ctx, "Expected an integer or integer expression here.");
return 0;
} }
std::string Expression::evaluateString(ResourceCompiler *ctx) std::string Expression::evaluateString(ResourceCompiler *ctx)
{ {
throw TypeError(); error(ctx, "Expected a string or string expression here.");
return "";
} }
Expression::~Expression() Expression::~Expression()
{ {
} }
void Expression::error(ResourceCompiler *ctx, std::string err)
{
ctx->problem(Diagnostic(Diagnostic::Severity::error, err, location));
}
StringExpr::~StringExpr() StringExpr::~StringExpr()
{ {
@ -80,8 +88,8 @@ int BinaryExpr::evaluateInt(ResourceCompiler *ctx)
case BinaryOp::DIVIDE: case BinaryOp::DIVIDE:
return a->evaluateInt(ctx) / b->evaluateInt(ctx); return a->evaluateInt(ctx) / b->evaluateInt(ctx);
default: default:
throw TypeError(); error(ctx, "Expected an integer or integer expression here.");
break; return 0;
} }
} }
@ -92,8 +100,8 @@ std::string BinaryExpr::evaluateString(ResourceCompiler *ctx)
case BinaryOp::CONCAT: case BinaryOp::CONCAT:
return a->evaluateString(ctx) + b->evaluateString(ctx); return a->evaluateString(ctx) + b->evaluateString(ctx);
default: default:
throw TypeError(); error(ctx, "Expected a string or string expression here.");
break; return "";
} }
} }
@ -111,14 +119,14 @@ int UnaryExpr::evaluateInt(ResourceCompiler *ctx)
case UnaryOp::COMPLEMENT: case UnaryOp::COMPLEMENT:
return ~a->evaluateInt(ctx); return ~a->evaluateInt(ctx);
default: default:
throw TypeError(); error(ctx, "Expected an integer or integer expression here.");
break; return 0;
} }
} }
IdentifierExpr::IdentifierExpr(std::string id) IdentifierExpr::IdentifierExpr(std::string id, yy::location loc)
: id(id) : Expression(loc), id(id)
{ {
} }
@ -133,7 +141,8 @@ ExprPtr IdentifierExpr::lookup(ResourceCompiler *ctx)
for(auto arg : arguments) for(auto arg : arguments)
sub.addSubscript(arg->evaluateInt(ctx)); sub.addSubscript(arg->evaluateInt(ctx));
ExprPtr val = ctx->lookupIdentifier(id, sub); ExprPtr val = ctx->lookupIdentifier(id, sub);
assert(val); if(!val)
error(ctx, "Identifier \"" + id + "\" is not defined.");
return val; return val;
} }
@ -141,17 +150,23 @@ int IdentifierExpr::evaluateInt(ResourceCompiler *ctx)
{ {
if(ctx->isPrePass()) if(ctx->isPrePass())
return 0; return 0;
return lookup(ctx)->evaluateInt(ctx); if(ExprPtr e = lookup(ctx))
return e->evaluateInt(ctx);
else
return 0;
} }
std::string IdentifierExpr::evaluateString(ResourceCompiler *ctx) std::string IdentifierExpr::evaluateString(ResourceCompiler *ctx)
{ {
return lookup(ctx)->evaluateString(ctx); if(ExprPtr e = lookup(ctx))
return e->evaluateString(ctx);
else
return "";
} }
CaseExpr::CaseExpr(const std::string &tag, CompoundExprPtr expr) CaseExpr::CaseExpr(const std::string &tag, CompoundExprPtr expr, yy::location loc)
: tag(tag), expr(expr) : Expression(loc), tag(tag), expr(expr)
{ {
} }
@ -193,15 +208,16 @@ std::string UnimplementedExpr::evaluateString(ResourceCompiler *ctx)
} }
PeekExpr::PeekExpr(ExprPtr addr, ExprPtr offset, ExprPtr size) PeekExpr::PeekExpr(ExprPtr addr, ExprPtr offset, ExprPtr size, yy::location loc)
: addr(addr), offset(offset), size(size) : Expression(loc), addr(addr), offset(offset), size(size)
{ {
} }
PeekExpr::PeekExpr(ExprPtr addr, int size) PeekExpr::PeekExpr(ExprPtr addr, int size, yy::location loc)
: addr(addr), : Expression(loc),
offset(std::make_shared<IntExpr>(0)), addr(addr),
size(std::make_shared<IntExpr>(size)) offset(std::make_shared<IntExpr>(0,loc)),
size(std::make_shared<IntExpr>(size,loc))
{ {
} }

View File

@ -4,6 +4,8 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
#include "location.hh"
class ResourceCompiler; class ResourceCompiler;
class Expression; class Expression;
@ -33,16 +35,22 @@ class TypeError
class Expression class Expression
{ {
public: public:
yy::location location;
Expression(yy::location loc) : location(loc) {}
virtual int evaluateInt(ResourceCompiler *ctx); virtual int evaluateInt(ResourceCompiler *ctx);
virtual std::string evaluateString(ResourceCompiler *ctx); virtual std::string evaluateString(ResourceCompiler *ctx);
virtual ~Expression(); virtual ~Expression();
void error(ResourceCompiler *ctx, std::string err);
}; };
class StringExpr : public Expression class StringExpr : public Expression
{ {
std::string str; std::string str;
public: public:
StringExpr(const std::string& str) : str(str) {} StringExpr(const std::string& str, yy::location loc) : Expression(loc), str(str) {}
~StringExpr(); ~StringExpr();
virtual std::string evaluateString(ResourceCompiler *ctx); virtual std::string evaluateString(ResourceCompiler *ctx);
}; };
@ -51,7 +59,7 @@ class IntExpr : public Expression
{ {
int val; int val;
public: public:
IntExpr(int val) : val(val) {} IntExpr(int val, yy::location loc) : Expression(loc), val(val) {}
~IntExpr(); ~IntExpr();
virtual int evaluateInt(ResourceCompiler *ctx); virtual int evaluateInt(ResourceCompiler *ctx);
@ -61,6 +69,8 @@ class CompoundExpr : public Expression
{ {
std::vector<ExprPtr> items; std::vector<ExprPtr> items;
public: public:
CompoundExpr(yy::location loc) : Expression(loc) {}
void addItem(ExprPtr item); void addItem(ExprPtr item);
ExprPtr getItem(int i) const { return items[i]; } ExprPtr getItem(int i) const { return items[i]; }
int size() const { return items.size(); } int size() const { return items.size(); }
@ -74,7 +84,7 @@ class CaseExpr : public Expression
CompoundExprPtr expr; CompoundExprPtr expr;
friend class SwitchField; friend class SwitchField;
public: public:
CaseExpr(const std::string& tag, CompoundExprPtr expr); CaseExpr(const std::string& tag, CompoundExprPtr expr, yy::location loc);
}; };
class BinaryExpr : public Expression class BinaryExpr : public Expression
@ -82,8 +92,8 @@ class BinaryExpr : public Expression
BinaryOp op; BinaryOp op;
ExprPtr a, b; ExprPtr a, b;
public: public:
BinaryExpr(BinaryOp op, ExprPtr a, ExprPtr b) BinaryExpr(BinaryOp op, ExprPtr a, ExprPtr b, yy::location loc)
: op(op), a(a), b(b) {} : Expression(loc), op(op), a(a), b(b) {}
~BinaryExpr(); ~BinaryExpr();
virtual int evaluateInt(ResourceCompiler *ctx); virtual int evaluateInt(ResourceCompiler *ctx);
@ -95,8 +105,8 @@ class UnaryExpr : public Expression
UnaryOp op; UnaryOp op;
ExprPtr a; ExprPtr a;
public: public:
UnaryExpr(UnaryOp op, ExprPtr a) UnaryExpr(UnaryOp op, ExprPtr a, yy::location loc)
: op(op), a(a) {} : Expression(loc), op(op), a(a) {}
~UnaryExpr(); ~UnaryExpr();
virtual int evaluateInt(ResourceCompiler *ctx); virtual int evaluateInt(ResourceCompiler *ctx);
@ -107,7 +117,7 @@ class IdentifierExpr : public Expression
public: public:
std::string id; std::string id;
std::vector<ExprPtr> arguments; std::vector<ExprPtr> arguments;
IdentifierExpr(std::string id); IdentifierExpr(std::string id, yy::location loc);
void addArgument(ExprPtr e); void addArgument(ExprPtr e);
ExprPtr lookup(ResourceCompiler *ctx); ExprPtr lookup(ResourceCompiler *ctx);
@ -119,7 +129,7 @@ class CountOfExpr : public Expression
{ {
IdentifierExprPtr arg; IdentifierExprPtr arg;
public: public:
CountOfExpr(IdentifierExprPtr arg) : arg(arg) {} CountOfExpr(IdentifierExprPtr arg, yy::location loc) : Expression(loc), arg(arg) {}
virtual int evaluateInt(ResourceCompiler *ctx); virtual int evaluateInt(ResourceCompiler *ctx);
}; };
@ -127,7 +137,7 @@ class ArrayIndexExpr : public Expression
{ {
IdentifierExprPtr arg; IdentifierExprPtr arg;
public: public:
ArrayIndexExpr(IdentifierExprPtr arg) : arg(arg) {} ArrayIndexExpr(IdentifierExprPtr arg, yy::location loc) : Expression(loc), arg(arg) {}
virtual int evaluateInt(ResourceCompiler *ctx); virtual int evaluateInt(ResourceCompiler *ctx);
}; };
@ -135,7 +145,7 @@ class ReadExpr : public Expression
{ {
ExprPtr arg; ExprPtr arg;
public: public:
ReadExpr(ExprPtr arg) : arg(arg) {} ReadExpr(ExprPtr arg, yy::location loc) : Expression(loc), arg(arg) {}
virtual std::string evaluateString(ResourceCompiler *ctx); virtual std::string evaluateString(ResourceCompiler *ctx);
}; };
@ -143,7 +153,7 @@ class UnimplementedExpr : public Expression
{ {
std::string msg; std::string msg;
public: public:
UnimplementedExpr(std::string msg) : msg(msg) {} UnimplementedExpr(std::string msg, yy::location loc) : Expression(loc), msg(msg) {}
virtual int evaluateInt(ResourceCompiler *ctx); virtual int evaluateInt(ResourceCompiler *ctx);
virtual std::string evaluateString(ResourceCompiler *ctx); virtual std::string evaluateString(ResourceCompiler *ctx);
}; };
@ -154,8 +164,8 @@ class PeekExpr : public Expression
ExprPtr offset; ExprPtr offset;
ExprPtr size; ExprPtr size;
public: public:
PeekExpr(ExprPtr addr, ExprPtr offset, ExprPtr size); PeekExpr(ExprPtr addr, ExprPtr offset, ExprPtr size, yy::location loc);
PeekExpr(ExprPtr addr, int size); PeekExpr(ExprPtr addr, int size, yy::location loc);
virtual int evaluateInt(ResourceCompiler *ctx); virtual int evaluateInt(ResourceCompiler *ctx);
}; };

View File

@ -1,10 +1,13 @@
#include "ResourceCompiler.h" #include "ResourceCompiler.h"
#include <iostream> #include <iostream>
#include "ResourceDefinitions.h" #include "ResourceDefinitions.h"
#include "RezWorld.h"
#include "Diagnostic.h"
ResourceCompiler::ResourceCompiler( ResourceCompiler::ResourceCompiler(
TypeDefinitionPtr type, CompoundExprPtr body, bool verboseFlag) RezWorld& world, TypeDefinitionPtr type, CompoundExprPtr body, bool verboseFlag)
: typeDefinition(type), : world(world),
typeDefinition(type),
body(body), body(body),
currentField(nullptr) currentField(nullptr)
{ {
@ -99,14 +102,14 @@ ExprPtr ResourceCompiler::lookupIdentifier(std::string name, const Subscripts &s
if(p != labelValues.end()) if(p != labelValues.end())
return p->second; return p->second;
std::cerr << "ID lookup failed: " << name << std::endl; //std::cerr << "ID lookup failed: " << name << std::endl;
return nullptr; return nullptr;
} }
void ResourceCompiler::defineLabel(const std::string &name) void ResourceCompiler::defineLabel(const std::string &name)
{ {
labelValues[std::make_pair(name,currentSubscripts)] = std::make_shared<IntExpr>(currentOffset); labelValues[std::make_pair(name,currentSubscripts)] = std::make_shared<IntExpr>(currentOffset, yy::location());
} }
void ResourceCompiler::compile() void ResourceCompiler::compile()
@ -142,6 +145,11 @@ int ResourceCompiler::getArrayIndex(const std::string &arrayName)
return curArrayIndices[arrayName]; return curArrayIndices[arrayName];
} }
void ResourceCompiler::problem(Diagnostic d)
{
world.problem(d);
}
void ResourceCompiler::beginArrayScope(std::string &arrayName, int index) void ResourceCompiler::beginArrayScope(std::string &arrayName, int index)
{ {
if(arrayName != "") if(arrayName != "")

View File

@ -5,7 +5,8 @@
#include "ResourceDefinitions.h" #include "ResourceDefinitions.h"
class Field; class Field;
class RezWorld;
class Diagnostic;
class Subscripts class Subscripts
{ {
@ -45,6 +46,7 @@ public:
class ResourceCompiler : public BinaryOutput class ResourceCompiler : public BinaryOutput
{ {
RezWorld& world;
TypeDefinitionPtr typeDefinition; TypeDefinitionPtr typeDefinition;
CompoundExprPtr body; CompoundExprPtr body;
std::map<std::pair<std::string, Subscripts>, ExprPtr> labelValues; std::map<std::pair<std::string, Subscripts>, ExprPtr> labelValues;
@ -53,13 +55,9 @@ class ResourceCompiler : public BinaryOutput
Field* currentField; Field* currentField;
Subscripts currentSubscripts; Subscripts currentSubscripts;
void beginArrayScope(std::string& arrayName, int index); void beginArrayScope(std::string& arrayName, int index);
public: public:
ResourceCompiler(TypeDefinitionPtr type, CompoundExprPtr body, bool verboseFlag); ResourceCompiler(RezWorld& world, TypeDefinitionPtr type, CompoundExprPtr body, bool verboseFlag);
ExprPtr lookupIdentifier(std::string name, const Subscripts& sub = Subscripts()); ExprPtr lookupIdentifier(std::string name, const Subscripts& sub = Subscripts());
@ -87,6 +85,8 @@ public:
: compiler(compiler) { compiler->beginArrayScope(arrayName, index); } : compiler(compiler) { compiler->beginArrayScope(arrayName, index); }
~ArrayScope() { compiler->currentSubscripts.popSubscript(); } ~ArrayScope() { compiler->currentSubscripts.popSubscript(); }
}; };
void problem(Diagnostic d);
}; };

View File

@ -20,14 +20,15 @@ FieldList::~FieldList()
} }
void FieldList::addField(FieldPtr field) void FieldList::addField(FieldPtr field, yy::location loc)
{ {
field->location = loc;
fields.push_back(field); fields.push_back(field);
} }
void FieldList::addLabel(std::string name) void FieldList::addLabel(std::string name, yy::location loc)
{ {
addField(std::make_shared<LabelField>(name)); addField(std::make_shared<LabelField>(name), loc);
} }
void FieldList::compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass) void FieldList::compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass)
@ -52,9 +53,9 @@ void SimpleField::addNamedValue(std::string n)
{ {
if(lastNamedValue) if(lastNamedValue)
addNamedValue(n, std::make_shared<BinaryExpr>( addNamedValue(n, std::make_shared<BinaryExpr>(
BinaryOp::PLUS, lastNamedValue, std::make_shared<IntExpr>(1))); BinaryOp::PLUS, lastNamedValue, std::make_shared<IntExpr>(1, yy::location()), yy::location()));
else else
addNamedValue(n, std::make_shared<IntExpr>(0)); addNamedValue(n, std::make_shared<IntExpr>(0, yy::location()));
} }
void SimpleField::addNamedValue(std::string n, ExprPtr val) void SimpleField::addNamedValue(std::string n, ExprPtr val)
@ -200,8 +201,12 @@ void SimpleField::compileCompound(ExprPtr expr, ResourceCompiler *compiler, bool
} }
CompoundExprPtr compound = std::dynamic_pointer_cast<CompoundExpr>(val); CompoundExprPtr compound = std::dynamic_pointer_cast<CompoundExpr>(val);
if(!compound || compound->size() != count)
{
expr->error(compiler, std::string("expected ") + (type == Type::rect ? "rect {t,l,b,r}." : "point {v,h}."));
return;
}
assert(compound); assert(compound);
assert(compound->size() == count); assert(compound->size() == count);
for(int i = 0; i < count; i++) for(int i = 0; i < count; i++)

View File

@ -8,6 +8,7 @@
#include "Expression.h" #include "Expression.h"
#include "ResType.h" #include "ResType.h"
#include "location.hh"
class TypeSpec class TypeSpec
{ {
@ -44,6 +45,8 @@ class ResourceCompiler;
class Field class Field
{ {
public: public:
yy::location location;
virtual bool needsValue() { return true; } virtual bool needsValue() { return true; }
virtual void compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass) = 0; virtual void compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass) = 0;
@ -129,8 +132,8 @@ protected:
std::vector<FieldPtr> fields; std::vector<FieldPtr> fields;
public: public:
virtual ~FieldList(); virtual ~FieldList();
void addField(FieldPtr field); void addField(FieldPtr field, yy::location loc);
void addLabel(std::string name); void addLabel(std::string name, yy::location loc);
virtual void compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass); virtual void compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass);
}; };

View File

@ -198,9 +198,9 @@ type_spec : res_type { $$ = TypeSpec($res_type); }
; ;
field_definitions : %empty field_definitions : %empty
| field_definitions IDENTIFIER ":" { world.fieldLists.top()->addLabel($2); } | field_definitions IDENTIFIER ":" { world.fieldLists.top()->addLabel($2, @2); }
| field_definitions ";" | field_definitions ";"
| field_definitions field_definition ";" { world.fieldLists.top()->addField($2); } | field_definitions field_definition ";" { world.fieldLists.top()->addField($2, @2); }
; ;
%type <FieldPtr> field_definition; %type <FieldPtr> field_definition;
@ -328,71 +328,71 @@ switch_case : "case" IDENTIFIER ":"
value : expression { $$ = $1; } value : expression { $$ = $1; }
| "{" resource_body "}" { $$ = $2; } | "{" resource_body "}" { $$ = $2; $$->location = @0; }
| string_expression { $$ = $1; } | string_expression { $$ = $1; }
; ;
expression : expression1 { $$ = $1; } expression : expression1 { $$ = $1; }
| expression "^" expression1 { $$ = std::make_shared<BinaryExpr>(BinaryOp::XOR, $1, $3); } | expression "^" expression1 { $$ = std::make_shared<BinaryExpr>(BinaryOp::XOR, $1, $3, @0); }
; ;
expression1 : expression2 { $$ = $1; } expression1 : expression2 { $$ = $1; }
| expression1 "&" expression2 { $$ = std::make_shared<BinaryExpr>(BinaryOp::AND, $1, $3); } | expression1 "&" expression2 { $$ = std::make_shared<BinaryExpr>(BinaryOp::AND, $1, $3, @0); }
; ;
expression2 : expression3 { $$ = $1; } expression2 : expression3 { $$ = $1; }
| expression2 "|" expression3 { $$ = std::make_shared<BinaryExpr>(BinaryOp::OR, $1, $3); } | expression2 "|" expression3 { $$ = std::make_shared<BinaryExpr>(BinaryOp::OR, $1, $3, @0); }
; ;
expression3 : expression4 { $$ = $1; } expression3 : expression4 { $$ = $1; }
| expression3 "==" expression4 { $$ = std::make_shared<BinaryExpr>(BinaryOp::EQUAL, $1, $3); } | expression3 "==" expression4 { $$ = std::make_shared<BinaryExpr>(BinaryOp::EQUAL, $1, $3, @0); }
| expression3 "!=" expression4 { $$ = std::make_shared<BinaryExpr>(BinaryOp::NOTEQUAL, $1, $3); } | expression3 "!=" expression4 { $$ = std::make_shared<BinaryExpr>(BinaryOp::NOTEQUAL, $1, $3, @0); }
; ;
expression4 : expression5 { $$ = $1; } expression4 : expression5 { $$ = $1; }
| expression4 ">>" expression5 { $$ = std::make_shared<BinaryExpr>(BinaryOp::SHIFTRIGHT, $1, $3); } | expression4 ">>" expression5 { $$ = std::make_shared<BinaryExpr>(BinaryOp::SHIFTRIGHT, $1, $3, @0); }
| expression4 "<<" expression5 { $$ = std::make_shared<BinaryExpr>(BinaryOp::SHIFTLEFT, $1, $3); } | expression4 "<<" expression5 { $$ = std::make_shared<BinaryExpr>(BinaryOp::SHIFTLEFT, $1, $3, @0); }
; ;
expression5 : expression6 { $$ = $1; } expression5 : expression6 { $$ = $1; }
| expression5 "+" expression6 { $$ = std::make_shared<BinaryExpr>(BinaryOp::PLUS, $1, $3); } | expression5 "+" expression6 { $$ = std::make_shared<BinaryExpr>(BinaryOp::PLUS, $1, $3, @0); }
| expression5 "-" expression6 { $$ = std::make_shared<BinaryExpr>(BinaryOp::MINUS, $1, $3); } | expression5 "-" expression6 { $$ = std::make_shared<BinaryExpr>(BinaryOp::MINUS, $1, $3, @0); }
; ;
expression6 : expression7 { $$ = $1; } expression6 : expression7 { $$ = $1; }
| expression6 "*" expression7 { $$ = std::make_shared<BinaryExpr>(BinaryOp::MULTIPLY, $1, $3); } | expression6 "*" expression7 { $$ = std::make_shared<BinaryExpr>(BinaryOp::MULTIPLY, $1, $3, @0); }
| expression6 "/" expression7 { $$ = std::make_shared<BinaryExpr>(BinaryOp::DIVIDE, $1, $3); } | expression6 "/" expression7 { $$ = std::make_shared<BinaryExpr>(BinaryOp::DIVIDE, $1, $3, @0); }
; ;
expression7 : expression8 { $$ = $1; } expression7 : expression8 { $$ = $1; }
| "-" expression7 { $$ = std::make_shared<UnaryExpr>(UnaryOp::MINUS, $2); } | "-" expression7 { $$ = std::make_shared<UnaryExpr>(UnaryOp::MINUS, $2, @0); }
| "+" expression7 { $$ = $2; } | "+" expression7 { $$ = $2; }
| "~" expression7 { $$ = std::make_shared<UnaryExpr>(UnaryOp::COMPLEMENT, $2); } | "~" expression7 { $$ = std::make_shared<UnaryExpr>(UnaryOp::COMPLEMENT, $2, @0); }
; ;
expression8 : INTLIT { $$ = std::make_shared<IntExpr>($1); } expression8 : INTLIT { $$ = std::make_shared<IntExpr>($1, @1); }
| CHARLIT { $$ = std::make_shared<IntExpr>($1); } | CHARLIT { $$ = std::make_shared<IntExpr>($1, @1); }
| identifier_expression { $$ = $1; } | identifier_expression { $$ = $1; }
| "(" expression ")" { $$ = $2; } | "(" expression ")" { $$ = $2; }
| "$$countof" "(" identifier_expression ")" | "$$countof" "(" identifier_expression ")"
{ $$ = std::make_shared<CountOfExpr>($identifier_expression); } { $$ = std::make_shared<CountOfExpr>($identifier_expression, @0); }
| "$$arrayindex" "(" identifier_expression ")" | "$$arrayindex" "(" identifier_expression ")"
{ $$ = std::make_shared<ArrayIndexExpr>($identifier_expression); } { $$ = std::make_shared<ArrayIndexExpr>($identifier_expression, @0); }
| "$$bitfield" "(" expression "," expression "," expression ")" | "$$bitfield" "(" expression "," expression "," expression ")"
{ $$ = std::make_shared<PeekExpr>($3, $5, $7); } { $$ = std::make_shared<PeekExpr>($3, $5, $7, @0); }
| "$$word" "(" expression ")" | "$$word" "(" expression ")"
{ $$ = std::make_shared<PeekExpr>($3, 16); } { $$ = std::make_shared<PeekExpr>($3, 16, @0); }
| "$$byte" "(" expression ")" | "$$byte" "(" expression ")"
{ $$ = std::make_shared<PeekExpr>($3, 8); } { $$ = std::make_shared<PeekExpr>($3, 8, @0); }
| "$$long" "(" expression ")" | "$$long" "(" expression ")"
{ $$ = std::make_shared<PeekExpr>($3, 32); } { $$ = std::make_shared<PeekExpr>($3, 32, @0); }
; ;
%type <IdentifierExprPtr> identifier_expression; %type <IdentifierExprPtr> identifier_expression;
identifier_expression : IDENTIFIER { $$ = std::make_shared<IdentifierExpr>($1); } identifier_expression : IDENTIFIER { $$ = std::make_shared<IdentifierExpr>($1, @1); }
| IDENTIFIER | IDENTIFIER
{ world.functionCalls.push(std::make_shared<IdentifierExpr>($1)); } { world.functionCalls.push(std::make_shared<IdentifierExpr>($1, @1)); }
"[" function_argument_list1 "]" "[" function_argument_list1 "]"
{ $$ = world.functionCalls.top(); world.functionCalls.pop(); } { $$ = world.functionCalls.top(); world.functionCalls.pop(); }
; ;
@ -407,7 +407,7 @@ function_argument_list1 : expression
%type <ExprPtr> string_expression string_expression1; %type <ExprPtr> string_expression string_expression1;
string_expression : string_expression1 { $$ = $1; } string_expression : string_expression1 { $$ = $1; }
| string_expression string_expression1 | string_expression string_expression1
{ $$ = std::make_shared<BinaryExpr>(BinaryOp::CONCAT, $1, $2); } { $$ = std::make_shared<BinaryExpr>(BinaryOp::CONCAT, $1, $2, @0); }
; ;
%type <std::string> stringlit; %type <std::string> stringlit;
@ -415,14 +415,14 @@ stringlit : STRINGLIT { $$ = $1; }
| DOLLAR STRINGLIT { $$ = fromHex($2); } | DOLLAR STRINGLIT { $$ = fromHex($2); }
; ;
string_expression1 : stringlit { $$ = std::make_shared<StringExpr>($1); } string_expression1 : stringlit { $$ = std::make_shared<StringExpr>($1, @1); }
| "$$read" "(" string_expression ")" | "$$read" "(" string_expression ")"
{ $$ = std::make_shared<ReadExpr>($string_expression); } { $$ = std::make_shared<ReadExpr>($string_expression, @0); }
; ;
resource : "resource" res_spec "{" resource_body "}" resource : "resource" res_spec "{" resource_body "}"
{ {
world.addResource($res_spec, $resource_body); world.addResource($res_spec, $resource_body, @0);
} }
; ;
@ -439,23 +439,23 @@ resource_attributes : %empty { $$ = [](ResSpec s){ return s; }; }
; ;
%type <CompoundExprPtr> resource_body resource_body1; %type <CompoundExprPtr> resource_body resource_body1;
resource_body : %empty { $$ = std::make_shared<CompoundExpr>(); } resource_body : %empty { $$ = std::make_shared<CompoundExpr>(@0); }
| resource_body1 { $$ = $1; } | resource_body1 { $$ = $1; $$->location = @1; }
; ;
resource_body1 : resource_item { $$ = std::make_shared<CompoundExpr>(); $$->addItem($1); } resource_body1 : resource_item { $$ = std::make_shared<CompoundExpr>(@1); $$->addItem($1); }
| resource_body1 "," resource_item { $$ = $1; $$->addItem($3); } | resource_body1 "," resource_item { $$ = $1; $$->addItem($3); }
| resource_body1 ";" resource_item { $$ = $1; $$->addItem($3); } | resource_body1 ";" resource_item { $$ = $1; $$->addItem($3); }
| resource_body1 ";" { $$ = $1; } | resource_body1 ";" { $$ = $1; }
; ;
resource_item : value { $$ = $1; } resource_item : value { $$ = $1; }
| IDENTIFIER "{" resource_body "}" { $$ = std::make_shared<CaseExpr>($IDENTIFIER, $resource_body); } | IDENTIFIER "{" resource_body "}" { $$ = std::make_shared<CaseExpr>($IDENTIFIER, $resource_body, @0); }
; ;
data : "data" res_spec "{" string_expression "}" data : "data" res_spec "{" string_expression "}"
{ {
world.addData($res_spec, $string_expression->evaluateString(nullptr)); world.addData($res_spec, $string_expression->evaluateString(nullptr), @0);
} }
; ;

View File

@ -4,6 +4,8 @@
#include <iostream> #include <iostream>
#include "Diagnostic.h"
RezWorld::RezWorld() RezWorld::RezWorld()
: verboseFlag(false) : verboseFlag(false)
{ {
@ -14,7 +16,7 @@ void RezWorld::addTypeDefinition(TypeSpec spec, TypeDefinitionPtr type)
types[spec] = type; types[spec] = type;
} }
TypeDefinitionPtr RezWorld::getTypeDefinition(ResType type, int id) TypeDefinitionPtr RezWorld::getTypeDefinition(ResType type, int id, yy::location loc)
{ {
auto p = types.find(TypeSpec(type, id)); auto p = types.find(TypeSpec(type, id));
if(p != types.end()) if(p != types.end())
@ -22,24 +24,31 @@ TypeDefinitionPtr RezWorld::getTypeDefinition(ResType type, int id)
p = types.find(TypeSpec(type)); p = types.find(TypeSpec(type));
if(p != types.end()) if(p != types.end())
return p->second; return p->second;
problem(Diagnostic(Diagnostic::Severity::error, "Can't find type definition for '" + std::string(type) + "'", loc));
return nullptr; return nullptr;
} }
void RezWorld::addResource(ResSpec spec, CompoundExprPtr body) void RezWorld::addResource(ResSpec spec, CompoundExprPtr body, yy::location loc)
{ {
if(verboseFlag) if(verboseFlag)
std::cout << "RESOURCE " << spec.type() << "(" << spec.id() << ", " << "\"" << spec.name() << "\"" << spec.attr() << ")" << std::endl; std::cout << "RESOURCE " << spec.type() << "(" << spec.id() << ", " << "\"" << spec.name() << "\"" << spec.attr() << ")" << std::endl;
TypeDefinitionPtr def = getTypeDefinition(spec.type(), spec.id()); TypeDefinitionPtr def = getTypeDefinition(spec.type(), spec.id(), loc);
ResourceCompiler compiler(def, body, verboseFlag);
ResourceCompiler compiler(*this, def, body, verboseFlag);
compiler.compile(); compiler.compile();
resources.addResource(Resource(spec.type(), spec.id(), compiler.resourceData(), spec.name(), spec.attr())); resources.addResource(Resource(spec.type(), spec.id(), compiler.resourceData(), spec.name(), spec.attr()));
} }
void RezWorld::addData(ResSpec spec, const std::string &data) void RezWorld::addData(ResSpec spec, const std::string &data, yy::location loc)
{ {
if(verboseFlag) if(verboseFlag)
std::cout << "DATA " << spec.type() << "(" << spec.id() << ", " << "\"" << spec.name() << "\"" << spec.attr() << ")" << std::endl; std::cout << "DATA " << spec.type() << "(" << spec.id() << ", " << "\"" << spec.name() << "\"" << spec.attr() << ")" << std::endl;
resources.addResource(Resource(spec.type(), spec.id(), data, spec.name(), spec.attr())); resources.addResource(Resource(spec.type(), spec.id(), data, spec.name(), spec.attr()));
} }
void RezWorld::problem(Diagnostic d)
{
std::cerr << d << std::endl;
}

View File

@ -9,6 +9,8 @@
#include "ResourceFork.h" #include "ResourceFork.h"
#include "ResSpec.h" #include "ResSpec.h"
class Diagnostic;
class RezWorld class RezWorld
{ {
friend class RezParser; friend class RezParser;
@ -19,18 +21,21 @@ class RezWorld
std::stack<SwitchFieldPtr> switches; std::stack<SwitchFieldPtr> switches;
Resources resources; Resources resources;
public: public:
RezWorld(); RezWorld();
void addTypeDefinition(TypeSpec spec, TypeDefinitionPtr type); void addTypeDefinition(TypeSpec spec, TypeDefinitionPtr type);
TypeDefinitionPtr getTypeDefinition(ResType type, int id); TypeDefinitionPtr getTypeDefinition(ResType type, int id, yy::location loc);
void addResource(ResSpec spec, CompoundExprPtr body); void addResource(ResSpec spec, CompoundExprPtr body, yy::location loc);
void addData(ResSpec spec, const std::string& data); void addData(ResSpec spec, const std::string& data, yy::location loc);
Resources& getResources() { return resources; } Resources& getResources() { return resources; }
bool verboseFlag; bool verboseFlag;
void problem(Diagnostic d);
}; };