Repository navigation
Expand file tree
/
Copy pathlexer.cpp
More file actions
116 lines (98 loc) · 3.28 KB
/
Copy pathlexer.cpp
File metadata and controls
116 lines (98 loc) · 3.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// lexer.cpp
#include "lexer.h"
#include <cctype>
#include <unordered_map>
Lexer::Lexer(const std::string& filename, const std::string& text)
: filename(filename), text(text), pos(0) {
current_char = text[pos];
}
void Lexer::advance() {
pos++;
current_char = pos < text.size() ? text[pos] : '\0';
}
void Lexer::skip_whitespace() {
while (current_char == ' ' || current_char == '\t' || current_char == '\r') {
advance();
}
}
Token Lexer::make_number() {
size_t start = pos;
std::string num_str;
bool has_dot = false;
while (isdigit(current_char) || current_char == '.') {
if (current_char == '.') {
if (has_dot) break;
has_dot = true;
}
num_str += current_char;
advance();
}
return Token(TokenType::NUMBER, num_str, start);
}
Token Lexer::make_identifier() {
size_t start = pos;
std::string id_str;
while (isalnum(current_char) || current_char == '_') {
id_str += current_char;
advance();
}
static std::unordered_map<std::string, TokenType> keywords = {
{"print", TokenType::PRINT},
{"let", TokenType::LET},
{"trace", TokenType::TRACE},
{"times", TokenType::TIMES},
{"read", TokenType::READ},
{"rand", TokenType::RAND},
{"sleep", TokenType::SLEEP}
};
TokenType type = keywords.count(id_str) ? keywords[id_str] : TokenType::IDENTIFIER;
return Token(type, id_str, start);
}
Token Lexer::make_string() {
size_t start = pos;
std::string str_val;
advance();
while (current_char != '"' && current_char != '\0') {
str_val += current_char;
advance();
}
if (current_char == '"') advance();
return Token(TokenType::STRING, str_val, start);
}
Token Lexer::make_operator() {
char op_char = current_char;
size_t start = pos;
advance();
switch (op_char) {
case '+': return Token(TokenType::PLUS, "+", start);
case '-': return Token(TokenType::MINUS, "-", start);
case '*': return Token(TokenType::MULTIPLY, "*", start);
case '/': return Token(TokenType::DIVIDE, "/", start);
case '%': return Token(TokenType::MODULO, "%", start);
case '(': return Token(TokenType::LPAREN, "(", start);
case ')': return Token(TokenType::RPAREN, ")", start);
case '=': return Token(TokenType::EQUALS, "=", start);
case ';': return Token(TokenType::SEMICOLON, ";", start);
default: return Token(TokenType::UNKNOWN, std::string(1, op_char), start);
}
}
std::pair<std::vector<Token>, Error> Lexer::make_tokens() {
std::vector<Token> tokens;
while (current_char != '\0') {
if (current_char == ' ' || current_char == '\t' || current_char == '\r') {
skip_whitespace();
} else if (current_char == '\n') {
tokens.push_back(Token(TokenType::NEWLINE, "\\n", pos));
advance();
} else if (isdigit(current_char)) {
tokens.push_back(make_number());
} else if (isalpha(current_char)) {
tokens.push_back(make_identifier());
} else if (current_char == '"') {
tokens.push_back(make_string());
} else {
tokens.push_back(make_operator());
}
}
return { tokens, Error() };
}