#pragma once

#include <string>
#include <vector>

namespace nix_irc {

struct Token {
  enum Type {
    LPAREN,
    RPAREN,
    LBRACE,
    RBRACE,
    LBRACKET,
    RBRACKET,
    IDENT,
    STRING,
    STRING_INTERP,
    INDENTED_STRING,
    INDENTED_STRING_INTERP,
    PATH,
    LOOKUP_PATH,
    INT,
    FLOAT,
    URI,
    BOOL,
    LET,
    IN,
    REC,
    IF,
    THEN,
    ELSE,
    ASSERT,
    WITH,
    INHERIT,
    IMPORT,
    DOT,
    SEMICOLON,
    COLON,
    EQUALS,
    AT,
    COMMA,
    QUESTION,
    ELLIPSIS,
    // Operators
    PLUS,
    MINUS,
    STAR,
    SLASH,
    CONCAT,
    MERGE,
    EQEQ,
    NE,
    LT,
    GT,
    LE,
    GE,
    AND,
    OR,
    IMPL,
    NOT,
    EOF_
  } type;
  std::string value;
  size_t line;
  size_t col;
};

class Lexer {
public:
  Lexer(const std::string& input);
  std::vector<Token> tokenize();

private:
  std::vector<Token> tokens;
  const std::string& input;
  size_t pos;
  size_t line;
  size_t col;

  void emit(const Token& t);
  void skip_whitespace();
  void tokenize_string();
  void tokenize_indented_string();
  std::string strip_indentation(const std::string& s);
  void tokenize_path();
  void tokenize_home_path();
  void tokenize_int();
  void tokenize_float();
  void tokenize_uri();
  void tokenize_ident();
};

} // namespace nix_irc
