// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <algorithm>
#include <string>
#include <vector>

#include "types.h"

#include "syscall_parser.h"

using std::string;
using std::vector;

bool is_identifier_keyword(const string& iden) {
    if (iden == "syscall" ||
        iden == "returns" ||
        iden == "optional" ||
        iden == "IN" || iden == "OUT" || iden == "INOUT") {
        return true;
    }
    return false;
}

bool vet_identifier(const string& iden, const FileCtx& fc) {
    if (iden.empty()) {
        fc.print_error("expecting idenfier", "");
        return false;
    }

    if (is_identifier_keyword(iden)) {
        fc.print_error("identifier cannot be keyword or attribute", iden);
        return false;
    }
    if (!isalpha(iden[0])) {
        fc.print_error("identifier should start with a-z|A-Z", string(iden));
        return false;
    }
    return true;
}

bool parse_param_attributes(TokenStream* ts, vector<string>* attrs) {
    while (ts->peek_next() != ")" && ts->peek_next() != ",") {
        auto attr = ts->next();
        attrs->push_back(attr);
    }
    return true;
}

bool parse_product_of_identifiers(TokenStream* ts, TypeSpec* type_spec,
                                  std::vector<std::string>* identifiers) {
    while (true) {
        if (!vet_identifier(ts->curr(), ts->filectx()))
            return false;
        if (ts->curr() == type_spec->name) {
            ts->filectx().print_error("invalid name for an array specifier", ts->curr());
            return false;
        }
        identifiers->push_back(ts->curr());
        if (ts->next() == "]") {
            return true;
        }
        if (ts->curr() != "*") {
            ts->filectx().print_error("expected ']' or '*'", "");
            return false;
        }
        ts->next(); // consume '*'
    }
}

bool parse_arrayspec(TokenStream* ts, TypeSpec* type_spec) {
    uint32_t count = 0;
    std::vector<std::string> multipliers;

    if (ts->next() != "[")
        return false;

    if (ts->next().empty())
        return false;

    auto c = ts->curr()[0];

    if (isalpha(c)) {
        if (!parse_product_of_identifiers(ts, type_spec, &multipliers)) {
            return false;
        }
    } else if (isdigit(c)) {
        count = c - '0';
        if (ts->curr().size() > 1 || count == 0 || count > 9) {
            ts->filectx().print_error("only 1-9 explicit array count allowed", "");
            return false;
        }
        if (ts->next() != "]") {
            ts->filectx().print_error("expected", "]");
            return false;
        }
    } else {
        ts->filectx().print_error("expected array specifier", "");
        return false;
    }
    type_spec->arr_spec.reset(new ArraySpec{ArraySpec::IN, count, multipliers});
    return true;
}

bool parse_typespec(TokenStream* ts, TypeSpec* type_spec) {
    if (ts->peek_next() == ":") {
        auto name = ts->curr();
        if (!vet_identifier(name, ts->filectx()))
            return false;

        type_spec->name = name;

        ts->next();
        if (ts->next().empty())
            return false;
    }

    auto type = ts->curr();
    if (!vet_identifier(type, ts->filectx()))
        return false;

    type_spec->type = type;

    if (ts->peek_next() == "[" && !parse_arrayspec(ts, type_spec)) {
        return false;
    }

    if (!parse_param_attributes(ts, &type_spec->attributes)) {
        return false;
    }

    if (type_spec->arr_spec && !type_spec->arr_spec->assign_kind(type_spec->attributes)) {
        ts->filectx().print_error("expected", "IN, INOUT or OUT");
        return false;
    }
    return true;
}

bool parse_argpack(TokenStream* ts, vector<TypeSpec>* v) {
    if (ts->curr() != "(") {
        ts->filectx().print_error("expected", "(");
        return false;
    }

    while (true) {
        if (ts->next() == ")")
            break;

        if (v->size() > 0) {
            if (ts->curr() != ",") {
                ts->filectx().print_error("expected", ", or :");
                return false;
            }
            ts->next();
        }

        TypeSpec type_spec;

        if (!parse_typespec(ts, &type_spec))
            return false;
        v->emplace_back(std::move(type_spec));
    }
    return true;
}

bool process_comment(AbigenGenerator* parser, TokenStream& ts) {
    if (ts.peek_next() == "!") {
        ts.next();  // '!'
        Requirement req;
        for (;;) {
            req.emplace_back(ts.next());
            if (ts.peek_next() == std::string())
                break;
        }
        parser->AppendRequirement(std::move(req));
    } else if (ts.peek_next() == "^") {
        ts.next();  // '^'
        TopDescription td;
        for (;;) {
            td.emplace_back(ts.next());
            if (ts.peek_next() == std::string())
                break;
        }
        parser->SetTopDescription(std::move(td));
    }
    return true;
}

bool process_syscall(AbigenGenerator* parser, TokenStream& ts) {
    auto name = ts.next();

    if (!vet_identifier(name, ts.filectx()))
        return false;

    Syscall syscall{ts.filectx(), name};

    // Every entry gets the special catch-all "*" attribute.
    syscall.attributes.push_back("*");

    while (true) {
        auto maybe_attr = ts.next();
        if (maybe_attr[0] != '(') {
            syscall.attributes.push_back(maybe_attr);
        } else {
            break;
        }
    }

    if (!parse_argpack(&ts, &syscall.arg_spec))
        return false;

    auto return_spec = ts.next();

    if (return_spec == "returns") {
        ts.next();

        if (!parse_argpack(&ts, &syscall.ret_spec)) {
            return false;
        }
        if (syscall.ret_spec.size() > 1) {
            std::for_each(syscall.ret_spec.begin() + 1, syscall.ret_spec.end(),
                          [](TypeSpec& type_spec) {
                              type_spec.arr_spec.reset(
                                  new ArraySpec{ArraySpec::OUT, 1, {}});
                          });
        }
    } else if (return_spec != ";") {
        ts.filectx().print_error("expected", ";");
        return false;
    }

    return parser->AddSyscall(std::move(syscall));
}
