slige/runtime/json.cpp

107 lines
3.0 KiB
C++
Raw Normal View History

2024-11-12 11:59:42 +01:00
#include "json.hpp"
#include <cstdlib>
#include <format>
#include <iostream>
#include <string>
#include <unordered_map>
using namespace sliger::json;
auto ident_tok_typs = std::unordered_map<std::string, TokTyp> {
{ "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;
}