153 lines
3.3 KiB
C++
153 lines
3.3 KiB
C++
#include <string>
|
|
#include <cassert>
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <vector>
|
|
|
|
#include "lexy/callback.hpp"
|
|
#include "lexy/dsl.hpp"
|
|
#include "lexy/input/string_input.hpp"
|
|
#include "lexy/action/parse.hpp"
|
|
#include "lexy_ext/report_error.hpp"
|
|
|
|
struct raw_text
|
|
{
|
|
std::string text;
|
|
std::string eol;
|
|
raw_text* next;
|
|
raw_text* prev;
|
|
};
|
|
|
|
struct document
|
|
{
|
|
raw_text* first_child;
|
|
};
|
|
|
|
raw_text* make_raw_text(const std::string& str, const std::string& eol)
|
|
{
|
|
raw_text* line = new raw_text;
|
|
line->text = str;
|
|
line->eol = eol;
|
|
line->next = nullptr;
|
|
line->prev = nullptr;
|
|
return line;
|
|
}
|
|
|
|
struct _node_sink
|
|
{
|
|
raw_text* _head = nullptr;
|
|
raw_text* _tail = nullptr;
|
|
|
|
using return_type = raw_text*;
|
|
|
|
raw_text* operator()(raw_text* obj)
|
|
{
|
|
if (obj != NULL)
|
|
{
|
|
if (_head == nullptr)
|
|
_head = _tail = obj;
|
|
else
|
|
{
|
|
_tail->next = obj;
|
|
obj->prev = _tail;
|
|
_tail = obj;
|
|
}
|
|
}
|
|
return _head;
|
|
}
|
|
|
|
raw_text* operator()(std::vector<char>&& str)
|
|
{
|
|
assert(false);
|
|
return make_raw_text("", "");
|
|
}
|
|
|
|
raw_text* operator()(std::string&& str)
|
|
{
|
|
return make_raw_text(str, "");
|
|
}
|
|
|
|
raw_text* finish() &&
|
|
{
|
|
return LEXY_MOV(_head);
|
|
}
|
|
};
|
|
|
|
struct _append_node
|
|
{
|
|
using return_type = raw_text*;
|
|
|
|
constexpr raw_text* operator()(raw_text* obj) const
|
|
{
|
|
return LEXY_MOV(obj);
|
|
}
|
|
|
|
raw_text* operator()(lexy::nullopt&&) const
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
template <typename... Args>
|
|
constexpr raw_text* operator()(Args&&... args) const
|
|
{
|
|
assert(false);
|
|
return nullptr;
|
|
}
|
|
|
|
auto sink() const
|
|
{
|
|
return _node_sink{};
|
|
}
|
|
};
|
|
|
|
constexpr auto append_node = _append_node {};
|
|
namespace grammar
|
|
{
|
|
|
|
namespace dsl = lexy::dsl;
|
|
|
|
struct eol
|
|
{
|
|
static constexpr auto rule = dsl::capture(dsl::newline);
|
|
static constexpr auto value = lexy::as_string<std::string>;
|
|
};
|
|
|
|
struct raw_line
|
|
{
|
|
// static constexpr auto rule = dsl::terminator(dsl::eol).opt_list(dsl::capture(dsl::code_point));
|
|
static constexpr auto rule = dsl::terminator(dsl::p<eol>).opt_list(dsl::capture(dsl::code_point));
|
|
static constexpr auto value = lexy::as_string<std::string> >>
|
|
lexy::callback<raw_text*>([](lexy::nullopt&& opt, std::string&& _eol) {
|
|
return make_raw_text("", _eol);
|
|
},
|
|
[](std::string&& str, std::string&& _eol) {
|
|
return make_raw_text(str, _eol);
|
|
});
|
|
};
|
|
|
|
struct document
|
|
{
|
|
static constexpr auto rule = dsl::terminator(dsl::eof).list(dsl::p<raw_line>);
|
|
static constexpr auto value = append_node;
|
|
};
|
|
} // namespace grammar
|
|
|
|
int main (int argc, char** argv)
|
|
{
|
|
if (argc > 1)
|
|
{
|
|
std::ifstream ifs(argv[1]);
|
|
std::string content((std::istreambuf_iterator<char>(ifs)),
|
|
(std::istreambuf_iterator<char>()));
|
|
|
|
auto input = lexy::string_input<lexy::utf8_encoding>(content);
|
|
auto result = lexy::parse<grammar::document>(input, lexy_ext::report_error);
|
|
|
|
if (!result)
|
|
return 2;
|
|
|
|
if (result.has_value())
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|