aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/openvic-dataloader/Error.hpp32
-rw-r--r--include/openvic-dataloader/csv/Parser.hpp2
-rw-r--r--include/openvic-dataloader/v2script/Parser.hpp2
-rw-r--r--src/openvic-dataloader/AbstractSyntaxTree.hpp5
-rw-r--r--src/openvic-dataloader/DiagnosticLogger.hpp26
-rw-r--r--src/openvic-dataloader/csv/CsvGrammar.hpp28
-rw-r--r--src/openvic-dataloader/csv/Parser.cpp12
-rw-r--r--src/openvic-dataloader/v2script/Parser.cpp12
-rw-r--r--src/openvic-dataloader/v2script/SimpleGrammar.hpp34
-rw-r--r--tests/src/Error.cpp59
10 files changed, 123 insertions, 89 deletions
diff --git a/include/openvic-dataloader/Error.hpp b/include/openvic-dataloader/Error.hpp
index 343abd9..8e182b6 100644
--- a/include/openvic-dataloader/Error.hpp
+++ b/include/openvic-dataloader/Error.hpp
@@ -7,6 +7,7 @@
#include <dryad/abstract_node.hpp>
#include <dryad/node.hpp>
+#include <dryad/symbol.hpp>
namespace ovdl {
template<typename>
@@ -50,6 +51,13 @@ namespace ovdl::error {
LastAnnotation = SecondaryAnnotation,
};
+ struct ErrorSymbolInterner {
+ struct SymbolId;
+ using index_type = std::uint32_t;
+ using symbol_type = dryad::symbol<SymbolId, index_type>;
+ using symbol_interner_type = dryad::symbol_interner<SymbolId, char, index_type>;
+ };
+
static constexpr std::string_view get_kind_name(ErrorKind kind) {
switch (kind) {
using enum ErrorKind;
@@ -62,13 +70,13 @@ namespace ovdl::error {
}
struct Error : dryad::abstract_node_all<ErrorKind> {
- const char* message() const { return _message; }
+ const char* message(const ErrorSymbolInterner::symbol_interner_type& symbols) const { return _message.c_str(symbols); }
protected:
DRYAD_ABSTRACT_NODE_CTOR(Error);
- void _set_message(const char* message) { _message = message; }
- const char* _message = "";
+ void _set_message(ErrorSymbolInterner::symbol_type message) { _message = message; }
+ ErrorSymbolInterner::symbol_type _message;
template<typename>
friend struct ovdl::BasicDiagnosticLogger;
@@ -94,7 +102,7 @@ namespace ovdl::error {
};
struct BufferError : dryad::basic_node<ErrorKind::BufferError, Error> {
- explicit BufferError(dryad::node_ctor ctor, const char* message) : node_base(ctor) {
+ explicit BufferError(dryad::node_ctor ctor, ErrorSymbolInterner::symbol_type message) : node_base(ctor) {
_set_message(message);
}
@@ -103,7 +111,7 @@ namespace ovdl::error {
struct Annotation : dryad::abstract_node_range<Error, ErrorKind::FirstAnnotation, ErrorKind::LastAnnotation> {
protected:
- explicit Annotation(dryad::node_ctor ctor, ErrorKind kind, const char* message) : node_base(ctor, kind) {
+ explicit Annotation(dryad::node_ctor ctor, ErrorKind kind, ErrorSymbolInterner::symbol_type message) : node_base(ctor, kind) {
_set_message(message);
}
};
@@ -129,7 +137,7 @@ namespace ovdl::error {
protected:
explicit ParseError(dryad::node_ctor ctor,
ErrorKind kind,
- const char* message,
+ ErrorSymbolInterner::symbol_type message,
const char* production_name)
: node_base(ctor, kind),
_production_name(production_name) {
@@ -143,7 +151,7 @@ namespace ovdl::error {
struct _ParseError_t : dryad::basic_node<NodeKind, ParseError> {
using base_node = dryad::basic_node<NodeKind, ParseError>;
- explicit _ParseError_t(dryad::node_ctor ctor, const char* message, const char* production_name)
+ explicit _ParseError_t(dryad::node_ctor ctor, ErrorSymbolInterner::symbol_type message, const char* production_name)
: base_node(ctor, message, production_name) {}
};
@@ -157,12 +165,12 @@ namespace ovdl::error {
explicit Semantic(dryad::node_ctor ctor, ErrorKind kind)
: node_base(ctor, kind) {};
- explicit Semantic(dryad::node_ctor ctor, ErrorKind kind, const char* message)
+ explicit Semantic(dryad::node_ctor ctor, ErrorKind kind, ErrorSymbolInterner::symbol_type message)
: node_base(ctor, kind) {
_set_message(message);
};
- explicit Semantic(dryad::node_ctor ctor, ErrorKind kind, const char* message, AnnotationList annotations)
+ explicit Semantic(dryad::node_ctor ctor, ErrorKind kind, ErrorSymbolInterner::symbol_type message, AnnotationList annotations)
: node_base(ctor, kind) {
push_back(annotations);
_set_message(message);
@@ -176,10 +184,10 @@ namespace ovdl::error {
explicit _SemanticError_t(dryad::node_ctor ctor)
: base_node(ctor) {}
- explicit _SemanticError_t(dryad::node_ctor ctor, const char* message)
+ explicit _SemanticError_t(dryad::node_ctor ctor, ErrorSymbolInterner::symbol_type message)
: base_node(ctor, message) {}
- explicit _SemanticError_t(dryad::node_ctor ctor, const char* message, AnnotationList annotations)
+ explicit _SemanticError_t(dryad::node_ctor ctor, ErrorSymbolInterner::symbol_type message, AnnotationList annotations)
: base_node(ctor, message, annotations) {}
};
@@ -192,7 +200,7 @@ namespace ovdl::error {
template<ErrorKind NodeKind>
struct _Annotation_t : dryad::basic_node<NodeKind, Annotation> {
- explicit _Annotation_t(dryad::node_ctor ctor, const char* message)
+ explicit _Annotation_t(dryad::node_ctor ctor, ErrorSymbolInterner::symbol_type message)
: dryad::basic_node<NodeKind, Annotation>(ctor, message) {}
};
diff --git a/include/openvic-dataloader/csv/Parser.hpp b/include/openvic-dataloader/csv/Parser.hpp
index 1c363c8..e3ae84d 100644
--- a/include/openvic-dataloader/csv/Parser.hpp
+++ b/include/openvic-dataloader/csv/Parser.hpp
@@ -42,6 +42,8 @@ namespace ovdl::csv {
using error_range = ovdl::detail::error_range<error::Root>;
Parser::error_range get_errors() const;
+ std::string_view error(const ovdl::error::Error* error) const;
+
const FilePosition get_error_position(const error::Error* error) const;
void print_errors_to(std::basic_ostream<char>& stream) const;
diff --git a/include/openvic-dataloader/v2script/Parser.hpp b/include/openvic-dataloader/v2script/Parser.hpp
index c5f37be..e575dfc 100644
--- a/include/openvic-dataloader/v2script/Parser.hpp
+++ b/include/openvic-dataloader/v2script/Parser.hpp
@@ -61,6 +61,8 @@ namespace ovdl::v2script {
using error_range = ovdl::detail::error_range<error::Root>;
Parser::error_range get_errors() const;
+ std::string_view error(const ovdl::error::Error* error) const;
+
const FilePosition get_error_position(const error::Error* error) const;
void print_errors_to(std::basic_ostream<char>& stream) const;
diff --git a/src/openvic-dataloader/AbstractSyntaxTree.hpp b/src/openvic-dataloader/AbstractSyntaxTree.hpp
index ade1c82..f9f5796 100644
--- a/src/openvic-dataloader/AbstractSyntaxTree.hpp
+++ b/src/openvic-dataloader/AbstractSyntaxTree.hpp
@@ -3,6 +3,7 @@
#include <concepts>
#include <cstdio>
#include <string_view>
+#include <type_traits>
#include <utility>
#include <openvic-dataloader/NodeLocation.hpp>
@@ -51,12 +52,12 @@ namespace ovdl {
using node_type = typename file_type::node_type;
explicit BasicAbstractSyntaxTree(file_type&& file)
- : AbstractSyntaxTree(file.size()),
+ : AbstractSyntaxTree(file.size() * file.visit_buffer([](auto&& buffer) -> size_t { return sizeof(typename std::decay_t<decltype(buffer)>::char_type); })),
_file { std::move(file) } {}
template<typename Encoding, typename MemoryResource = void>
explicit BasicAbstractSyntaxTree(lexy::buffer<Encoding, MemoryResource>&& buffer)
- : AbstractSyntaxTree(buffer.size()),
+ : AbstractSyntaxTree(buffer.size() * sizeof(Encoding::char_type)),
_file { std::move(buffer) } {}
void set_location(const node_type* n, NodeLocation loc) {
diff --git a/src/openvic-dataloader/DiagnosticLogger.hpp b/src/openvic-dataloader/DiagnosticLogger.hpp
index 9810e1e..8c491ca 100644
--- a/src/openvic-dataloader/DiagnosticLogger.hpp
+++ b/src/openvic-dataloader/DiagnosticLogger.hpp
@@ -2,6 +2,7 @@
#include <concepts> // IWYU pragma: keep
#include <cstdio>
+#include <iostream>
#include <ostream>
#include <string>
#include <type_traits>
@@ -37,12 +38,7 @@ namespace ovdl {
template<typename ParseState>
struct BasicDiagnosticLogger;
- struct DiagnosticLogger {
- struct SymbolId;
- using index_type = std::uint32_t;
- using symbol_type = dryad::symbol<SymbolId, index_type>;
- using symbol_interner_type = dryad::symbol_interner<SymbolId, char, index_type>;
-
+ struct DiagnosticLogger : error::ErrorSymbolInterner {
using AnnotationKind = lexy_ext::annotation_kind;
using DiagnosticKind = lexy_ext::diagnostic_kind;
@@ -116,23 +112,23 @@ namespace ovdl {
}
result = writer.error();
} else {
- auto production = _logger.intern_cstr(production_name);
+ auto production = production_name;
if constexpr (std::is_same_v<Tag, lexy::expected_literal>) {
auto string = lexy::_detail::make_literal_lexeme<typename Reader::encoding>(error.string(), error.length());
NodeLocation loc = NodeLocation::make_from(context.position(), error.position() - 1);
- auto message = _logger.intern_cstr(fmt::format("expected '{}'", string.data()));
+ auto message = _logger.intern(fmt::format("expected '{}'", string.data()));
result = _logger.template create<error::ExpectedLiteral>(loc, message, production);
} else if constexpr (std::is_same_v<Tag, lexy::expected_keyword>) {
auto string = lexy::_detail::make_literal_lexeme<typename Reader::encoding>(error.string(), error.length());
NodeLocation loc = NodeLocation::make_from(context.position(), error.position() - 1);
- auto message = _logger.intern_cstr(fmt::format("expected keyword '{}'", string.data()));
+ auto message = _logger.intern(fmt::format("expected keyword '{}'", string.data()));
result = _logger.template create<error::ExpectedKeyword>(loc, message, production);
} else if constexpr (std::is_same_v<Tag, lexy::expected_char_class>) {
- auto message = _logger.intern_cstr(fmt::format("expected {}", error.name()));
+ auto message = _logger.intern(fmt::format("expected {}", error.name()));
result = _logger.template create<error::ExpectedCharClass>(error.position(), message, production);
} else {
NodeLocation loc = NodeLocation::make_from(error.begin(), error.end());
- auto message = _logger.intern_cstr(error.message());
+ auto message = _logger.intern(error.message());
result = _logger.template create<error::GenericParseError>(loc, message, production);
}
}
@@ -361,7 +357,7 @@ namespace ovdl {
});
error::Annotation* annotation;
- auto message = _logger.intern_cstr(output);
+ auto message = _logger.intern(output);
switch (kind) {
case AnnotationKind::primary:
annotation = _logger.create<error::PrimaryAnnotation>(loc, message);
@@ -404,7 +400,7 @@ namespace ovdl {
});
impl.write_path(iter, file().path());
- auto message = intern_cstr(output);
+ auto message = intern(output);
error->_set_message(message);
if (!error->is_linked_in_tree())
insert(error);
@@ -422,8 +418,8 @@ namespace ovdl {
});
impl.write_path(iter, file().path());
- auto production = intern_cstr(production_name);
- auto message = intern_cstr(output);
+ auto production = production_name;
+ auto message = intern(output);
auto* error = [&] {
if constexpr (std::is_same_v<Tag, lexy::expected_literal>) {
return create<error::ExpectedLiteral>(loc, message, production);
diff --git a/src/openvic-dataloader/csv/CsvGrammar.hpp b/src/openvic-dataloader/csv/CsvGrammar.hpp
index 19aee54..91226c7 100644
--- a/src/openvic-dataloader/csv/CsvGrammar.hpp
+++ b/src/openvic-dataloader/csv/CsvGrammar.hpp
@@ -11,10 +11,7 @@
#include <lexy/_detail/config.hpp>
#include <lexy/callback.hpp>
-#include <lexy/callback/string.hpp>
#include <lexy/dsl.hpp>
-#include <lexy/dsl/ascii.hpp>
-#include <lexy/dsl/option.hpp>
#include <lexy/encoding.hpp>
#include "detail/Convert.hpp"
@@ -73,6 +70,9 @@ namespace ovdl::csv::grammar {
constexpr auto escaped_quote = lexy::symbol_table<char> //
.map<'"'>('"');
+ constexpr auto escaped_newline = lexy::symbol_table<char> //
+ .map<'n'>('\n');
+
template<ParseOptions Options>
struct CsvGrammar {
struct StringValue : lexy::scan_production<std::string>,
@@ -118,6 +118,11 @@ namespace ovdl::csv::grammar {
template<auto character>
static constexpr auto _escape_check = character - (lexy::dsl::lit_b<Options.SepChar> / lexy::dsl::ascii::newline);
+ struct Backslash {
+ static constexpr auto rule = LEXY_LIT("\\n");
+ static constexpr auto value = lexy::constant('\n');
+ };
+
template<typename Context, typename Reader>
static constexpr scan_result scan(lexy::rule_scanner<Context, Reader>& scanner, detail::IsFileParseState auto& state) {
using encoding = typename Reader::encoding;
@@ -134,13 +139,16 @@ namespace ovdl::csv::grammar {
if constexpr (Options.SupportStrings) {
return lexy::dsl::identifier(character - (lexy::dsl::lit_b<Options.SepChar> / lexy::dsl::ascii::newline));
} else {
- auto escape_check_char = _escape_check<character>;
- auto id_check_char = escape_check_char - lexy::dsl::lit_b<'\\'>;
- auto id_segment = lexy::dsl::identifier(id_check_char);
- auto escape_segement = lexy::dsl::token(escape_check_char);
- auto escape_sym = lexy::dsl::symbol<escaped_symbols>(escape_segement);
- auto escape_rule = lexy::dsl::lit_b<'\\'> >> escape_sym;
- return lexy::dsl::list(id_segment | escape_rule);
+ constexpr auto backslash = lexy::dsl::lit_b<'\\'>;
+
+ constexpr auto escape_check_char = _escape_check<character>;
+ constexpr auto escape_rule = lexy::dsl::p<Backslash>;
+
+ return lexy::dsl::list(
+ lexy::dsl::identifier(escape_check_char - backslash) |
+ escape_rule |
+ lexy::dsl::capture(escape_check_char) //
+ );
}
}();
diff --git a/src/openvic-dataloader/csv/Parser.cpp b/src/openvic-dataloader/csv/Parser.cpp
index 8fe8b17..bbd1be4 100644
--- a/src/openvic-dataloader/csv/Parser.cpp
+++ b/src/openvic-dataloader/csv/Parser.cpp
@@ -195,6 +195,10 @@ typename Parser::error_range Parser::get_errors() const {
return _parse_handler->get_errors();
}
+std::string_view Parser::error(const ovdl::error::Error* error) const {
+ return error->message(_parse_handler->parse_state().logger().symbol_interner());
+}
+
const FilePosition Parser::get_error_position(const error::Error* error) const {
if (!error || !error->is_linked_in_tree()) {
return {};
@@ -231,20 +235,20 @@ void Parser::print_errors_to(std::basic_ostream<char>& stream) const {
dryad::visit_tree(
error,
[&](const error::BufferError* buffer_error) {
- stream << "buffer error: " << buffer_error->message() << '\n';
+ stream << "buffer error: " << this->error(buffer_error) << '\n';
},
[&](dryad::child_visitor<error::ErrorKind> visitor, const error::AnnotatedError* annotated_error) {
- stream << annotated_error->message() << '\n';
+ stream << this->error(annotated_error) << '\n';
auto annotations = annotated_error->annotations();
for (auto annotation : annotations) {
visitor(annotation);
}
},
[&](const error::PrimaryAnnotation* primary) {
- stream << primary->message() << '\n';
+ stream << this->error(primary) << '\n';
},
[&](const error::SecondaryAnnotation* secondary) {
- stream << secondary->message() << '\n';
+ stream << this->error(secondary) << '\n';
});
}
} \ No newline at end of file
diff --git a/src/openvic-dataloader/v2script/Parser.cpp b/src/openvic-dataloader/v2script/Parser.cpp
index 2375a1a..e5234d6 100644
--- a/src/openvic-dataloader/v2script/Parser.cpp
+++ b/src/openvic-dataloader/v2script/Parser.cpp
@@ -320,6 +320,10 @@ Parser::error_range Parser::get_errors() const {
return _parse_handler->get_errors();
}
+std::string_view Parser::error(const ovdl::error::Error* error) const {
+ return error->message(_parse_handler->parse_state().logger().symbol_interner());
+}
+
const FilePosition Parser::get_error_position(const error::Error* error) const {
if (!error || !error->is_linked_in_tree()) {
return {};
@@ -352,20 +356,20 @@ void Parser::print_errors_to(std::basic_ostream<char>& stream) const {
dryad::visit_tree(
error,
[&](const error::BufferError* buffer_error) {
- stream << "buffer error: " << buffer_error->message() << '\n';
+ stream << "buffer error: " << this->error(buffer_error) << '\n';
},
[&](dryad::child_visitor<error::ErrorKind> visitor, const error::AnnotatedError* annotated_error) {
- stream << annotated_error->message() << '\n';
+ stream << this->error(annotated_error) << '\n';
auto annotations = annotated_error->annotations();
for (auto annotation : annotations) {
visitor(annotation);
}
},
[&](const error::PrimaryAnnotation* primary) {
- stream << primary->message() << '\n';
+ stream << this->error(primary) << '\n';
},
[&](const error::SecondaryAnnotation* secondary) {
- stream << secondary->message() << '\n';
+ stream << this->error(secondary) << '\n';
});
}
} \ No newline at end of file
diff --git a/src/openvic-dataloader/v2script/SimpleGrammar.hpp b/src/openvic-dataloader/v2script/SimpleGrammar.hpp
index c47b243..5474c79 100644
--- a/src/openvic-dataloader/v2script/SimpleGrammar.hpp
+++ b/src/openvic-dataloader/v2script/SimpleGrammar.hpp
@@ -5,15 +5,6 @@
#include <lexy/callback.hpp>
#include <lexy/dsl.hpp>
-#include <lexy/dsl/any.hpp>
-#include <lexy/dsl/identifier.hpp>
-#include <lexy/dsl/option.hpp>
-#include <lexy/dsl/peek.hpp>
-#include <lexy/dsl/punctuator.hpp>
-#include <lexy/dsl/recover.hpp>
-#include <lexy/dsl/scan.hpp>
-#include <lexy/dsl/symbol.hpp>
-#include <lexy/dsl/unicode.hpp>
#include <lexy/encoding.hpp>
#include <lexy/input/base.hpp>
#include <lexy/input/buffer.hpp>
@@ -63,7 +54,7 @@ namespace ovdl::v2script::grammar {
/* REQUIREMENTS: DAT-631 */
static constexpr auto comment_specifier = LEXY_LIT("#") >> lexy::dsl::until(lexy::dsl::newline).or_eof();
- static constexpr auto ascii = lexy::dsl::ascii::alpha_digit_underscore / LEXY_ASCII_ONE_OF("+:@%&'-.");
+ static constexpr auto ascii = lexy::dsl::ascii::alpha_digit_underscore / LEXY_ASCII_ONE_OF("+:@%&'-.\\");
/* REQUIREMENTS:
* DAT-632
@@ -91,7 +82,7 @@ namespace ovdl::v2script::grammar {
static constexpr auto data_char_class = LEXY_CHAR_CLASS("DataSpecifier", data_specifier);
- static constexpr auto utf_data_specifier = lexy::dsl::unicode::xid_continue / LEXY_ASCII_ONE_OF("+:@%&'-.");
+ static constexpr auto utf_data_specifier = lexy::dsl::unicode::xid_continue / LEXY_ASCII_ONE_OF("+:@%&'-.\\");
static constexpr auto utf_char_class = LEXY_CHAR_CLASS("DataSpecifier", utf_data_specifier);
@@ -196,9 +187,9 @@ namespace ovdl::v2script::grammar {
if constexpr (Options.NoStringEscape) {
auto c = [] {
if constexpr (std::same_as<encoding, lexy::default_encoding> || std::same_as<encoding, lexy::byte_encoding>) {
- return dsl::lit_b_range<0x20, 0xFF> / lexy::dsl::lit_b<0x07> / lexy::dsl::lit_b<0x09> / lexy::dsl::lit_b<0x0A> / lexy::dsl::lit_b<0x0D>;
+ return dsl::lit_b_range<0x01, 0xFF>;
} else {
- return -lexy::dsl::unicode::control;
+ return lexy::dsl::unicode::character;
}
}();
return lexy::dsl::quoted(c);
@@ -287,7 +278,7 @@ namespace ovdl::v2script::grammar {
}();
static constexpr auto value = dsl::callback<ast::Statement*>(
- [](detail::IsParseState auto& state, const char* pos, ast::IdentifierValue* name, ast::Value* initializer) {
+ [](detail::IsParseState auto& state, const char* pos, ast::IdentifierValue* name, ast::Value* initializer) -> ast::AssignStatement* {
return state.ast().template create<ast::AssignStatement>(pos, name, initializer);
},
[](detail::IsParseState auto& state, bool&, const char* pos, ast::IdentifierValue* name, ast::Value* initializer) {
@@ -306,11 +297,15 @@ namespace ovdl::v2script::grammar {
return state.ast().template create<ast::ValueStatement>(pos, left);
},
[](detail::IsParseState auto& state, ast::Value* left) -> ast::ValueStatement* {
- if (left == nullptr) return nullptr;
+ if (left == nullptr) { // May no longer be neccessary
+ return nullptr;
+ }
return state.ast().template create<ast::ValueStatement>(state.ast().location_of(left), left);
},
[](detail::IsParseState auto& state, bool&, ast::Value* left) -> ast::ValueStatement* {
- if (left == nullptr) return nullptr;
+ if (left == nullptr) { // May no longer be neccessary
+ return nullptr;
+ }
return state.ast().template create<ast::ValueStatement>(state.ast().location_of(left), left);
});
};
@@ -322,12 +317,12 @@ namespace ovdl::v2script::grammar {
auto assign_statement = lexy::dsl::recurse_branch<AssignmentStatement>;
- auto assign_try = lexy::dsl::try_(assign_statement);
+ auto assign_try = lexy::dsl::try_(assign_statement, lexy::dsl::nullopt);
auto assign_opt = lexy::dsl::opt(lexy::dsl::list(assign_try));
auto curly_bracket = dsl::curly_bracketed(assign_opt + lexy::dsl::opt(lexy::dsl::semicolon));
- return lexy::dsl::try_(curly_bracket, lexy::dsl::find(right_brace));
+ return curly_bracket;
}();
static constexpr auto value =
@@ -346,9 +341,6 @@ namespace ovdl::v2script::grammar {
} else {
return state.ast().template create<ast::ListValue>(ovdl::NodeLocation::make_from(begin, end), LEXY_MOV(list));
}
- },
- [](detail::IsParseState auto& state, lexy::nullopt fail = {}) {
- return fail;
});
};
};
diff --git a/tests/src/Error.cpp b/tests/src/Error.cpp
index 136b650..7c78cd4 100644
--- a/tests/src/Error.cpp
+++ b/tests/src/Error.cpp
@@ -14,7 +14,7 @@ using namespace ovdl;
using namespace ovdl::error;
using namespace std::string_view_literals;
-struct ErrorTree : SymbolIntern {
+struct ErrorTree : ovdl::error::ErrorSymbolInterner {
using error_range = detail::error_range<error::Root>;
dryad::node_map<const error::Error, NodeLocation> map;
@@ -27,42 +27,59 @@ struct ErrorTree : SymbolIntern {
}
template<typename T, typename LocCharT, typename... Args>
- T* create(BasicNodeLocation<LocCharT> loc, Args&&... args) {
+ T* create(BasicNodeLocation<LocCharT> loc, std::string_view message, Args&&... args) {
using node_creator = dryad::node_creator<decltype(DRYAD_DECLVAL(T).kind()), void>;
- T* result = tree.create<T>(DRYAD_FWD(args)...);
+ T* result = tree.create<T>(symbol_interner.intern(message.data(), message.length()), DRYAD_FWD(args)...);
map.insert(result, loc);
return result;
}
template<typename T, typename... Args>
- T* create(Args&&... args) {
+ T* create(std::string_view message, Args&&... args) {
using node_creator = dryad::node_creator<decltype(DRYAD_DECLVAL(T).kind()), void>;
- T* result = tree.create<T>(DRYAD_FWD(args)...);
+ T* result = tree.create<T>(symbol_interner.intern(message.data(), message.length()), DRYAD_FWD(args)...);
return result;
}
+ template<typename T>
+ T* create() {
+ static_assert(!std::same_as<T, error::Root>, "Only supports error::Root");
+ return nullptr;
+ }
+
error_range get_errors() const {
return tree.root()->errors();
}
+ std::string_view error(const ovdl::error::Error* error) const {
+ return error->message(symbol_interner);
+ }
+
void insert(error::Error* root) {
tree.root()->insert_back(root);
}
};
+template<>
+inline error::Root* ErrorTree::create<error::Root>() {
+ using node_creator = dryad::node_creator<decltype(DRYAD_DECLVAL(error::Root).kind()), void>;
+ error::Root* result = tree.create<error::Root>();
+ return result;
+}
+
TEST_CASE("Error Nodes", "[error-nodes]") {
ErrorTree errors;
auto* buffer_error = errors.create<BufferError>("error");
CHECK_IF(buffer_error) {
CHECK(buffer_error->kind() == ErrorKind::BufferError);
- CHECK(buffer_error->message() == "error"sv);
+ CHECK(errors.error(buffer_error) == "error"sv);
}
auto* expect_lit = errors.create<ExpectedLiteral>("expected lit", "production");
CHECK_IF(expect_lit) {
CHECK(expect_lit->kind() == ErrorKind::ExpectedLiteral);
- CHECK(expect_lit->message() == "expected lit"sv);
+ CHECK(errors.error(expect_lit) == "expected lit"sv);
CHECK(expect_lit->production_name() == "production"sv);
CHECK(expect_lit->annotations().empty());
}
@@ -70,7 +87,7 @@ TEST_CASE("Error Nodes", "[error-nodes]") {
auto* expect_kw = errors.create<ExpectedKeyword>("expected keyword", "production2");
CHECK_IF(expect_kw) {
CHECK(expect_kw->kind() == ErrorKind::ExpectedKeyword);
- CHECK(expect_kw->message() == "expected keyword"sv);
+ CHECK(errors.error(expect_kw) == "expected keyword"sv);
CHECK(expect_kw->production_name() == "production2"sv);
CHECK(expect_kw->annotations().empty());
}
@@ -78,7 +95,7 @@ TEST_CASE("Error Nodes", "[error-nodes]") {
auto* expect_char_c = errors.create<ExpectedCharClass>("expected char", "production3");
CHECK_IF(expect_char_c) {
CHECK(expect_char_c->kind() == ErrorKind::ExpectedCharClass);
- CHECK(expect_char_c->message() == "expected char"sv);
+ CHECK(errors.error(expect_char_c) == "expected char"sv);
CHECK(expect_char_c->production_name() == "production3"sv);
CHECK(expect_char_c->annotations().empty());
}
@@ -86,7 +103,7 @@ TEST_CASE("Error Nodes", "[error-nodes]") {
auto* generic_error = errors.create<GenericParseError>("generic error", "production 4");
CHECK_IF(generic_error) {
CHECK(generic_error->kind() == ErrorKind::GenericParseError);
- CHECK(generic_error->message() == "generic error"sv);
+ CHECK(errors.error(generic_error) == "generic error"sv);
CHECK(generic_error->production_name() == "production 4"sv);
CHECK(generic_error->annotations().empty());
}
@@ -94,55 +111,55 @@ TEST_CASE("Error Nodes", "[error-nodes]") {
auto* sem_error = errors.create<SemanticError>("sem error");
CHECK_IF(sem_error) {
CHECK(sem_error->kind() == ErrorKind::SemanticError);
- CHECK(sem_error->message() == "sem error"sv);
+ CHECK(errors.error(sem_error) == "sem error"sv);
CHECK(sem_error->annotations().empty());
}
auto* sem_warn = errors.create<SemanticWarning>("sem warn");
CHECK_IF(sem_warn) {
CHECK(sem_warn->kind() == ErrorKind::SemanticWarning);
- CHECK(sem_warn->message() == "sem warn"sv);
+ CHECK(errors.error(sem_warn) == "sem warn"sv);
CHECK(sem_warn->annotations().empty());
}
auto* sem_info = errors.create<SemanticInfo>("sem info");
CHECK_IF(sem_info) {
CHECK(sem_info->kind() == ErrorKind::SemanticInfo);
- CHECK(sem_info->message() == "sem info"sv);
+ CHECK(errors.error(sem_info) == "sem info"sv);
CHECK(sem_info->annotations().empty());
}
auto* sem_debug = errors.create<SemanticDebug>("sem debug");
CHECK_IF(sem_debug) {
CHECK(sem_debug->kind() == ErrorKind::SemanticDebug);
- CHECK(sem_debug->message() == "sem debug"sv);
+ CHECK(errors.error(sem_debug) == "sem debug"sv);
CHECK(sem_debug->annotations().empty());
}
auto* sem_fixit = errors.create<SemanticFixit>("sem fixit");
CHECK_IF(sem_fixit) {
CHECK(sem_fixit->kind() == ErrorKind::SemanticFixit);
- CHECK(sem_fixit->message() == "sem fixit"sv);
+ CHECK(errors.error(sem_fixit) == "sem fixit"sv);
CHECK(sem_fixit->annotations().empty());
}
auto* sem_help = errors.create<SemanticHelp>("sem help");
CHECK_IF(sem_help) {
CHECK(sem_help->kind() == ErrorKind::SemanticHelp);
- CHECK(sem_help->message() == "sem help"sv);
+ CHECK(errors.error(sem_help) == "sem help"sv);
CHECK(sem_help->annotations().empty());
}
auto* prim_annotation = errors.create<PrimaryAnnotation>("primary annotation");
CHECK_IF(prim_annotation) {
CHECK(prim_annotation->kind() == ErrorKind::PrimaryAnnotation);
- CHECK(prim_annotation->message() == "primary annotation"sv);
+ CHECK(errors.error(prim_annotation) == "primary annotation"sv);
}
auto* sec_annotation = errors.create<SecondaryAnnotation>("secondary annotation");
CHECK_IF(sec_annotation) {
CHECK(sec_annotation->kind() == ErrorKind::SecondaryAnnotation);
- CHECK(sec_annotation->message() == "secondary annotation"sv);
+ CHECK(errors.error(sec_annotation) == "secondary annotation"sv);
}
AnnotationList annotation_list {};
@@ -153,7 +170,7 @@ TEST_CASE("Error Nodes", "[error-nodes]") {
auto* annotated_error = errors.create<SemanticError>("annotated error", annotation_list);
CHECK_IF(annotated_error) {
CHECK(annotated_error->kind() == ErrorKind::SemanticError);
- CHECK(annotated_error->message() == "annotated error"sv);
+ CHECK(errors.error(annotated_error) == "annotated error"sv);
auto annotations = annotated_error->annotations();
CHECK_FALSE(annotations.empty());
for (const auto [annotation, list_val] : ranges::views::zip(annotations, annotation_list)) {
@@ -216,10 +233,10 @@ TEST_CASE("Error Nodes Location", "[error-nodes-location]") {
constexpr auto fake_buffer = "id"sv;
- auto* expected_lit = errors.create<ExpectedLiteral>(NodeLocation::make_from(&fake_buffer[0], &fake_buffer[1]), "expected lit", "production");
+ auto* expected_lit = errors.create<ExpectedLiteral>(NodeLocation::make_from(&fake_buffer[0], &fake_buffer[1]), "expected lit"sv, "production");
CHECK_IF(expected_lit) {
- CHECK(expected_lit->message() == "expected lit"sv);
+ CHECK(errors.error(expected_lit) == "expected lit"sv);
CHECK(expected_lit->production_name() == "production"sv);
auto location = errors.location_of(expected_lit);