<commit_before>//
//  PackageParser.cpp
//  Emojicode
//
//  Created by <NAME> on 24/04/16.
//  Copyright © 2016 <NAME>. All rights reserved.
//

#include "PackageParser.hpp"
#include "../utf8.h"
#include "Class.hpp"
#include "Enum.hpp"
#include "Function.hpp"
#include "Protocol.hpp"
#include "TypeContext.hpp"
#include "ValueType.hpp"
#include <cstring>
#include <experimental/optional>

namespace EmojicodeCompiler {

void PackageParser::parse() {
    while (stream_.hasMoreTokens()) {
        auto documentation = Documentation().parse(&stream_);
        auto exported = Attribute<E_EARTH_GLOBE_EUROPE_AFRICA>().parse(&stream_);
        auto final = Attribute<E_LOCK_WITH_INK_PEN>().parse(&stream_);
        auto &theToken = stream_.consumeToken(TokenType::Identifier);
        switch (theToken.value()[0]) {
            case E_PACKAGE: {
                exported.disallow();
                final.disallow();
                documentation.disallow();

                auto &nameToken = stream_.consumeToken(TokenType::Variable);
                auto &namespaceToken = stream_.consumeToken(TokenType::Identifier);

                package_->loadPackage(nameToken.value().utf8(), namespaceToken.value(), theToken.position());

                continue;
            }
            case E_CROCODILE:
                final.disallow();
                parseProtocol(documentation.get(), theToken, exported.set());
                continue;
            case E_TURKEY:
                final.disallow();
                parseEnum(documentation.get(), theToken, exported.set());
                continue;
            case E_RADIO:
                final.disallow();
                exported.disallow();
                documentation.disallow();
                package_->setRequiresBinary();
                if (package_->name() == "_") {
                    throw CompilerError(theToken.position(), "You may not set 📻 for the _ package.");
                }
                continue;
            case E_TRIANGLE_POINTED_DOWN: {
                ParsedType alias = parseType();
                Type type = Type::nothingness();
                package_->fetchRawType(parseType(), false, &type);

                package_->registerType(type, alias.name, alias.ns, false, theToken.position());
                continue;
            }
            case E_CRYSTAL_BALL: {
                final.disallow();
                exported.disallow();
                if (package_->validVersion()) {
                    throw CompilerError(theToken.position(), "Package version already declared.");
                }

                auto major = std::stoi(stream_.consumeToken(TokenType::Integer).value().utf8());
                auto minor = std::stoi(stream_.consumeToken(TokenType::Integer).value().utf8());

                package_->setPackageVersion(PackageVersion(major, minor));
                if (!package_->validVersion()) {
                    throw CompilerError(theToken.position(), "The provided package version is not valid.");
                }

                package_->setDocumentation(documentation.get());

                continue;
            }
            case E_WALE: {
                final.disallow();
                exported.disallow();
                documentation.disallow();

                auto parsedType = parseType();

                Type type = Type::nothingness();

                if (!package_->fetchRawType(parsedType, false, &type)) {
                    throw CompilerError(parsedType.token.position(), "Class does not exist.");
                }
                if (type.type() != TypeContent::Class && type.type() != TypeContent::ValueType) {
                    throw CompilerError(parsedType.token.position(), "Only classes and value types are extendable.");
                }

                // Native extensions are allowed if the class was defined in this package.
                parseTypeDefinitionBody(type, nullptr, type.eclass()->package() == package_);

                continue;
            }
            case E_RABBIT:
                parseClass(documentation.get(), theToken, exported.set(), final.set());
                continue;
            case E_DOVE_OF_PEACE:
                final.disallow();
                parseValueType(documentation.get(), theToken, exported.set());
                continue;
            case E_SCROLL: {
                final.disallow();
                exported.disallow();
                documentation.disallow();

                auto &pathString = stream_.consumeToken(TokenType::String);
                auto relativePath = std::string(pathString.position().file);
                auto fileString = pathString.value().utf8();

                auto lastSlash = relativePath.find_last_of('/');<commit_msg>💴 Proper type definition accessor<commit_after>//
//  PackageParser.cpp
//  Emojicode
//
//  Created by <NAME> on 24/04/16.
//  Copyright © 2016 <NAME>. All rights reserved.
//

#include "PackageParser.hpp"
#include "../utf8.h"
#include "Class.hpp"
#include "Enum.hpp"
#include "Function.hpp"
#include "Protocol.hpp"
#include "TypeContext.hpp"
#include "ValueType.hpp"
#include <cstring>
#include <experimental/optional>

namespace EmojicodeCompiler {

void PackageParser::parse() {
    while (stream_.hasMoreTokens()) {
        auto documentation = Documentation().parse(&stream_);
        auto exported = Attribute<E_EARTH_GLOBE_EUROPE_AFRICA>().parse(&stream_);
        auto final = Attribute<E_LOCK_WITH_INK_PEN>().parse(&stream_);
        auto &theToken = stream_.consumeToken(TokenType::Identifier);
        switch (theToken.value()[0]) {
            case E_PACKAGE: {
                exported.disallow();
                final.disallow();
                documentation.disallow();

                auto &nameToken = stream_.consumeToken(TokenType::Variable);
                auto &namespaceToken = stream_.consumeToken(TokenType::Identifier);

                package_->loadPackage(nameToken.value().utf8(), namespaceToken.value(), theToken.position());

                continue;
            }
            case E_CROCODILE:
                final.disallow();
                parseProtocol(documentation.get(), theToken, exported.set());
                continue;
            case E_TURKEY:
                final.disallow();
                parseEnum(documentation.get(), theToken, exported.set());
                continue;
            case E_RADIO:
                final.disallow();
                exported.disallow();
                documentation.disallow();
                package_->setRequiresBinary();
                if (package_->name() == "_") {
                    throw CompilerError(theToken.position(), "You may not set 📻 for the _ package.");
                }
                continue;
            case E_TRIANGLE_POINTED_DOWN: {
                ParsedType alias = parseType();
                Type type = Type::nothingness();
                package_->fetchRawType(parseType(), false, &type);

                package_->registerType(type, alias.name, alias.ns, false, theToken.position());
                continue;
            }
            case E_CRYSTAL_BALL: {
                final.disallow();
                exported.disallow();
                if (package_->validVersion()) {
                    throw CompilerError(theToken.position(), "Package version already declared.");
                }

                auto major = std::stoi(stream_.consumeToken(TokenType::Integer).value().utf8());
                auto minor = std::stoi(stream_.consumeToken(TokenType::Integer).value().utf8());

                package_->setPackageVersion(PackageVersion(major, minor));
                if (!package_->validVersion()) {
                    throw CompilerError(theToken.position(), "The provided package version is not valid.");
                }

                package_->setDocumentation(documentation.get());

                continue;
            }
            case E_WALE: {
                final.disallow();
                exported.disallow();
                documentation.disallow();

                auto parsedType = parseType();

                Type type = Type::nothingness();

                if (!package_->fetchRawType(parsedType, false, &type)) {
                    throw CompilerError(parsedType.token.position(), "Class does not exist.");
                }
                if (type.type() != TypeContent::Class && type.type() != TypeContent::ValueType) {
                    throw CompilerError(parsedType.token.position(), "Only classes and value types are extendable.");
                }

                // Native extensions are allowed if the class was defined in this package.
                parseTypeDefinitionBody(type, nullptr, type.typeDefinitionFunctional()->package() == package_);

                continue;
            }
            case E_RABBIT:
                parseClass(documentation.get(), theToken, exported.set(), final.set());
                continue;
            case E_DOVE_OF_PEACE:
                final.disallow();
                parseValueType(documentation.get(), theToken, exported.set());
                continue;
            case E_SCROLL: {
                final.disallow();
                exported.disallow();
                documentation.disallow();

                auto &pathString = stream_.consumeToken(TokenType::String);
                auto relativePath = std::string(pathString.position().file);
                auto fileString = pathString.value().utf8();

                auto lastSlash = relativePath.find_last_of('/');
{'fraction_non_alphanumeric': 0.11864583333333334, 'fraction_numerical': 0.0033333333333333335, 'mean_word_length': 1.822993237283152, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '4992683', 'n_tokens_mistral': 2504, 'n_tokens_neox': 2300, 'n_words': 475}