Skip to content

Commit

Permalink
Improve parsers
Browse files Browse the repository at this point in the history
  • Loading branch information
albin-johansson committed Dec 15, 2023
1 parent f94d8d0 commit f3e6124
Show file tree
Hide file tree
Showing 15 changed files with 172 additions and 126 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

#pragma once

#include <utility> // to_underlying
#include <system_error> // error_category, error_code
#include <utility> // to_underlying

#include "tactile/foundation/api.hpp"
#include "tactile/foundation/functional/expected.hpp"
Expand All @@ -18,29 +19,19 @@ enum class SaveFormatError : int {
kUnknown, ///< An unknown error occurred.
kBadFile, ///< Something went wrong when loading or saving a file.
kUnsupportedFormat, ///< Tried to load/save file with unknown format.

kMissingKey, ///< A required attribute was not found in a save file.

kUnsupportedOrientation, ///< An unsupported map orientation was detected.
kUnsupportedLayerType, ///< An unsupported layer type was detected.
kUnsupportedPropertyType, ///< An unsupported property type was detected.
kMissingKey, ///< A required attribute was not found in a save file.
kUnsupportedVersion,
kUnsupportedOrientation,
kUnsupportedLayerType,
kUnsupportedObjectType,
kUnsupportedTileEncoding, ///< An unsupported tile data encoding was detected.
kUnsupportedCompressionMode, ///< An unsupported compression mode was detected.

kBadColorProperty, ///< An invalid color property value was detected.
kBadTileLayerData, ///< Corrupt tile layer data was detected.
kBadCompressionMode, ///< An invalid compression mode was detected.

kCorruptPropertyValue,
kUnsupportedPropertyType,
kUnsupportedTileEncoding,
kUnsupportedCompression,
kBadTileLayerData,
kBadPropertyValue,
kPropertyWithoutValue,

kInvalidTileFormat,

kMapMissingWidth,
kMapMissingHeight,
kMapMissingTileWidth,
kMapMissingTileHeight,
kInvalidComponentType,
kInvalidTileFormat
};

[[nodiscard]]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,22 @@ class SaveFormatErrorCategory final : public std::error_category {
case kUnknown: return "an unknown error occurred";
case kBadFile: return "could not read or save a file";
case kUnsupportedFormat: return "a file uses an unsupported file format";
case kMissingKey: return "an expected attribute was not found in a save file";
case kMissingKey: return "an expected element was not found in a save file";
case kUnsupportedVersion: return "unsupported save format version";
case kUnsupportedOrientation: return "detected an unsupported map orientation";
case kUnsupportedLayerType: return "detected an unsupported layer type";
case kUnsupportedObjectType: return "detected an unsupported object type";
case kUnsupportedPropertyType: return "detected an unsupported property type";
case kUnsupportedCompressionMode: return "detected an unsupported compression mode";
case kUnsupportedTileEncoding: return "detected an unsupported tile encoding";
case kBadColorProperty: return "detected an invalid color property";
case kBadTileLayerData: return "detected an invalid tile layer data";
case kBadCompressionMode: return "detected an invalid compression mode";
case kUnsupportedCompression: return "detected an unsupported compression mode";
case kBadTileLayerData: return "detected invalid tile layer data";
case kBadPropertyValue: return "detected invalid property data";
case kPropertyWithoutValue: return "detected property without a value";
case kInvalidComponentType: return "detected attached component with invalid type";
case kInvalidTileFormat: return "invalid tile format configuration";
}

return "unknown";
return "?";
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include "tactile/foundation/container/file_path.hpp"
#include "tactile/foundation/container/string.hpp"
#include "tactile/foundation/functional/maybe.hpp"
#include "tactile/foundation/functional/result.hpp"
#include "tactile/foundation/io/save/save_format_error.hpp"
#include "tactile/foundation/log/logger.hpp"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@

namespace tactile::yml_format {

[[nodiscard]]
TACTILE_YML_FORMAT_API auto parse_attached_component_attribute(
const YAML::Node& attached_component_node,
const ir::Component& prototype) -> Result<ir::NamedAttribute>;

[[nodiscard]]
TACTILE_YML_FORMAT_API auto parse_attached_component_attributes(
const YAML::Node& attached_component_node,
const ir::Component& prototype) -> Result<Vector<ir::NamedAttribute>>;

[[nodiscard]]
TACTILE_YML_FORMAT_API auto parse_attached_component(
const YAML::Node& attached_component_node,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <sstream> // stringstream

#include "tactile/foundation/io/tile_matrix_encoding.hpp"
#include "tactile/foundation/log/logger.hpp"
#include "tactile/tactile-yml-format/emit/meta_emitter.hpp"
#include "tactile/tactile-yml-format/emit/object_emitter.hpp"

Expand Down Expand Up @@ -46,10 +47,16 @@ void emit_tile_layer_data(YAML::Emitter& emitter,
emit_plain_text_tile_layer_data(emitter, layer, options);
}
else {
emitter << YAML::Key << "data";
emitter << YAML::Value
<< base64_encode_tile_matrix(layer.tiles, map.tile_format.compression)
.value(); // FIXME
if (const auto encoded_tiles =
base64_encode_tile_matrix(layer.tiles, map.tile_format.compression)) {
emitter << YAML::Key << "data";
emitter << YAML::Value << *encoded_tiles;
}
else {
// TODO return result as well
TACTILE_LOG_ERROR("Could not emit tile layer data: {}",
encoded_tiles.error().message());
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,64 +4,89 @@

#include <utility> // move

#include "tactile/foundation/io/save/save_format_error.hpp"
#include "tactile/foundation/log/logger.hpp"
#include "tactile/tactile-yml-format/parse/common.hpp"
#include "tactile/tactile-yml-format/parse/property_parser.hpp"

namespace tactile::yml_format {

auto parse_attached_component_attribute(const YAML::Node& attached_component_node,
const ir::Component& prototype_component)
const ir::Component& prototype)
-> Result<ir::NamedAttribute>
{
ir::NamedAttribute attribute {};
return parse_to(attached_component_node, "name", attribute.name)
.and_then([&] {
const auto attr_type = get_attribute_type(prototype_component, attribute.name);
return parse_property_value(attached_component_node, attr_type.value()); // FIXME
.and_then([&] -> Result<Attribute> {
if (const auto attr_type = get_attribute_type(prototype, attribute.name)) {
return parse_property_value(attached_component_node, *attr_type);
}

return unexpected(
make_save_format_error(SaveFormatError::kUnsupportedPropertyType));
})
.and_then([&](Attribute value) {
.and_then([&](Attribute&& value) {
attribute.value = std::move(value);
return kOK;
})
.transform([&] { return std::move(attribute); });
}

auto parse_attached_component(const YAML::Node& attached_component_node,
const ir::Map& map) -> Result<ir::AttachedComponent>
auto parse_attached_component_attributes(const YAML::Node& attached_component_node,
const ir::Component& prototype)
-> Result<Vector<ir::NamedAttribute>>
{
TACTILE_LOG_TRACE("Parsing attached component node at {}:{}...",
attached_component_node.Mark().line,
attached_component_node.Mark().column);

ir::AttachedComponent attached_component {};
parse_to(attached_component_node, "type", attached_component.type); // FIXME

const auto prototype_component_iter =
std::find_if(map.components.begin(),
map.components.end(),
[&](const ir::Component& component) {
return component.name == attached_component.type;
});

if (prototype_component_iter == map.components.end()) {
// TODO NoSuchComponent
return unexpected(make_save_format_error(SaveFormatError::kUnknown));
}
Vector<ir::NamedAttribute> attributes {};

if (const auto value_seq = attached_component_node["values"]) {
attributes.reserve(value_seq.size());

for (const auto& value_node : value_seq) {
if (auto attribute =
parse_attached_component_attribute(value_node, *prototype_component_iter)) {
attached_component.attributes.push_back(std::move(*attribute));
if (auto attribute = parse_attached_component_attribute(value_node, prototype)) {
attributes.push_back(std::move(*attribute));
}
else {
return propagate_unexpected(attribute);
}
}
}

return attached_component;
return attributes;
}

auto parse_attached_component(const YAML::Node& attached_component_node,
const ir::Map& map) -> Result<ir::AttachedComponent>
{
TACTILE_LOG_TRACE("Parsing attached component node at {}:{}",
attached_component_node.Mark().line,
attached_component_node.Mark().column);

ir::AttachedComponent attached_component {};

return parse_to(attached_component_node, "type", attached_component.type)
.and_then([&]() -> Result<const ir::Component*> {
const auto prototype_component_iter =
std::find_if(map.components.begin(),
map.components.end(),
[&](const ir::Component& component) {
return component.name == attached_component.type;
});

if (prototype_component_iter == map.components.end()) {
return unexpected(
make_save_format_error(SaveFormatError::kInvalidComponentType));
}

return &*prototype_component_iter;
})
.and_then([&](const ir::Component* prototype) {
return parse_attached_component_attributes(attached_component_node, *prototype);
})
.and_then([&](Vector<ir::NamedAttribute>&& attributes) {
attached_component.attributes = std::move(attributes);
return kOK;
})
.transform([&] { return std::move(attached_component); });
}

auto parse_attached_components(const YAML::Node& context_node, const ir::Map& map)
Expand All @@ -74,7 +99,7 @@ auto parse_attached_components(const YAML::Node& context_node, const ir::Map& ma
return attached_components;
}

TACTILE_LOG_TRACE("Parsing attached component sequence at {}:{}...",
TACTILE_LOG_TRACE("Parsing attached component sequence at {}:{}",
attached_component_seq.Mark().line,
attached_component_seq.Mark().column);

Expand Down Expand Up @@ -123,7 +148,7 @@ auto parse_component_attributes(const YAML::Node& component_node)
{
Vector<ir::NamedAttribute> attributes {};

if (auto attribute_seq = component_node["attributes"]) {
if (const auto attribute_seq = component_node["attributes"]) {
attributes.reserve(attribute_seq.size());

for (const auto& attribute_node : attribute_seq) {
Expand All @@ -141,15 +166,15 @@ auto parse_component_attributes(const YAML::Node& component_node)

auto parse_component(const YAML::Node& component_node) -> Result<ir::Component>
{
TACTILE_LOG_TRACE("Parsing component node at {}:{}...",
TACTILE_LOG_TRACE("Parsing component node at {}:{}",
component_node.Mark().line,
component_node.Mark().column);

ir::Component component {};

return parse_to(component_node, "name", component.name)
.and_then([&] { return parse_component_attributes(component_node); })
.and_then([&](Vector<ir::NamedAttribute> attributes) {
.and_then([&](Vector<ir::NamedAttribute>&& attributes) {
component.attributes = std::move(attributes);
return kOK;
})
Expand All @@ -160,10 +185,11 @@ auto parse_components(const YAML::Node& root_node) -> Result<Vector<ir::Componen
{
Vector<ir::Component> components {};

if (auto component_seq = root_node["component-definitions"]) {
TACTILE_LOG_TRACE("Parsing component sequence at {}:{}...",
if (const auto component_seq = root_node["component-definitions"]) {
TACTILE_LOG_TRACE("Parsing component sequence at {}:{}",
component_seq.Mark().line,
component_seq.Mark().column);
components.reserve(component_seq.size());

for (const auto& component_node : component_seq) {
if (auto component = parse_component(component_node)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ auto parse_group_layer_data(const YAML::Node& layer_node,

auto parse_layer(const YAML::Node& layer_node, const ir::Map& map) -> Result<ir::Layer>
{
TACTILE_LOG_TRACE("Parsing layer node at {}:{}...",
TACTILE_LOG_TRACE("Parsing layer node at {}:{}",
layer_node.Mark().line,
layer_node.Mark().column);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ auto parse_map(String map_name,
const YAML::Node& root_node,
const SaveFormatReadOptions& options) -> Result<ir::Map>
{
TACTILE_LOG_TRACE("Parsing map node at {}:{}...",
TACTILE_LOG_TRACE("Parsing map node at {}:{}",
root_node.Mark().line,
root_node.Mark().column);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ auto parse_metadata(const YAML::Node& context_node,
const ir::Map& map,
ir::Metadata& metadata) -> Result<void>
{
TACTILE_LOG_TRACE("Parsing metadata from node at {}:{}...",
TACTILE_LOG_TRACE("Parsing metadata from node at {}:{}",
context_node.Mark().line,
context_node.Mark().column);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ auto parse_object_type(const StringView name) -> Result<ObjectType>

auto parse_object(const YAML::Node& object_node, const ir::Map& map) -> Result<ir::Object>
{
TACTILE_LOG_TRACE("Parsing object node at {}:{}...",
TACTILE_LOG_TRACE("Parsing object node at {}:{}",
object_node.Mark().line,
object_node.Mark().column);

Expand Down
Loading

0 comments on commit f3e6124

Please sign in to comment.