#include "json.hpp" #include #include #include #include #include using namespace sliger::json; auto ident_tok_typs = std::unordered_map { { "null", TokTyp::Null }, { "false", TokTyp::False }, { "true", TokTyp::True }, }; auto id_start_chars = "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ_"; auto id_tail_chars = "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "1234567890"; auto Lexer::next() -> Tok { if (done()) { return TokTyp::Eof; } auto pos = this->pos(); if (test('"')) { step(); auto value = std::string(); while (!done() and !test('"')) { if (cur() == '\\') { step(); if (done()) break; value.push_back([&] { char ch = cur(); switch (ch) { case 'n': return '\n'; case 'r': return '\r'; case 't': return '\t'; case '0': return '\0'; default: return ch; } }()); } else { value.push_back(cur()); } step(); } } auto step_n_ret = [&](auto tok) { step(); return tok; }; switch (cur()) { case '0': return step_n_ret(Tok(TokTyp::Float, 0.0)); case '{': return step_n_ret(TokTyp::LBrace); case '}': return step_n_ret(TokTyp::RBrace); case '[': return step_n_ret(TokTyp::LBracket); case ']': return step_n_ret(TokTyp::RBracket); case ',': return step_n_ret(TokTyp::Comma); case ':': return step_n_ret(TokTyp::Colon); } if (test_in(id_start_chars)) { auto value = std::string(); while (test_in(id_tail_chars)) { value.push_back(cur()); step(); } if (ident_tok_typs.find(value) == ident_tok_typs.end()) { std::cerr << std::format("sliger::json::Lexer error: unknown " "identifier \"{}\" at {}:{}", value, pos.col, pos.line); return TokTyp::Error; } return ident_tok_typs.at(value); } if (test_in("123456789")) { auto value_str = std::string(); while (test_in("1234567890")) { value_str.push_back(cur()); step(); } auto value = std::atof(value_str.c_str()); return Tok(TokTyp::Float, value); } std::cerr << std::format( "sliger::json::Lexer error: unknown character '{}' at {}:{}", cur(), this->line, this->col); step(); return TokTyp::Error; }