src/parser.cpp

changeset 200
ca23936b455b
parent 183
97b591813c8b
child 201
5d201ee4a9c3
--- 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};
 	}
 }

mercurial