-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlexer.cpp
90 lines (71 loc) · 2.19 KB
/
lexer.cpp
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
#include "lexer.hpp"
#include <utility>
TextSpan::TextSpan(const unsigned long long begin, const unsigned long long end) : begin(begin), end(end) { }
Token::Token(const TextSpan& span, const TokenKind type, const char value)
: span(span), type(type), value(value) { }
auto TokenStream::lookahead() -> Token {
if (stash)
return stash.value();
auto token = supplier();
stash.emplace(token);
return token;
}
auto TokenStream::next() -> Token {
if (!stash)
return supplier();
auto temp = stash.value();
stash = std::nullopt;
return temp;
}
TokenStream::TokenStream(std::function<Token()> supplier) : supplier(std::move(supplier)) {
stash = std::nullopt;
}
auto Lexer::lex() -> TokenStream {
static std::unordered_map<char, TokenKind> tokenMap = {
{ '.', TokenKind::Dot },
{ ',', TokenKind::Comma },
{ '<', TokenKind::LeftAngledBracket },
{ '>', TokenKind::RightAngledBracket },
{ '[', TokenKind::LeftBracket },
{ ']', TokenKind::RightBracket },
{ '+', TokenKind::Plus },
{ '-', TokenKind::Minus }
};
return TokenStream([&]() {
char character;
TextSpan span = TextSpan(0, 0);
TokenKind type;
do {
character = supply();
if (character == '\0')
return Token(TextSpan(position, position), TokenKind::EndOfFile, '\0');
span = TextSpan(position - 1, position);
auto search = tokenMap.find(character);
type = search == tokenMap.end() ? TokenKind::Comment : search->second;
} while (type == TokenKind::Comment);
return Token(span, type, character);
});
}
TextLexer::TextLexer(std::string text) : text(std::move(text)) {
position = 0;
}
auto TextLexer::supply() -> char {
if (position >= text.length())
return '\0';
return text[position++];
}
FileLexer::FileLexer(std::ifstream stream) : stream(std::move(stream)) {
position = 0;
done = false;
}
auto FileLexer::supply() -> char {
if (done)
return '\0';
position++;
auto data = stream.get();
if (data == -1) {
done = true;
return '\0';
}
return data;
}