mirror of
https://github.com/autc04/Retro68.git
synced 2025-02-07 18:31:06 +00:00
Rez: better error reporting
This commit is contained in:
parent
ee00fe1ec5
commit
d26d88f5ee
@ -13,5 +13,16 @@ Diagnostic::Diagnostic(Severity sev, std::string msg, yy::location loc)
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const Diagnostic &d)
|
||||
{
|
||||
return out << d.location << ": " << d.message;
|
||||
//return out << d.location << ": " << d.message;
|
||||
const yy::location& loc = d.location;
|
||||
if (loc.begin.filename)
|
||||
out << *loc.begin.filename << ':';
|
||||
out << loc.begin.line << ':' << loc.begin.column;
|
||||
out << ": ";
|
||||
if(d.severity >= Diagnostic::error)
|
||||
out << "error";
|
||||
else
|
||||
out << "warning";
|
||||
out << ": " << d.message;
|
||||
return out;
|
||||
}
|
||||
|
@ -147,7 +147,8 @@ int ResourceCompiler::getArrayIndex(const std::string &arrayName)
|
||||
|
||||
void ResourceCompiler::problem(Diagnostic d)
|
||||
{
|
||||
world.problem(d);
|
||||
if(prePass)
|
||||
world.problem(d);
|
||||
}
|
||||
|
||||
void ResourceCompiler::beginArrayScope(std::string &arrayName, int index)
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include <cassert>
|
||||
|
||||
#include "ResourceCompiler.h"
|
||||
|
||||
#include "Diagnostic.h"
|
||||
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, TypeSpec ts)
|
||||
@ -40,10 +40,20 @@ void FieldList::compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass)
|
||||
for(FieldPtr f : fields)
|
||||
{
|
||||
if(f->needsValue())
|
||||
f->compile(compound->getItem(i++), compiler, prePass);
|
||||
{
|
||||
if(i >= compound->size())
|
||||
compiler->problem(Diagnostic(Diagnostic::error,"not enough values specified", compound->location));
|
||||
else
|
||||
f->compile(compound->getItem(i++), compiler, prePass);
|
||||
}
|
||||
else
|
||||
f->compile(nullptr, compiler, prePass);
|
||||
}
|
||||
if(i < compound->size())
|
||||
{
|
||||
compiler->problem(Diagnostic(Diagnostic::error,"extra value specified",
|
||||
compound->getItem(i)->location));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
30
Rez/Rez.cc
30
Rez/Rez.cc
@ -10,6 +10,7 @@
|
||||
#include "ResourceFork.h"
|
||||
#include "BinaryIO.h"
|
||||
#include "ResourceFile.h"
|
||||
#include "Diagnostic.h"
|
||||
|
||||
namespace po = boost::program_options;
|
||||
namespace fs = boost::filesystem;
|
||||
@ -94,23 +95,34 @@ int main(int argc, const char *argv[])
|
||||
if(options.count("input"))
|
||||
for(std::string fn : options["input"].as<std::vector<std::string>>())
|
||||
{
|
||||
RezLexer lexer(fn);
|
||||
try
|
||||
{
|
||||
RezLexer lexer(world, fn);
|
||||
|
||||
if(options.count("define"))
|
||||
for(std::string define : options["define"].as<std::vector<std::string>>())
|
||||
lexer.addDefine(define);
|
||||
if(options.count("include"))
|
||||
for(std::string path : options["include"].as<std::vector<std::string>>())
|
||||
lexer.addIncludePath(path);
|
||||
if(options.count("define"))
|
||||
for(std::string define : options["define"].as<std::vector<std::string>>())
|
||||
lexer.addDefine(define);
|
||||
if(options.count("include"))
|
||||
for(std::string path : options["include"].as<std::vector<std::string>>())
|
||||
lexer.addIncludePath(path);
|
||||
|
||||
|
||||
RezParser parser(lexer, world);
|
||||
parser.parse();
|
||||
RezParser parser(lexer, world);
|
||||
parser.parse();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
world.problem(Diagnostic(Diagnostic::fatalError,"unknown error",yy::location(&fn)));
|
||||
}
|
||||
}
|
||||
|
||||
if(world.hadErrors)
|
||||
return 1;
|
||||
|
||||
rsrcFile.resources = world.getResources();
|
||||
rsrcFile.creator = options["creator"].as<std::string>();
|
||||
rsrcFile.type = options["type"].as<std::string>();
|
||||
rsrcFile.write();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
#include "RezLexerWaveToken.h"
|
||||
#include "RezWorld.h"
|
||||
#include "Diagnostic.h"
|
||||
|
||||
namespace wave = boost::wave;
|
||||
|
||||
@ -88,12 +90,13 @@ struct RezLexer::Priv
|
||||
}
|
||||
};
|
||||
|
||||
RezLexer::RezLexer(std::string filename)
|
||||
: RezLexer(filename, readContents(std::ifstream(filename)))
|
||||
RezLexer::RezLexer(RezWorld& world, std::string filename)
|
||||
: RezLexer(world, filename, readContents(std::ifstream(filename)))
|
||||
{
|
||||
}
|
||||
|
||||
RezLexer::RezLexer(std::string filename, const std::string &data)
|
||||
RezLexer::RezLexer(RezWorld& world, std::string filename, const std::string &data)
|
||||
: world(world), curFile(filename), lastLocation(&curFile)
|
||||
{
|
||||
pImpl.reset(new Priv(preFilter(data), filename));
|
||||
|
||||
@ -129,12 +132,32 @@ bool RezLexer::atEnd()
|
||||
|
||||
RezLexer::WaveToken RezLexer::nextWave()
|
||||
{
|
||||
if(pImpl->iter == pImpl->ctx.end())
|
||||
return WaveToken();
|
||||
else
|
||||
try
|
||||
{
|
||||
WaveToken tok = *pImpl->iter++;
|
||||
return tok;
|
||||
if(pImpl->iter == pImpl->ctx.end())
|
||||
return WaveToken();
|
||||
else
|
||||
{
|
||||
WaveToken tok = *pImpl->iter++;
|
||||
return tok;
|
||||
}
|
||||
}
|
||||
catch(preprocess_exception e)
|
||||
{
|
||||
curFile = e.file_name();
|
||||
auto yypos = yy::position(&curFile, e.line_no(), e.column_no());
|
||||
yy::location loc(yypos);
|
||||
lastLocation = loc;
|
||||
|
||||
world.problem(Diagnostic(
|
||||
e.severity_level(e.get_errorcode()) >= util::severity_error
|
||||
? Diagnostic::error
|
||||
: Diagnostic::warning,
|
||||
preprocess_exception::error_text(e.get_errorcode()), loc));
|
||||
if(e.is_recoverable())
|
||||
return nextWave();
|
||||
else
|
||||
return WaveToken();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,14 +4,19 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "location.hh"
|
||||
|
||||
class RezSymbol;
|
||||
class RezWorld;
|
||||
|
||||
class RezLexer
|
||||
{
|
||||
RezWorld& world;
|
||||
struct Priv;
|
||||
std::unique_ptr<Priv> pImpl;
|
||||
|
||||
std::string curFile;
|
||||
yy::location lastLocation;
|
||||
|
||||
class WaveToken;
|
||||
|
||||
@ -20,8 +25,8 @@ class RezLexer
|
||||
WaveToken peekWave();
|
||||
|
||||
public:
|
||||
RezLexer(std::string filename);
|
||||
RezLexer(std::string filename, const std::string& data);
|
||||
RezLexer(RezWorld& world, std::string filename);
|
||||
RezLexer(RezWorld& world, std::string filename, const std::string& data);
|
||||
~RezLexer();
|
||||
|
||||
RezSymbol nextToken();
|
||||
|
@ -155,6 +155,7 @@ RezSymbol RezLexer::nextToken()
|
||||
curFile = pos.get_file().c_str();
|
||||
auto yypos = yy::position(&curFile, pos.get_line(), pos.get_column());
|
||||
yy::location loc(yypos);
|
||||
lastLocation = loc;
|
||||
|
||||
if(tok == (UnknownTokenType | '"'))
|
||||
{
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include "Diagnostic.h"
|
||||
|
||||
RezWorld::RezWorld()
|
||||
: verboseFlag(false)
|
||||
: verboseFlag(false), hadErrors(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -53,5 +53,6 @@ void RezWorld::addData(ResSpec spec, const std::string &data, yy::location loc)
|
||||
|
||||
void RezWorld::problem(Diagnostic d)
|
||||
{
|
||||
hadErrors = true;
|
||||
std::cerr << d << std::endl;
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ public:
|
||||
Resources& getResources() { return resources; }
|
||||
|
||||
bool verboseFlag;
|
||||
bool hadErrors;
|
||||
|
||||
void problem(Diagnostic d);
|
||||
};
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "RezLexer.h"
|
||||
#include "RezParser.generated.hh"
|
||||
#include "ResourceCompiler.h"
|
||||
#include "RezWorld.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@ -26,7 +27,8 @@ BOOST_AUTO_TEST_SUITE(LexSuite)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(basicInt)
|
||||
{
|
||||
RezLexer lex("test", "123 0x456 0xaBcd9\n");
|
||||
RezWorld world;
|
||||
RezLexer lex(world, "test", "123 0x456 0xaBcd9\n");
|
||||
|
||||
CHECKSYM(RezParser::token::INTLIT, int, 123);
|
||||
CHECKSYM(RezParser::token::INTLIT, int, 0x456);
|
||||
@ -36,7 +38,8 @@ BOOST_AUTO_TEST_CASE(basicInt)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(alternateHex)
|
||||
{
|
||||
RezLexer lex("test", "$456 $aBcd9\n");
|
||||
RezWorld world;
|
||||
RezLexer lex(world, "test", "$456 $aBcd9\n");
|
||||
|
||||
CHECKSYM(RezParser::token::INTLIT, int, 0x456);
|
||||
CHECKSYM(RezParser::token::INTLIT, int, 0xabcd9);
|
||||
@ -45,7 +48,8 @@ BOOST_AUTO_TEST_CASE(alternateHex)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(noNewlineAtEOF)
|
||||
{
|
||||
RezLexer lex("test", "123 456");
|
||||
RezWorld world;
|
||||
RezLexer lex(world, "test", "123 456");
|
||||
CHECKSYM(RezParser::token::INTLIT, int, 123);
|
||||
CHECKSYM(RezParser::token::INTLIT, int, 456);
|
||||
CHECKSYM_(0);
|
||||
@ -53,7 +57,8 @@ BOOST_AUTO_TEST_CASE(noNewlineAtEOF)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(strings)
|
||||
{
|
||||
RezLexer lex("test", R"rez(
|
||||
RezWorld world;
|
||||
RezLexer lex(world, "test", R"rez(
|
||||
"Hello, world."
|
||||
"Foo \n"
|
||||
"\r Quux"
|
||||
|
@ -26,7 +26,7 @@ QDGlobals qd;
|
||||
pascal void ButtonFrameProc(DialogRef dlg, DialogItemIndex itemNo)
|
||||
{
|
||||
DialogItemType type;
|
||||
Handle itemH;
|
||||
Handle itemH;
|
||||
Rect box;
|
||||
|
||||
GetDialogItem(dlg, 1, &type, &itemH, &box);
|
||||
|
Loading…
x
Reference in New Issue
Block a user