143 lines
2.5 KiB
C++
143 lines
2.5 KiB
C++
#pragma once
|
|
|
|
#include <cstdint>
|
|
#include <fstream>
|
|
#include <string>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
|
|
namespace stela {
|
|
|
|
struct Pos {
|
|
size_t index;
|
|
int64_t line;
|
|
int64_t col;
|
|
};
|
|
|
|
struct Error {
|
|
Pos pos;
|
|
std::string message;
|
|
};
|
|
|
|
enum class TokenType {
|
|
Error,
|
|
Eof,
|
|
If,
|
|
Else,
|
|
Return,
|
|
Public,
|
|
Private,
|
|
Class,
|
|
Derivable,
|
|
Derives,
|
|
Enumeration,
|
|
Associate,
|
|
Attribute,
|
|
Operation,
|
|
StateMachine,
|
|
Transition,
|
|
Initial,
|
|
Final,
|
|
Entry,
|
|
Exit,
|
|
LParen,
|
|
RParen,
|
|
LBrace,
|
|
RBrace,
|
|
LBracket,
|
|
RBracket,
|
|
Dot,
|
|
Comma,
|
|
Semicolon,
|
|
Colon,
|
|
ColonColon,
|
|
Minus,
|
|
MinusLt,
|
|
Equal,
|
|
Id,
|
|
Int,
|
|
};
|
|
|
|
struct Token {
|
|
TokenType type;
|
|
Pos pos;
|
|
uint64_t id;
|
|
};
|
|
|
|
class Lexer {
|
|
public:
|
|
Lexer(std::ifstream& file, std::vector<Error>& errors)
|
|
: file(&file)
|
|
, current_char(file.get())
|
|
, errors(&errors)
|
|
{ }
|
|
|
|
auto next() -> Token;
|
|
|
|
private:
|
|
inline auto step()
|
|
{
|
|
if (this->current_char == EOF) {
|
|
this->eof_reached = true;
|
|
return;
|
|
}
|
|
if (this->current_char == '\n') {
|
|
this->line += 1;
|
|
this->col = 1;
|
|
} else {
|
|
this->col += 1;
|
|
}
|
|
this->current_char = this->file->get();
|
|
this->index += 1;
|
|
}
|
|
|
|
inline auto single_token(TokenType type, Pos pos) -> Token
|
|
{
|
|
step();
|
|
return token(type, pos);
|
|
}
|
|
inline auto error_token(Pos pos, std::string message) const -> Token
|
|
{
|
|
this->errors->push_back(Error { pos, message });
|
|
return token(TokenType::Error, pos);
|
|
}
|
|
inline auto token(TokenType type, Pos pos) const -> Token
|
|
{
|
|
return Token { type, pos, 0 };
|
|
}
|
|
inline auto pos() const -> Pos
|
|
{
|
|
return Pos {
|
|
.index = this->index,
|
|
.line = this->line,
|
|
.col = this->col,
|
|
};
|
|
}
|
|
|
|
inline auto done() const -> bool { return this->eof_reached; }
|
|
inline auto current() const -> char
|
|
{
|
|
return static_cast<char>(this->current_char);
|
|
}
|
|
|
|
auto populate_keyword_map();
|
|
|
|
bool eof_reached = false;
|
|
|
|
size_t index = 0;
|
|
int64_t line = 1;
|
|
int64_t col = 1;
|
|
|
|
std::ifstream* file;
|
|
int current_char;
|
|
|
|
std::unordered_map<std::string, TokenType> keyword_map {};
|
|
|
|
std::vector<std::string> symbol_values {};
|
|
std::vector<int64_t> int_values {};
|
|
|
|
std::vector<Error>* errors;
|
|
};
|
|
|
|
}
|