--- a/src/parser.cpp Wed May 25 20:36:34 2022 +0300 +++ b/src/parser.cpp Mon Jun 06 22:01:22 2022 +0300 @@ -18,14 +18,7 @@ #include "model.h" #include "parser.h" -#include "linetypes/conditionaledge.h" -#include "linetypes/edge.h" -#include "linetypes/errorline.h" -#include "linetypes/metacommand.h" -#include "linetypes/object.h" -#include "linetypes/quadrilateral.h" -#include "linetypes/subfilereference.h" -#include "linetypes/triangle.h" +#include "ldrawalgorithm.h" struct BodyParseError { @@ -64,11 +57,12 @@ invertNext = true; continue; } - model.append(parseFromString(line)); + ModelElement element = parseLDrawLine(line); if (invertNext) { - model[model.size() - 1]->invert(nullptr); + element = inverted(element); } + model.append(element); invertNext = false; } } @@ -140,19 +134,13 @@ return result; } -static std::unique_ptr<ldraw::Object> parseType0Line( - const QString& line, - const QStringList& tokens) +static Comment parseType0Line(const QString& line) { - Q_UNUSED(tokens) - return std::make_unique<ldraw::MetaCommand>(line.mid(1).trimmed()); + return {line.mid(1).trimmed()}; } -static std::unique_ptr<ldraw::SubfileReference> parseType1Line( - const QString& line, - const QStringList& tokens) +static Colored<SubfileReference> parseType1Line(const QStringList& tokens) { - Q_UNUSED(line) constexpr int colorPosition = 1; constexpr int positionPosition = 2; // 2..4 constexpr int transformPosition = 5; // 5..13 @@ -164,15 +152,18 @@ const ldraw::Color color = colorFromString(tokens[colorPosition]); const glm::mat4 transform = matrixFromStrings(tokens, transformPosition, positionPosition); const QString& name = tokens[namePosition]; - return std::make_unique<ldraw::SubfileReference>(transform, name, color); + return Colored<SubfileReference>{ + { + .name = name, + .transformation = transform, + }, + color, + }; } -template<typename T, int NumVertices> -static std::unique_ptr<T> parsePolygon( - const QString& line, - const QStringList& tokens) +template<int NumVertices> +static auto parsePolygon(const QStringList& tokens) { - Q_UNUSED(line) constexpr int colorPosition = 1; auto vertexPosition = [](int n) { return 2 + 3*n; }; if (tokens.size() != 2 + 3 * NumVertices) @@ -185,10 +176,10 @@ { vertices[unsigned_cast(i)] = vertexFromStrings(tokens, vertexPosition(i)); } - return std::make_unique<T>(vertices, color); + return std::make_pair(vertices, color); } -std::unique_ptr<ldraw::Object> Parser::parseFromString(QString line) +ModelElement parseLDrawLine(QString line) { line = line.trimmed(); try @@ -196,7 +187,7 @@ const QStringList tokens = line.split(QRegExp{R"(\s+)"}); if (tokens.empty() or tokens == QStringList{{""}}) { - return std::make_unique<ldraw::Empty>(); + return Empty{}; } bool ok_code; const int code = tokens[0].toInt(&ok_code); @@ -207,23 +198,38 @@ switch (code) { case 0: - return parseType0Line(line, tokens); + return parseType0Line(line); case 1: - return parseType1Line(line, tokens); + return parseType1Line(tokens); case 2: - return parsePolygon<ldraw::Edge, 2>(line, tokens); + { + const auto pair = parsePolygon<2>(tokens); + return Colored<LineSegment>{{pair.first[0], pair.first[1]}, pair.second}; + } case 3: - return parsePolygon<ldraw::Triangle, 3>(line, tokens); + { + const auto pair = parsePolygon<3>(tokens); + return Colored<Triangle>{{pair.first[0], pair.first[1], pair.first[2]}, pair.second + }; + } case 4: - return parsePolygon<ldraw::Quadrilateral, 4>(line, tokens); + { + const auto pair = parsePolygon<4>(tokens); + const Quadrilateral quad{pair.first[0], pair.first[1], pair.first[2], pair.first[3]}; + return Colored<Quadrilateral>{quad, pair.second}; + } case 5: - return parsePolygon<ldraw::ConditionalEdge, 4>(line, tokens); + { + const auto pair = parsePolygon<4>(tokens); + const ConditionalEdge cedge{pair.first[0], pair.first[1], pair.first[2], pair.first[3]}; + return Colored<ConditionalEdge>{cedge, pair.second}; + } default: throw BodyParseError{utility::format("bad line type '%1'", code)}; } } catch(const BodyParseError& error) { - return std::make_unique<ldraw::ErrorLine>(line, error.message); + return ParseError{line}; } }