Line data Source code
1 : #include "stax/lexer/lexer.hpp"
2 :
3 : #include <format>
4 : #include <stax/utils/result.hpp>
5 : #include <utility>
6 :
7 : namespace stax::lexer {
8 :
9 8 : Lexer::Lexer(std::string input) : input_(std::move(input)) {
10 4 : curr_ = input_.begin();
11 4 : peek_ = curr_ + 1;
12 4 : ConsumeWhitespace();
13 4 : }
14 :
15 76 : auto Lexer::NextToken() -> result_t<token::Token> {
16 152 : if (IsWhitespace(*curr_)) {
17 43 : ConsumeWhitespace();
18 : }
19 152 : if (curr_ == input_.end()) return token::Token{token::Type::kEOF, ""};
20 :
21 70 : std::optional<token::Token> t;
22 140 : switch (const auto c = *curr_) {
23 6 : case '=': t = token::Token{token::Type::kAssign, "="}; break;
24 2 : case '+': t = token::Token{token::Type::kPlus, "+"}; break;
25 5 : case '(': t = token::Token{token::Type::kLParen, "("}; break;
26 5 : case ')': t = token::Token{token::Type::kRParen, ")"}; break;
27 4 : case '{': t = token::Token{token::Type::kLBrace, "{"}; break;
28 4 : case '}': t = token::Token{token::Type::kRBrace, "}"}; break;
29 3 : case ',': t = token::Token{token::Type::kComma, ","}; break;
30 9 : case ';': t = token::Token{token::Type::kSemicolon, ";"}; break;
31 32 : default: {
32 : // Deal with numerics and letters
33 32 : if (IsLetter(c)) {
34 24 : TRY_RESULT(const auto sv, Identifier());
35 :
36 24 : if (kKeywords.contains(sv)) {
37 3 : return token::Token{kKeywords.at(sv), sv};
38 : }
39 :
40 21 : return token::Token{token::Type::kIdent, sv};
41 24 : }
42 :
43 8 : if (IsDigit(c)) {
44 8 : TRY_RESULT(const auto sv, Number());
45 8 : return token::Token(token::Type::kInt, sv);
46 8 : }
47 :
48 0 : return result::Err(Error::IllegalCharacter,
49 0 : std::format("{} not recognized", c));
50 : }
51 : }
52 :
53 38 : Advance();
54 :
55 38 : if (t.has_value()) {
56 38 : return t.value();
57 : }
58 :
59 0 : return result::Err(Error::Syntax);
60 : }
61 :
62 24 : auto Lexer::Identifier() -> result_t<std::string_view> {
63 24 : auto beg = curr_;
64 198 : while (IsLetter(*curr_)) {
65 75 : Advance();
66 : }
67 :
68 48 : return {beg, curr_};
69 : }
70 :
71 8 : auto Lexer::Number() -> result_t<std::string_view> {
72 8 : auto beg = curr_;
73 44 : while (IsDigit(*curr_)) {
74 14 : Advance();
75 : }
76 :
77 16 : return {beg, curr_};
78 : }
79 :
80 220 : void Lexer::Advance() {
81 220 : ++curr_;
82 220 : ++peek_;
83 220 : }
84 :
85 47 : void Lexer::ConsumeWhitespace() {
86 280 : while (IsWhitespace(*curr_)) {
87 93 : Advance();
88 : }
89 47 : }
90 :
91 : } // namespace stax::lexer
|