<commit_before>/*
 * Copyright (C) 2018 <NAME>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <misc/num.h>
#include <misc/unicode.hpp>

#include "json.h"

namespace json {

// ##################
// ##     JSON     ##
// ##################

JSON::JSON(std::initializer_list<json::Member> list) : JSON(createObject()) {
    for(auto &v : list) {
        this->asObject().emplace(
                std::move(const_cast<Member&>(v).key),
                std::move(const_cast<Member&>(v).value));
    }
}

JSON& JSON::operator[](unsigned int index) {
    if(!this->isArray()) {
        fatal("must be array\n");
    }
    return this->asArray()[index];
}

JSON& JSON::operator[](const std::string &key) {
    if(!this->isObject()) {
        fatal("must be object\n");
    }
    return this->asObject()[key];
}

size_t JSON::size() const {
    if(this->isArray()) {
        return this->asArray().size();
    }
    if(this->isObject()) {
        return this->asObject().size();
    }
    return 0;
}


const char *toString(JSONTokenKind kind) {
    const char *table[] = {
#define GEN_STR(T, S) S,
            EACH_JSON_TOKEN(GEN_STR)
#undef GEN_STR
    };
    return table[static_cast<unsigned int>(kind)];
}

// ####################
// ##     Parser     ##
// ####################

#define EACH_LA_VALUE(OP) \
    OP(NIL) \
    OP(TRUE) \
    OP(FALSE) \
    OP(NUMBER) \
    OP(STRING) \
    OP(ARRAY_OPEN) \
    OP(OBJECT_OPEN)


#define GEN_LA_CASE(CASE) case CASE:
#define GEN_LA_ALTER(CASE) CASE,

#define E_ALTER(...) \
do { this->raiseNoViableAlterError((JSONTokenKind[]) { __VA_ARGS__ }); return nullptr; } while(false)

#define TRY(expr) \
({ auto v = expr; if(this->hasError()) { return nullptr; } std::forward<decltype(v)>(v); })


JSON Parser::operator()(json::Lexer &&lexer) {
    this->lex = std::move(lexer);
    this->lexer = &this->lex;
    this->fetchNext();
    auto ret = TRY(this->parseValue());
    TRY(this->expect(EOS));
    return ret;
}

JSON Parser::parseValue() {
    switch(this->curKind) {
    case NIL:
        this->expect(NIL);
        return nullptr;
    case TRUE:
        this->expect(TRUE);
        return true;
    case FALSE:
        this->expect(FALSE);
        return false;
    case NUMBER:
        return this->parseNumber();
    case STRING: {
        Token token = this->expect(STRING); // always success
        auto str = createString();
        TRY(this->unescapeStr(token, *str));
        return str;
    }
    case ARRAY_OPEN:
        return this->parseArray();
    case OBJECT_OPEN:
        return this->parseObject();
    default:
        E_ALTER(EACH_LA_VALUE(GEN_LA_ALTER));
    }
}

static bool isFloat(const char *str) {
    return strchr(str, '.') != nullptr || strchr(str, 'e') != nullptr || strchr(str, 'E') != nullptr;
}

JSON Parser::parseNumber() {
    auto token = this->expect(NUMBER);  // always success<commit_msg>fix build error<commit_after>/*
 * Copyright (C) 2018 <NAME>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <misc/num.h>
#include <misc/unicode.hpp>

#include "json.h"

namespace json {

// ##################
// ##     JSON     ##
// ##################

JSON::JSON(std::initializer_list<json::Member> list) : JSON(createObject()) {
    for(auto &v : list) {
        this->asObject().emplace(
                std::move(const_cast<Member&>(v).key),
                std::move(const_cast<Member&>(v).value));
    }
}

JSON& JSON::operator[](unsigned int index) {
    if(!this->isArray()) {
        fatal("must be array\n");
    }
    return this->asArray()[index];
}

JSON& JSON::operator[](const std::string &key) {
    if(!this->isObject()) {
        fatal("must be object\n");
    }
    return this->asObject()[key];
}

size_t JSON::size() const {
    if(this->isArray()) {
        return this->asArray().size();
    }
    if(this->isObject()) {
        return this->asObject().size();
    }
    return 0;
}


const char *toString(JSONTokenKind kind) {
    const char *table[] = {
#define GEN_STR(T, S) S,
            EACH_JSON_TOKEN(GEN_STR)
#undef GEN_STR
    };
    return table[static_cast<unsigned int>(kind)];
}

// ####################
// ##     Parser     ##
// ####################

#define EACH_LA_VALUE(OP) \
    OP(NIL) \
    OP(TRUE) \
    OP(FALSE) \
    OP(NUMBER) \
    OP(STRING) \
    OP(ARRAY_OPEN) \
    OP(OBJECT_OPEN)


#define GEN_LA_CASE(CASE) case CASE:
#define GEN_LA_ALTER(CASE) CASE,

#define E_ALTER(...) \
do { this->raiseNoViableAlterError((JSONTokenKind[]) { __VA_ARGS__ }); return nullptr; } while(false)

#define TRY(expr) \
({ auto v = expr; if(this->hasError()) { return nullptr; } std::forward<decltype(v)>(v); })


JSON Parser::operator()(json::Lexer &&lexer) {
    this->lex = std::move(lexer);
    this->lexer = &this->lex;
    this->fetchNext();
    auto ret = TRY(this->parseValue());
    TRY(this->expect(EOS));
    return ret;
}

JSON Parser::parseValue() {
    switch(this->curKind) {
    case NIL:
        this->expect(NIL);
        return nullptr;
    case TRUE:
        this->expect(TRUE);
        return true;
    case FALSE:
        this->expect(FALSE);
        return false;
    case NUMBER:
        return this->parseNumber();
    case STRING: {
        Token token = this->expect(STRING); // always success
        auto str = createString();
        TRY(this->unescapeStr(token, *str));
        return JSON(std::move(str));    // for prevent build error in older gcc/clang
    }
    case ARRAY_OPEN:
        return this->parseArray();
    case OBJECT_OPEN:
        return this->parseObject();
    default:
        E_ALTER(EACH_LA_VALUE(GEN_LA_ALTER));
    }
}

static bool isFloat(const char *str) {
    return strchr(str, '.') != nullptr || strchr(str, 'e') != nullptr || strchr(str, 'E') != nullptr;
}

JSON Parser::parseNumber() {
    auto token = this->expect(NUMBER);  // always success
{'fraction_non_alphanumeric': 0.17623906705539358, 'fraction_numerical': 0.0026239067055393588, 'mean_word_length': 2.9590305828043855, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 73, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6054550', 'n_tokens_mistral': 2240, 'n_tokens_neox': 2204, 'n_words': 536}