Big YAML parser cleanup
This commit is contained in:
parent
687de91a81
commit
d20e4154fe
13 changed files with 409 additions and 207 deletions
|
@ -5,12 +5,16 @@
|
|||
Import('env')
|
||||
|
||||
|
||||
objs = []
|
||||
|
||||
subdirs = [
|
||||
# TODO: Put subdirectories here.
|
||||
'yaml',
|
||||
]
|
||||
|
||||
for d in subdirs:
|
||||
env.SConscript(env.Dir(d).File('SConscript'), {'env': env})
|
||||
dir_objs = env.SConscript(env.Dir(d).File('SConscript'), {'env': env})
|
||||
print dir_objs
|
||||
objs.extend(dir_objs)
|
||||
|
||||
|
||||
files = [
|
||||
|
@ -26,11 +30,10 @@ files = [
|
|||
'writer_png.cc',
|
||||
]
|
||||
|
||||
objs = []
|
||||
for f in files:
|
||||
objs.append(env.Object(f))
|
||||
|
||||
lib = env.Library('charles', files)
|
||||
lib = env.Library('charles', objs)
|
||||
prog = env.Program('charles', ['charles.cc'], LIBS=[lib, 'png', 'yaml'])
|
||||
env.Alias('charles', prog)
|
||||
|
||||
|
|
|
@ -15,228 +15,47 @@
|
|||
|
||||
#include "reader_yaml.hh"
|
||||
|
||||
|
||||
struct Parser;
|
||||
typedef std::stack<Parser *> ParserStack;
|
||||
#include "yaml/parsers.hh"
|
||||
#include "yaml/scene_parser.hh"
|
||||
|
||||
|
||||
struct Parser
|
||||
{
|
||||
Parser(Scene& scene,
|
||||
ParserStack& parsers)
|
||||
: mScene(scene),
|
||||
mParsers(parsers)
|
||||
{ }
|
||||
|
||||
virtual
|
||||
~Parser()
|
||||
{ }
|
||||
|
||||
virtual void
|
||||
handle_event(yaml_event_t& event)
|
||||
{
|
||||
/* TODO: Shouldn't ever get here. */
|
||||
abort();
|
||||
}
|
||||
|
||||
bool
|
||||
done()
|
||||
const
|
||||
{
|
||||
return mDone;
|
||||
}
|
||||
|
||||
protected:
|
||||
Scene& mScene;
|
||||
ParserStack &mParsers;
|
||||
bool mDone;
|
||||
};
|
||||
|
||||
|
||||
struct SceneParser
|
||||
#if 0
|
||||
struct ObjectParser
|
||||
: public Parser
|
||||
{
|
||||
SceneParser(Scene& scene, ParserStack& parsers)
|
||||
ObjectParser(Scene& scene, ParserStack& parsers)
|
||||
: Parser(scene, parsers),
|
||||
mSection(SceneParser::NoSection),
|
||||
mDimension(SceneParser::NoDimension)
|
||||
mSection(NoSection)
|
||||
{
|
||||
printf("SceneParser\n");
|
||||
printf("ObjectParser\n");
|
||||
}
|
||||
|
||||
~SceneParser()
|
||||
~ObjectParser()
|
||||
{
|
||||
printf("~SceneParser\n");
|
||||
printf("~ObjectParser\n");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
handle_event(yaml_event_t& event)
|
||||
{
|
||||
switch (mSection) {
|
||||
case NoSection:
|
||||
handle_toplevel_event(event);
|
||||
break;
|
||||
case CameraSection:
|
||||
handle_camera_event(event);
|
||||
case TypeSection:
|
||||
break;
|
||||
case DimensionsSection:
|
||||
handle_dimensions_event(event);
|
||||
break;
|
||||
case ObjectsSection:
|
||||
handle_objects_event(event);
|
||||
break;
|
||||
default:
|
||||
/* TODO: WHAT. Fail gracefully. */
|
||||
abort();
|
||||
case OriginSection:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
handle_toplevel_event(yaml_event_t& event)
|
||||
{
|
||||
static const std::string CAMERA = "camera";
|
||||
static const std::string DIMENSIONS = "dimensions";
|
||||
static const std::string OBJECTS = "objects";
|
||||
|
||||
if (event.type == YAML_MAPPING_END_EVENT) {
|
||||
mDone = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.type != YAML_SCALAR_EVENT) {
|
||||
/* TODO: Invalid event type for top-level Scene. Fail. */
|
||||
abort();
|
||||
}
|
||||
|
||||
std::string key = (char *)event.data.scalar.value;
|
||||
if (key == CAMERA) {
|
||||
mSection = SceneParser::CameraSection;
|
||||
}
|
||||
else if (key == DIMENSIONS) {
|
||||
mSection = SceneParser::DimensionsSection;
|
||||
}
|
||||
else if (key == OBJECTS) {
|
||||
mSection = SceneParser::ObjectsSection;
|
||||
}
|
||||
else {
|
||||
/* TODO: Invalid key. Fail. */
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
handle_camera_event(yaml_event_t& event)
|
||||
{ }
|
||||
|
||||
void
|
||||
handle_dimensions_event(yaml_event_t& event)
|
||||
{
|
||||
int dim;
|
||||
|
||||
switch (mDimension) {
|
||||
case NoDimension:
|
||||
switch (event.type) {
|
||||
case YAML_SEQUENCE_START_EVENT:
|
||||
printf(" start dimensions\n");
|
||||
mDimension = SceneParser::WidthDimension;
|
||||
break;
|
||||
default:
|
||||
/* TODO: Fail gracefully. */
|
||||
abort();
|
||||
}
|
||||
break;
|
||||
case WidthDimension:
|
||||
switch (event.type) {
|
||||
case YAML_SCALAR_EVENT:
|
||||
printf(" width = %s\n", event.data.scalar.value);
|
||||
sscanf((char *)event.data.scalar.value, "%d", &dim);
|
||||
mScene.set_width(dim);
|
||||
mDimension = SceneParser::HeightDimension;
|
||||
break;
|
||||
default:
|
||||
/* TODO: Fail gracefully. */
|
||||
abort();
|
||||
}
|
||||
break;
|
||||
case HeightDimension:
|
||||
if (event.type == YAML_SCALAR_EVENT) {
|
||||
printf(" height = %s\n", event.data.scalar.value);
|
||||
sscanf((char *)event.data.scalar.value, "%d", &dim);
|
||||
mScene.set_height(dim);
|
||||
mDimension = SceneParser::DoneDimension;
|
||||
}
|
||||
else {
|
||||
/* TODO: Fail gracefully. */
|
||||
abort();
|
||||
}
|
||||
break;
|
||||
case DoneDimension:
|
||||
if (event.type == YAML_SEQUENCE_END_EVENT) {
|
||||
printf(" end dimensions\n");
|
||||
mSection = NoSection;
|
||||
}
|
||||
else {
|
||||
/* TODO: Fail gracefully. */
|
||||
abort();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
handle_objects_event(yaml_event_t& event)
|
||||
{ }
|
||||
|
||||
private:
|
||||
enum {
|
||||
NoSection,
|
||||
CameraSection,
|
||||
DimensionsSection,
|
||||
ObjectsSection,
|
||||
TypeSection,
|
||||
OriginSection,
|
||||
} mSection;
|
||||
|
||||
enum {
|
||||
NoDimension,
|
||||
HeightDimension,
|
||||
WidthDimension,
|
||||
DoneDimension
|
||||
} mDimension;
|
||||
};
|
||||
|
||||
|
||||
struct DocumentParser
|
||||
: public Parser
|
||||
{
|
||||
DocumentParser(Scene& scene,
|
||||
ParserStack& parsers)
|
||||
: Parser(scene, parsers)
|
||||
{
|
||||
printf("DocumentParser\n");
|
||||
}
|
||||
|
||||
~DocumentParser()
|
||||
{
|
||||
printf("~DocumentParser\n");
|
||||
}
|
||||
|
||||
void
|
||||
handle_event(yaml_event_t& event)
|
||||
{
|
||||
switch (event.type) {
|
||||
case YAML_DOCUMENT_END_EVENT:
|
||||
mDone = true;
|
||||
break;
|
||||
case YAML_MAPPING_START_EVENT:
|
||||
mParsers.push(new SceneParser(mScene, mParsers));
|
||||
break;
|
||||
default:
|
||||
/* TODO: Fail gracefully. */
|
||||
abort();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
ssize_t
|
||||
|
@ -255,7 +74,7 @@ YAMLReader::read_file(const std::string& filename)
|
|||
printf("Reading file: %s\n", filename.c_str());
|
||||
yaml_parser_set_input_file(&parser, yaml_infile);
|
||||
|
||||
ParserStack parsers;
|
||||
yaml::ParserStack parsers;
|
||||
bool success = true;
|
||||
bool done = false;
|
||||
yaml_event_t event;
|
||||
|
@ -280,16 +99,22 @@ YAMLReader::read_file(const std::string& filename)
|
|||
|
||||
case YAML_DOCUMENT_START_EVENT:
|
||||
printf("YAML_DOCUMENT_START_EVENT\n");
|
||||
parsers.push(new DocumentParser(mScene, parsers));
|
||||
break;
|
||||
case YAML_DOCUMENT_END_EVENT:
|
||||
printf("YAML_DOCUMENT_END_EVENT\n");
|
||||
break;
|
||||
|
||||
case YAML_MAPPING_START_EVENT:
|
||||
parsers.push(new yaml::SceneParser(mScene, parsers));
|
||||
break;
|
||||
|
||||
default:
|
||||
if (parsers.top()->done()) {
|
||||
delete parsers.top();
|
||||
parsers.pop();
|
||||
}
|
||||
if (!parsers.empty()) {
|
||||
parsers.top()->handle_event(event);
|
||||
parsers.top()->HandleEvent(event);
|
||||
if (parsers.top()->GetDone()) {
|
||||
delete parsers.top();
|
||||
parsers.pop();
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
|
18
src/yaml/SConscript
Normal file
18
src/yaml/SConscript
Normal file
|
@ -0,0 +1,18 @@
|
|||
# SConscript
|
||||
# vim: set ft=python:
|
||||
# Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
Import('env')
|
||||
|
||||
|
||||
files = [
|
||||
'parsers.cc',
|
||||
'scene_parser.cc',
|
||||
]
|
||||
|
||||
objs = []
|
||||
for f in files:
|
||||
objs.append(env.Object(f))
|
||||
|
||||
print objs
|
||||
Return('objs')
|
0
src/yaml/camera_parser.cc
Normal file
0
src/yaml/camera_parser.cc
Normal file
0
src/yaml/camera_parser.hh
Normal file
0
src/yaml/camera_parser.hh
Normal file
0
src/yaml/object_parser.cc
Normal file
0
src/yaml/object_parser.cc
Normal file
0
src/yaml/object_parser.hh
Normal file
0
src/yaml/object_parser.hh
Normal file
72
src/yaml/parsers.cc
Normal file
72
src/yaml/parsers.cc
Normal file
|
@ -0,0 +1,72 @@
|
|||
/* parsers.cc
|
||||
* vim: set tw=80:
|
||||
* Eryn Wells <eryn@erynwells.me>
|
||||
*/
|
||||
/**
|
||||
* YAML parser superclasses.
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "yaml.h"
|
||||
|
||||
#include "parsers.hh"
|
||||
|
||||
|
||||
namespace yaml {
|
||||
|
||||
Parser::Parser(Scene& scene,
|
||||
ParserStack& parsers)
|
||||
: mScene(scene),
|
||||
mParsers(parsers)
|
||||
{ }
|
||||
|
||||
|
||||
Parser::~Parser()
|
||||
{ }
|
||||
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunused-parameter"
|
||||
|
||||
void
|
||||
Parser::HandleEvent(yaml_event_t& event)
|
||||
{
|
||||
/* Shouldn't ever get here. */
|
||||
assert(false);
|
||||
}
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
|
||||
void
|
||||
Parser::SetDone(bool done)
|
||||
{
|
||||
mDone = done;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Parser::GetDone()
|
||||
const
|
||||
{
|
||||
return mDone;
|
||||
}
|
||||
|
||||
|
||||
Scene&
|
||||
Parser::GetScene()
|
||||
const
|
||||
{
|
||||
return mScene;
|
||||
}
|
||||
|
||||
|
||||
ParserStack&
|
||||
Parser::GetParsers()
|
||||
const
|
||||
{
|
||||
return mParsers;
|
||||
}
|
||||
|
||||
} /* namespace yaml */
|
99
src/yaml/parsers.hh
Normal file
99
src/yaml/parsers.hh
Normal file
|
@ -0,0 +1,99 @@
|
|||
/* parsers.hh
|
||||
* vim: set tw=80:
|
||||
* Eryn Wells <eryn@erynwells.me>
|
||||
*/
|
||||
/**
|
||||
* Some top-level YAML parser objects.
|
||||
*/
|
||||
|
||||
#ifndef __YAML_PARSERS_HH__
|
||||
#define __YAML_PARSERS_HH__
|
||||
|
||||
#include <functional>
|
||||
#include <stack>
|
||||
|
||||
#include "yaml.h"
|
||||
|
||||
#include "scene.h"
|
||||
|
||||
|
||||
namespace yaml {
|
||||
|
||||
struct Parser;
|
||||
typedef std::stack<Parser*> ParserStack;
|
||||
|
||||
|
||||
/**
|
||||
* A Parser handles parsing a chunk of YAML, updating its mScene member as
|
||||
* necessary.
|
||||
*/
|
||||
struct Parser
|
||||
{
|
||||
/** Constructor */
|
||||
Parser(Scene& scene, ParserStack& parsers);
|
||||
|
||||
/** Destructor */
|
||||
virtual ~Parser();
|
||||
|
||||
/**
|
||||
* Called by the parser event loop to handle a libyaml parser event.
|
||||
*
|
||||
* @param [in] event A libyaml parser event object
|
||||
*/
|
||||
virtual void HandleEvent(yaml_event_t& event);
|
||||
|
||||
|
||||
/** Set the done flag. */
|
||||
void SetDone(bool done);
|
||||
|
||||
/**
|
||||
* Returns true if the parser is done parsing.
|
||||
*
|
||||
* @returns `true` if done, `false` if not
|
||||
*/
|
||||
bool GetDone() const;
|
||||
|
||||
protected:
|
||||
Scene& GetScene() const;
|
||||
ParserStack& GetParsers() const;
|
||||
|
||||
private:
|
||||
/** The Scene being described by the YAML this parser is parsing. */
|
||||
Scene& mScene;
|
||||
|
||||
/** The stack of parsers. */
|
||||
ParserStack& mParsers;
|
||||
|
||||
/** `true` if the parser is done parsing */
|
||||
bool mDone;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* UtilityParsers handle small reusable bits of YAML and their constructors take
|
||||
* a C++11 lambda, which will be called back with the result of the parsed data.
|
||||
*/
|
||||
template<typename CallbackType>
|
||||
struct UtilityParser
|
||||
: public Parser
|
||||
{
|
||||
typedef std::function<CallbackType> CallbackFunction;
|
||||
|
||||
UtilityParser(Scene& scene,
|
||||
ParserStack& parsers,
|
||||
CallbackFunction callback)
|
||||
: Parser(scene, parsers),
|
||||
mCallback(callback)
|
||||
{ }
|
||||
|
||||
virtual
|
||||
~UtilityParser()
|
||||
{ }
|
||||
|
||||
private:
|
||||
CallbackFunction mCallback;
|
||||
};
|
||||
|
||||
} /* namespace yaml */
|
||||
|
||||
#endif /* __YAML_PARSERS_HH__ */
|
140
src/yaml/scene_parser.cc
Normal file
140
src/yaml/scene_parser.cc
Normal file
|
@ -0,0 +1,140 @@
|
|||
/* scene_parser.cc
|
||||
* vim: set tw=80:
|
||||
* Eryn Wells <eryn@erynwells.me>
|
||||
*/
|
||||
/**
|
||||
* A SceneParser parses a YAML Scene object.
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
|
||||
#include "scene_parser.hh"
|
||||
|
||||
|
||||
namespace yaml {
|
||||
|
||||
SceneParser::SceneParser(Scene& scene,
|
||||
ParserStack& parsers)
|
||||
: Parser(scene, parsers),
|
||||
mSection(SceneParser::NoSection),
|
||||
mDimension(SceneParser::NoDimension)
|
||||
{ }
|
||||
|
||||
|
||||
SceneParser::~SceneParser()
|
||||
{ }
|
||||
|
||||
|
||||
void
|
||||
SceneParser::HandleEvent(yaml_event_t& event)
|
||||
{
|
||||
switch (mSection) {
|
||||
case NoSection:
|
||||
HandleTopLevelEvent(event);
|
||||
break;
|
||||
case CameraSection:
|
||||
break;
|
||||
case DimensionsSection:
|
||||
HandleDimensionsEvent(event);
|
||||
break;
|
||||
case ObjectsSection:
|
||||
break;
|
||||
default:
|
||||
/* TODO: WHAT. Fail gracefully. */
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SceneParser::HandleTopLevelEvent(yaml_event_t& event)
|
||||
{
|
||||
static const std::string CAMERA = "camera";
|
||||
static const std::string DIMENSIONS = "dimensions";
|
||||
static const std::string OBJECTS = "objects";
|
||||
|
||||
if (event.type == YAML_MAPPING_END_EVENT) {
|
||||
SetDone(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.type != YAML_SCALAR_EVENT) {
|
||||
/* TODO: Invalid event type for top-level Scene. Fail. */
|
||||
abort();
|
||||
}
|
||||
|
||||
std::string key = (char *)event.data.scalar.value;
|
||||
if (key == CAMERA) {
|
||||
mSection = SceneParser::CameraSection;
|
||||
}
|
||||
else if (key == DIMENSIONS) {
|
||||
mSection = SceneParser::DimensionsSection;
|
||||
}
|
||||
else if (key == OBJECTS) {
|
||||
mSection = SceneParser::ObjectsSection;
|
||||
}
|
||||
else {
|
||||
/* TODO: Invalid key. Fail. */
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SceneParser::HandleDimensionsEvent(yaml_event_t& event)
|
||||
{
|
||||
int dim;
|
||||
|
||||
switch (mDimension) {
|
||||
case NoDimension:
|
||||
switch (event.type) {
|
||||
case YAML_SEQUENCE_START_EVENT:
|
||||
printf(" start dimensions\n");
|
||||
mDimension = SceneParser::WidthDimension;
|
||||
break;
|
||||
default:
|
||||
/* TODO: Fail gracefully. */
|
||||
abort();
|
||||
}
|
||||
break;
|
||||
case WidthDimension:
|
||||
switch (event.type) {
|
||||
case YAML_SCALAR_EVENT:
|
||||
printf(" width = %s\n", event.data.scalar.value);
|
||||
sscanf((char *)event.data.scalar.value, "%d", &dim);
|
||||
GetScene().set_width(dim);
|
||||
mDimension = SceneParser::HeightDimension;
|
||||
break;
|
||||
default:
|
||||
/* TODO: Fail gracefully. */
|
||||
abort();
|
||||
}
|
||||
break;
|
||||
case HeightDimension:
|
||||
if (event.type == YAML_SCALAR_EVENT) {
|
||||
printf(" height = %s\n", event.data.scalar.value);
|
||||
sscanf((char *)event.data.scalar.value, "%d", &dim);
|
||||
GetScene().set_height(dim);
|
||||
mDimension = SceneParser::DoneDimension;
|
||||
}
|
||||
else {
|
||||
/* TODO: Fail gracefully. */
|
||||
abort();
|
||||
}
|
||||
break;
|
||||
case DoneDimension:
|
||||
if (event.type == YAML_SEQUENCE_END_EVENT) {
|
||||
printf(" end dimensions\n");
|
||||
mSection = NoSection;
|
||||
}
|
||||
else {
|
||||
/* TODO: Fail gracefully. */
|
||||
abort();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace yaml */
|
45
src/yaml/scene_parser.hh
Normal file
45
src/yaml/scene_parser.hh
Normal file
|
@ -0,0 +1,45 @@
|
|||
/* scene_parser.hh
|
||||
* vim: set tw=80:
|
||||
* Eryn Wells <eryn@erynwells.me>
|
||||
*/
|
||||
/**
|
||||
* A SceneParser parses a YAML Scene object.
|
||||
*/
|
||||
|
||||
#ifndef __YAML_SCENE_PARSER_HH__
|
||||
#define __YAML_SCENE_PARSER_HH__
|
||||
|
||||
#include "parsers.hh"
|
||||
|
||||
|
||||
namespace yaml {
|
||||
|
||||
struct SceneParser
|
||||
: public Parser
|
||||
{
|
||||
SceneParser(Scene& scene, ParserStack& parsers);
|
||||
~SceneParser();
|
||||
|
||||
void HandleEvent(yaml_event_t& event);
|
||||
void HandleTopLevelEvent(yaml_event_t& event);
|
||||
void HandleDimensionsEvent(yaml_event_t& event);
|
||||
|
||||
private:
|
||||
enum {
|
||||
NoSection,
|
||||
CameraSection,
|
||||
DimensionsSection,
|
||||
ObjectsSection,
|
||||
} mSection;
|
||||
|
||||
enum {
|
||||
NoDimension,
|
||||
HeightDimension,
|
||||
WidthDimension,
|
||||
DoneDimension
|
||||
} mDimension;
|
||||
};
|
||||
|
||||
} /* namespace yaml */
|
||||
|
||||
#endif /* __YAML_SCENE_PARSER_HH__ */
|
0
src/yaml/vector_parser.cc
Normal file
0
src/yaml/vector_parser.cc
Normal file
0
src/yaml/vector_parser.hh
Normal file
0
src/yaml/vector_parser.hh
Normal file
Loading…
Add table
Add a link
Reference in a new issue