// Copyright 2020 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 "src/lib/fidl_codec/semantic_parser.h"

#include <lib/syslog/cpp/macros.h>

#include <cctype>
#include <iostream>
#include <memory>
#include <ostream>
#include <string>

#include "src/lib/fidl_codec/library_loader.h"
#include "src/lib/fidl_codec/wire_types.h"

namespace fidl_codec {
namespace semantic {

std::ostream& ParserErrors::AddError() {
  ++error_count_;
  return os_;
}

std::ostream& ParserErrors::AddError(const Location& location) {
  ++error_count_;
  // Computes the line and column in the buffer of the error.
  std::string::const_iterator start_line = location.buffer().begin();
  int line = 1;
  int column = 1;
  std::string::const_iterator current = start_line;
  while (current != location.location()) {
    if (*current == '\n') {
      start_line = ++current;
      ++line;
      column = 1;
    } else {
      ++current;
      ++column;
    }
  }
  while (current != location.buffer().end()) {
    if (*current == '\n') {
      break;
    }
    ++current;
  }
  // Displays the line of the error (the whole line).
  os_ << std::string_view(&*start_line, current - start_line) << '\n';
  // Displays some spaces. This way, the caret will be right under the error location.
  // It will point the first character of the previous line where the error is.
  current = start_line;
  for (int i = 1; i < column; ++i) {
    os_ << ((*current == '\t') ? '\t' : ' ');
    ++current;
  }
  // Displays the marker (caret) which points to the error, the line and the column.
  os_ << "^\n" << line << ":" << column << ": ";
  // Returns the stream. This way, the caller can add the error message.
  return os_;
}

void SemanticParser::NextLexicalToken() {
  bool error_found = false;
  for (;;) {
    while (isspace(*next_)) {
      ++next_;
    }
    current_location_ = next_;
    switch (*next_) {
      case '\0':
        current_lexical_token_ = LexicalToken::kEof;
        return;
      case '\'':
        LexerString();
        return;
      case '{':
        ++next_;
        current_lexical_token_ = LexicalToken::kLeftBrace;
        return;
      case '}':
        ++next_;
        current_lexical_token_ = LexicalToken::kRightBrace;
        return;
      case '(':
        ++next_;
        current_lexical_token_ = LexicalToken::kLeftParenthesis;
        return;
      case ')':
        ++next_;
        current_lexical_token_ = LexicalToken::kRightParenthesis;
        return;
      case ':':
        ++next_;
        if (*next_ == ':') {
          ++next_;
          current_lexical_token_ = LexicalToken::kColonColon;
        } else {
          current_lexical_token_ = LexicalToken::kColon;
        }
        return;
      case ',':
        ++next_;
        current_lexical_token_ = LexicalToken::kComma;
        return;
      case '.':
        ++next_;
        current_lexical_token_ = LexicalToken::kDot;
        return;
      case '=':
        ++next_;
        current_lexical_token_ = LexicalToken::kEqual;
        return;
      case ';':
        ++next_;
        current_lexical_token_ = LexicalToken::kSemicolon;
        return;
      case '/':
        ++next_;
        current_lexical_token_ = LexicalToken::kSlash;
        return;
      default:
        if (isalpha(*next_) || (*next_ == '_')) {
          LexerIdentifier();
          return;
        }
        if (!error_found && !ignore_unknown_characters_) {
          error_found = true;
          AddError() << "Unknown character <" << *next_ << ">\n";
        }
        ++next_;
        break;
    }
  }
}

void SemanticParser::JumpToSemicolon() {
  IgnoreUnknownCharacters ignore_unknown_characters(this);
  while (!IsEof()) {
    if (IsSemicolon() || IsRightBrace()) {
      return;
    }
    if (ConsumeLeftParenthesis()) {
      SkipRightParenthesis();
    } else {
      NextLexicalToken();
    }
  }
}

void SemanticParser::SkipSemicolon() {
  IgnoreUnknownCharacters ignore_unknown_characters(this);
  while (!IsEof()) {
    if (ConsumeSemicolon() || IsRightBrace()) {
      return;
    }
    if (ConsumeLeftParenthesis()) {
      SkipRightParenthesis();
    } else {
      NextLexicalToken();
    }
  }
}

void SemanticParser::SkipBlock() {
  IgnoreUnknownCharacters ignore_unknown_characters(this);
  while (!IsEof()) {
    if (ConsumeRightBrace() || ConsumeSemicolon()) {
      return;
    }
    if (ConsumeLeftBrace()) {
      SkipRightBrace();
    } else {
      NextLexicalToken();
    }
  }
}

void SemanticParser::SkipRightBrace() {
  IgnoreUnknownCharacters ignore_unknown_characters(this);
  while (!IsEof()) {
    if (ConsumeRightBrace()) {
      return;
    }
    if (ConsumeLeftBrace()) {
      SkipRightBrace();
    } else {
      NextLexicalToken();
    }
  }
}

void SemanticParser::SkipRightParenthesis() {
  IgnoreUnknownCharacters ignore_unknown_characters(this);
  while (!IsEof()) {
    if (ConsumeRightParenthesis() || IsSemicolon()) {
      return;
    }
    if (ConsumeLeftBrace()) {
      SkipRightBrace();
    } else if (ConsumeLeftParenthesis()) {
      SkipRightParenthesis();
    } else {
      NextLexicalToken();
    }
  }
}

std::string SemanticParser::ConsumeString() {
  std::string result = std::string(current_string_);
  size_t pos = 0;
  for (;;) {
    auto backslash = result.find('\\', pos);
    if (backslash == std::string::npos) {
      NextLexicalToken();
      return result;
    }
    // We already checked that backslashes are followed by another character.
    FX_DCHECK(backslash < result.size() - 1);
    result.erase(backslash);
    pos = backslash + 1;
  }
}

void SemanticParser::ParseSemantic() {
  while (!IsEof()) {
    if (Is("library")) {
      ParseLibrary();
    } else {
      AddError() << "Keyword 'library' expected.\n";
      SkipBlock();
    }
  }
}

void SemanticParser::ParseLibrary() {
  allow_dots_in_identifiers_ = true;
  NextLexicalToken();
  if (!IsIdentifier()) {
    AddError() << "Library name expected.\n";
    SkipBlock();
    return;
  }
  allow_dots_in_identifiers_ = false;
  Library* library = library_loader_->GetLibraryFromName(std::string(current_string_));
  if (library == nullptr) {
    AddError() << "Library " << current_string_ << " not found.\n";
  } else {
    library->DecodeTypes();
  }
  NextLexicalToken();
  if (!ParseLeftBrace()) {
    SkipBlock();
    return;
  }
  while (!ConsumeRightBrace()) {
    if (!IsIdentifier()) {
      AddError() << "Protocol name expected.\n";
      SkipBlock();
      NextLexicalToken();
      return;
    }
    Protocol* protocol = nullptr;
    if (library != nullptr) {
      std::string protocol_name = library->name() + "/" + std::string(current_string_);
      if (!library->GetProtocolByName(protocol_name, &protocol)) {
        AddError() << "Protocol " << current_string_ << " not found in library " << library->name()
                   << '\n';
      }
    }
    NextLexicalToken();
    if (!ParseColonColon()) {
      SkipBlock();
      NextLexicalToken();
      return;
    }
    if (!IsIdentifier()) {
      AddError() << "Method name expected.\n";
      SkipBlock();
      NextLexicalToken();
      return;
    }
    ProtocolMethod* method = nullptr;
    if (protocol != nullptr) {
      method = protocol->GetMethodByName(current_string_);
      if (method == nullptr) {
        AddError() << "Method " << current_string_ << " not found in protocol " << protocol->name()
                   << '\n';
      }
    }
    NextLexicalToken();
    if (!ParseLeftBrace()) {
      SkipBlock();
      NextLexicalToken();
      return;
    }
    ParseMethod(method);
  }
}

void SemanticParser::ParseMethod(ProtocolMethod* method) {
  while (!ConsumeRightBrace() && !IsEof()) {
    if (Is("input_field")) {
      NextLexicalToken();
      ParseColon();
      std::unique_ptr<DisplayExpression> expression = ParseDisplayExpression();
      if (method != nullptr) {
        MethodDisplay* display = method->short_display();
        if (display == nullptr) {
          method->set_short_display(std::make_unique<MethodDisplay>());
          display = method->short_display();
        }
        display->AddInput(std::move(expression));
      }
      if (!ParseSemicolon()) {
        SkipSemicolon();
      }
    } else if (Is("result")) {
      NextLexicalToken();
      ParseColon();
      std::unique_ptr<DisplayExpression> expression = ParseDisplayExpression();
      if (method != nullptr) {
        MethodDisplay* display = method->short_display();
        if (display == nullptr) {
          method->set_short_display(std::make_unique<MethodDisplay>());
          display = method->short_display();
        }
        display->AddResult(std::move(expression));
      }
      if (!ParseSemicolon()) {
        SkipSemicolon();
      }
    } else {
      MethodSemantic* method_semantic = nullptr;
      if (method != nullptr) {
        method_semantic = method->semantic();
        if (method_semantic == nullptr) {
          method->set_semantic(std::make_unique<MethodSemantic>());
          method_semantic = method->semantic();
        }
      }
      ParseAssignment(method_semantic);
    }
  }
}

std::unique_ptr<DisplayExpression> SemanticParser::ParseDisplayExpression() {
  auto display_expression = std::make_unique<DisplayExpression>();
  if (IsString()) {
    display_expression->set_header(ConsumeString());
  }
  std::unique_ptr<Expression> expression = ParseExpression();
  if (expression != nullptr) {
    display_expression->set_expression(std::move(expression));
  }
  if (IsString()) {
    display_expression->set_footer(ConsumeString());
  }
  return display_expression;
}

void SemanticParser::ParseAssignment(MethodSemantic* method_semantic) {
  std::unique_ptr<Expression> destination = ParseExpression();
  if (destination == nullptr) {
    AddError() << "Assignment expected.\n";
    SkipSemicolon();
    return;
  }
  if (!ParseEqual()) {
    SkipSemicolon();
    return;
  }
  std::unique_ptr<Expression> source = ParseExpression();
  if (source == nullptr) {
    AddError() << "Expression expected.\n";
    SkipSemicolon();
    return;
  }
  if (method_semantic != nullptr) {
    method_semantic->AddAssignment(std::move(destination), std::move(source));
  }
  if (!ParseSemicolon()) {
    SkipSemicolon();
  }
}

std::unique_ptr<Expression> SemanticParser::ParseExpression() {
  return ParseMultiplicativeExpression();
}

std::unique_ptr<Expression> SemanticParser::ParseMultiplicativeExpression() {
  std::unique_ptr<Expression> expression = ParseAccessExpression();
  if (expression == nullptr) {
    return nullptr;
  }
  for (;;) {
    if (ConsumeSlash()) {
      std::unique_ptr<Expression> right = ParseAccessExpression();
      if (right == nullptr) {
        return nullptr;
      }
      expression = std::make_unique<ExpressionSlash>(std::move(expression), std::move(right));
    } else if (ConsumeColon()) {
      std::unique_ptr<Expression> right = ParseAccessExpression();
      if (right == nullptr) {
        return nullptr;
      }
      expression = std::make_unique<ExpressionColon>(std::move(expression), std::move(right));
    } else {
      return expression;
    }
  }
}

std::unique_ptr<Expression> SemanticParser::ParseAccessExpression() {
  std::unique_ptr<Expression> expression = ParseTerminalExpression();
  if (expression == nullptr) {
    return nullptr;
  }
  for (;;) {
    if (ConsumeDot()) {
      if (!IsIdentifier()) {
        AddError() << "Field name expected.\n";
        expression = std::make_unique<ExpressionFieldAccess>(std::move(expression), "");
      } else {
        std::string_view name = current_string_;
        NextLexicalToken();
        expression = std::make_unique<ExpressionFieldAccess>(std::move(expression), name);
      }
    } else {
      return expression;
    }
  }
}

std::unique_ptr<Expression> SemanticParser::ParseTerminalExpression() {
  if (IsString()) {
    return std::make_unique<ExpressionStringLiteral>(ConsumeString());
  }
  if (Consume("request")) {
    return std::make_unique<ExpressionRequest>();
  }
  if (Consume("handle")) {
    return std::make_unique<ExpressionHandle>();
  }
  if (Consume("HandleDescription")) {
    return ParseHandleDescription();
  }
  return nullptr;
}

std::unique_ptr<Expression> SemanticParser::ParseHandleDescription() {
  if (!ParseLeftParenthesis()) {
    JumpToSemicolon();
    return std::make_unique<ExpressionHandleDescription>(nullptr, nullptr);
  }
  std::unique_ptr<Expression> type = ParseExpression();
  if (type == nullptr) {
    AddError() << "Expression expected (handle type)";
    SkipRightParenthesis();
    return std::make_unique<ExpressionHandleDescription>(nullptr, nullptr);
  }
  if (!ParseComma()) {
    SkipRightParenthesis();
    return std::make_unique<ExpressionHandleDescription>(std::move(type), nullptr);
  }
  std::unique_ptr<Expression> path = ParseExpression();
  if (path == nullptr) {
    AddError() << "Expression expected (handle path)";
    SkipRightParenthesis();
    return std::make_unique<ExpressionHandleDescription>(std::move(type), nullptr);
  }
  if (!ParseRightParenthesis()) {
    SkipRightParenthesis();
  }
  return std::make_unique<ExpressionHandleDescription>(std::move(type), std::move(path));
}

void SemanticParser::LexerIdentifier() {
  std::string::const_iterator start = next_;
  while (isalnum(*next_) || (*next_ == '_') || ((*next_ == '.') && allow_dots_in_identifiers_)) {
    ++next_;
  }
  current_string_ = std::string_view(&*start, next_ - start);
  current_lexical_token_ = LexicalToken::kIdentifier;
}

void SemanticParser::LexerString() {
  std::string::const_iterator start = ++next_;
  while (*next_ != '\'') {
    if (*next_ == '\0') {
      AddError() << "Unterminated string.\n";
      current_lexical_token_ = LexicalToken::kString;
      next_ = start;
      current_string_ = std::string_view(&*start, 0);
      return;
    }
    if (*next_ == '\\') {
      ++next_;
      if (*next_ == '\0') {
        AddError() << "Unterminated string.\n";
        current_lexical_token_ = LexicalToken::kString;
        next_ = start;
        current_string_ = std::string_view(&*start, 0);
        return;
      }
    }
    ++next_;
  }
  current_string_ = std::string_view(&*start, next_ - start);
  ++next_;
  current_lexical_token_ = LexicalToken::kString;
}

}  // namespace semantic
}  // namespace fidl_codec
