-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcompiler.cpp
More file actions
122 lines (107 loc) · 3.1 KB
/
compiler.cpp
File metadata and controls
122 lines (107 loc) · 3.1 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
117
118
119
120
121
122
#include "compiler.h"
void Compiler::error(std::string message) {
if (panicMode)
return;
hadError = panicMode = true;
std::cerr << "Compile error: " << message << std::endl;
}
void Compiler::advance() {
curr++;
}
void Compiler::consume(Token::Type t, std::string errMsg) {
if (t == tokens.at(curr).getType()) {
advance();
return;
}
error(errMsg);
}
void Compiler::emitByte(uint8_t byte) {
bytecodes.top()->writeByte(byte, tokens.at(curr - 1).getLine());
}
void Compiler::emitConstant(Token& t) {
std::string lit = t.getLiteral();
int l = t.getLine();
switch (t.getType()) {
case Token::NUM: bytecodes.top()->writeConstant(Value(std::stod(lit)), l); break;
case Token::STRING: bytecodes.top()->writeConstant(Value(lit), l); break;
case Token::TRUE: emitByte(Opcode::TRUE); break;
case Token::FALSE: emitByte(Opcode::FALSE); break;
case Token::NUL: emitByte(Opcode::NUL); break;
}
}
void Compiler::endCompiler() {
#ifdef DEBUG_PRINT_CODE
// if (!hadError)
bytecodes.top()->disassembleCode();
#endif
emitByte(Opcode::RETURN);
}
void Compiler::binary() {
Token::Type t = tokens.at(curr - 1).getType();
parseRule& rule = getRule(t);
parsePrecedence(static_cast<Precedence>(rule.precedence + 1));
switch (t) {
case Token::PLUS: emitByte(Opcode::ADD); break;
case Token::MINUS: emitByte(Opcode::SUBTRACT); break;
case Token::STAR: emitByte(Opcode::MULTIPLY); break;
case Token::SLASH: emitByte(Opcode::DIVIDE); break;
case Token::EQUAL: emitByte(Opcode::EQUAL); break;
case Token::GREATER: emitByte(Opcode::GREATER); break;
case Token::LESSER: emitByte(Opcode::LESSER); break;
case Token::UNEQUAL:
emitByte(Opcode::EQUAL), emitByte(Opcode::NOT);
break;
case Token::GREATEREQ:
emitByte(Opcode::LESSER), emitByte(Opcode::NOT);
break;
case Token::LESSEREQ:
emitByte(Opcode::GREATER), emitByte(Opcode::NOT);
break;
}
}
void Compiler::literal() {
emitConstant(tokens.at(curr - 1));
}
void Compiler::grouping() {
expression();
consume(Token::RPARAN, "Expected ) at line " + std::to_string(tokens.at(curr - 1).getLine()));
}
void Compiler::unary() {
Token::Type t = tokens.at(curr - 1).getType();
parsePrecedence(Precedence::UNARY);
switch (t) {
case Token::MINUS: emitByte(Opcode::NEGATE); break;
case Token::BANG: emitByte(Opcode::NOT); break;
}
}
void Compiler::parsePrecedence(Precedence precedence) {
advance();
auto prefixRule = getRule(tokens.at(curr - 1).getType()).prefix;
if (!prefixRule) {
error("Expected expression at line " + std::to_string(tokens.at(curr - 1).getLine()));
return;
};
prefixRule();
while (precedence <= getRule(tokens.at(curr).getType()).precedence) {
advance();
auto infixRule = getRule(tokens.at(curr - 1).getType()).infix;
infixRule();
}
}
Compiler::parseRule& Compiler::getRule(Token::Type t) {
return rules[t];
}
void Compiler::expression() {
parsePrecedence(Precedence::ASSIGN);
}
bool Compiler::compile(std::istream& input, Bytecode* code) {
tokens = Scanner::getTokens(input, hadError);
if (hadError)
return false;
bytecodes.push(code);
// advance();
expression();
consume(Token::FILEEND, "Expected EOF!");
endCompiler();
return !hadError;
}