-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Parse the provided token stream into an in-memory representation wrapped by the type `json`. So far, the interface to it is very limited and verbose. Some tests (but that many) are already provided in the samples directory as usual. Signed-off-by: Kristiyan Stoimenov <kristoimenov@gmail.com>
- Loading branch information
Showing
15 changed files
with
756 additions
and
199 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
#ifndef FMI_JSON_PARSER_PARSER_INCLUDED | ||
#define FMI_JSON_PARSER_PARSER_INCLUDED | ||
|
||
#include <mystd/optional.h> | ||
|
||
#include <json-parser/tokenizer.h> | ||
#include <json-parser/json.h> | ||
|
||
namespace json_parser { | ||
|
||
class parser_exception : public std::exception { | ||
|
||
public: | ||
explicit parser_exception(std::string msg, | ||
mystd::optional<location> location = {}) | ||
: m_location { location } | ||
, m_msg { std::move(msg) } | ||
{ | ||
} | ||
|
||
[[nodiscard]] const char* what() const noexcept { return m_msg.c_str(); } | ||
|
||
private: | ||
mystd::optional<location> m_location; | ||
std::string m_msg; | ||
}; | ||
|
||
class parser { | ||
|
||
public: | ||
explicit parser(const std::string& filename) | ||
: m_tokenizer{filename} | ||
, m_token_cit{m_tokenizer.begin()} | ||
{ | ||
} | ||
|
||
const json &parse() &; | ||
const json &operator()() & { return parse(); } | ||
|
||
json parse() &&; | ||
json operator()() && { return parse(); } | ||
|
||
private: | ||
/// | ||
/// Parsing behaviour | ||
/// | ||
|
||
void parse_and_store(); | ||
[[nodiscard]] json::pmrvalue parse_object(); | ||
[[nodiscard]] json::pmrvalue parse_array(); | ||
[[nodiscard]] json::pmrvalue parse_value(); | ||
|
||
/// | ||
/// Error handling and helpers | ||
/// | ||
|
||
[[nodiscard]] bool has_more() const noexcept { return m_token_cit.has_more(); } | ||
|
||
void expect_has_more() const { | ||
if (!m_token_cit.has_more()) | ||
throw parser_exception_here("Expected more tokens during parsing."); | ||
} | ||
|
||
template <typename TokenKind> | ||
mystd::unique_ptr<token> expect_token() { | ||
expect_has_more(); | ||
mystd::unique_ptr<token> next_token = *m_token_cit++; | ||
if (!token_as<TokenKind>(next_token)) | ||
throw parser_exception_here(std::string("Expected token of type `") + typeid(TokenKind).name() + "` but no such was found."); | ||
return next_token; | ||
} | ||
|
||
template <typename T> | ||
[[nodiscard]] parser_exception parser_exception_here(T&& msg) const { | ||
return parser_exception(mystd::forward<T>(msg), m_token_cit.current_location()); | ||
} | ||
|
||
private: | ||
tokenizer m_tokenizer; | ||
token_citerator m_token_cit; | ||
mystd::optional<json> m_parsed; | ||
}; | ||
|
||
} | ||
|
||
#endif // FMI_JSON_PARSER_PARSER_INCLUDED |
Oops, something went wrong.