--- a/src/parser.h Mon Jul 04 15:37:22 2022 +0300 +++ b/src/parser.h Mon Jul 04 19:53:13 2022 +0300 @@ -20,15 +20,124 @@ #include "src/basics.h" #include "src/model.h" -class Parser : public QObject +struct TextRange { - Q_OBJECT -public: - Parser(QTextStream& stream, QObject* parent = nullptr); - void parseBody(Model &model); -private: - QString readLine(); - QTextStream& stream; + int start; + int length; +}; + + +enum class Attribute { + LineType, + Color, + X1, + Y1, + Z1, + X2, + Y2, + Z2, + X3, + Y3, + Z3, + X4, + Y4, + Z4, + Name, + Text +}; + +template<typename T, Attribute... Attribs> +struct LineType +{ + static constexpr Attribute attributes[] = {Attribs...}; + QString content; + TextRange positions[countof(attributes)]; + T value; }; -ModelElement parseLDrawLine(QString line); +using LineType0 = LineType<Comment, Attribute::Text>; +using LineType1 = LineType<Colored<SubfileReference>, + Attribute::LineType, + Attribute::Color, + Attribute::X1, + Attribute::Y1, + Attribute::Z1, + Attribute::X2, + Attribute::Y2, + Attribute::Z2, + Attribute::X3, + Attribute::Y3, + Attribute::Z3, + Attribute::X4, + Attribute::Y4, + Attribute::Z4, + Attribute::Name>; +using LineType2 = LineType<Colored<LineSegment>, + Attribute::LineType, + Attribute::Color, + Attribute::X1, + Attribute::Y1, + Attribute::Z1, + Attribute::X2, + Attribute::Y2, + Attribute::Z2>; +using LineType3 = LineType<Colored<Triangle>, + Attribute::LineType, + Attribute::Color, + Attribute::X1, + Attribute::Y1, + Attribute::Z1, + Attribute::X2, + Attribute::Y2, + Attribute::Z2, + Attribute::X3, + Attribute::Y3, + Attribute::Z3>; +using LineType4 = LineType<Colored<Quadrilateral>, + Attribute::LineType, + Attribute::Color, + Attribute::X1, + Attribute::Y1, + Attribute::Z1, + Attribute::X2, + Attribute::Y2, + Attribute::Z2, + Attribute::X3, + Attribute::Y3, + Attribute::Z3, + Attribute::X4, + Attribute::Y4, + Attribute::Z4>; +using LineType5 = LineType<Colored<ConditionalEdge>, + Attribute::LineType, + Attribute::Color, + Attribute::X1, + Attribute::Y1, + Attribute::Z1, + Attribute::X2, + Attribute::Y2, + Attribute::Z2, + Attribute::X3, + Attribute::Y3, + Attribute::Z3, + Attribute::X4, + Attribute::Y4, + Attribute::Z4>; + +template<typename T, Attribute Attrib> +constexpr int findAttributeIndex() +{ + constexpr auto it = std::find( + std::begin(T::attributes), + std::end(T::attributes), + Attrib + ); + static_assert(it != std::end(T::attributes), "Attribute not found"); + return it - std::begin(T::attributes); +} + +template<typename T, Attribute Attrib> +constexpr int attribIndex = findAttributeIndex<T, Attrib>(); +static_assert(attribIndex<LineType3, Attribute::X1> == 2); +using ParsedLine = std::variant<LineType0, LineType1, LineType2, LineType3, LineType4, LineType5>; +opt<ParsedLine> parse(const QString& line);