Add interpreter
This commit is contained in:
parent
a8e6a4552b
commit
ede4dea616
4
Makefile
4
Makefile
@ -6,7 +6,7 @@ CXX := g++
|
||||
LD_CXXFLAGS =
|
||||
|
||||
# Compilation flag
|
||||
CXXFLAGS = -Wall -Wextra -g -O3
|
||||
CXXFLAGS = -Wall -Wextra -g -O3 -std=c++2a
|
||||
# Remove warnings about unused variables, functions, ...
|
||||
# -Wno-unused-parameter -Wno-unused-function -Wno-unused-variable -Wno-unused-but-set-variable
|
||||
# Compile with debug
|
||||
@ -14,7 +14,7 @@ CXXFLAGS = -Wall -Wextra -g -O3
|
||||
# See memory leaks and Incorrect Read/Write
|
||||
# -fsanitize=address -lasan
|
||||
|
||||
$(BUILDDIR)/main: $(SRCDIR)/main.cpp $(BUILDDIR)/input.o src/include/parser.h
|
||||
$(BUILDDIR)/main: $(SRCDIR)/main.cpp $(BUILDDIR)/input.o $(BUILDDIR)/interpreter.o $(BUILDDIR)/parser.o $(BUILDDIR)/tokenize.o
|
||||
$(CXX) $^ -o $@ $(CXXFLAGS) $(LD_CXXFLAGS)
|
||||
|
||||
|
||||
|
@ -1,6 +1,12 @@
|
||||
#ifndef DEF_INPUT_H
|
||||
#define DEF_INPUT_H
|
||||
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
Retrieves user input
|
||||
*/
|
||||
string get_input();
|
||||
|
||||
#endif
|
@ -1,6 +1,14 @@
|
||||
#ifndef INTERPRETER_H
|
||||
#define INTERPRETER_H
|
||||
|
||||
#include <variant>
|
||||
using namespace std;
|
||||
|
||||
using EvalResult = variant<int, monostate>;
|
||||
|
||||
/*
|
||||
Evaluates the AST, returning the latest calulated value
|
||||
*/
|
||||
EvalResult eval(Node &ast);
|
||||
|
||||
#endif
|
@ -56,7 +56,6 @@ enum class NodeType {
|
||||
Mod, // -> F % T
|
||||
UnaryMinus, // -> -F
|
||||
UnaryPlus, // -> +F
|
||||
Parenthesis, // -> (Expr)
|
||||
Assignment // -> Identifier = Expr
|
||||
};
|
||||
|
||||
|
@ -6,14 +6,24 @@
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
enum class TokenType { Type, Identifier, Number, Plus, Minus, Star, Slash, Percent, Equal, Semicolon, LParenthese, RParenthese };
|
||||
enum class TokenType { Type, Identifier, Int, Plus, Minus, Star, Slash, Percent, Equal, Semicolon, LParenthese, RParenthese };
|
||||
enum class Type { Int };
|
||||
|
||||
using TokenData = variant<double, string, Type>;
|
||||
using TokenData = variant<int, string, Type>;
|
||||
|
||||
struct Token {
|
||||
TokenType type;
|
||||
TokenData data;
|
||||
};
|
||||
|
||||
/*
|
||||
Parses a string into a vector of tokens
|
||||
*/
|
||||
vector<Token> tokenize(string str);
|
||||
|
||||
/*
|
||||
Formats a list of tokens and prints it
|
||||
*/
|
||||
void _debug_print_tokens(vector<Token> tokens);
|
||||
|
||||
#endif
|
@ -1,16 +1,105 @@
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include "include/parser.h"
|
||||
#include "include/interpreter.h"
|
||||
using namespace std;
|
||||
|
||||
void eval(Node &ast) {
|
||||
unordered_map<string, int> memory;
|
||||
|
||||
EvalResult eval(Node &ast) {
|
||||
if (ast.index() == 0) {
|
||||
InnerNode node = get<InnerNode>(ast);
|
||||
switch (node.type) {
|
||||
case NodeType::Prog:
|
||||
eval(node.children[0]);
|
||||
return eval(node.children[1]);
|
||||
break;
|
||||
case NodeType::Epsilon:
|
||||
return {};
|
||||
break;
|
||||
case NodeType::Plus: {
|
||||
int e1 = get<int>(eval(node.children[0]));
|
||||
int e2 = get<int>(eval(node.children[1]));
|
||||
return e1 + e2;
|
||||
} break;
|
||||
case NodeType::Minus: {
|
||||
int e1 = get<int>(eval(node.children[0]));
|
||||
int e2 = get<int>(eval(node.children[1]));
|
||||
return e1 - e2;
|
||||
} break;
|
||||
case NodeType::Mult: {
|
||||
int e1 = get<int>(eval(node.children[0]));
|
||||
int e2 = get<int>(eval(node.children[1]));
|
||||
return e1 * e2;
|
||||
} break;
|
||||
case NodeType::Div: {
|
||||
int e1 = get<int>(eval(node.children[0]));
|
||||
int e2 = get<int>(eval(node.children[1]));
|
||||
// if (e2 == 0)
|
||||
return e1 / e2;
|
||||
} break;
|
||||
case NodeType::Mod: {
|
||||
int e1 = get<int>(eval(node.children[0]));
|
||||
int e2 = get<int>(eval(node.children[1]));
|
||||
// if (e2 == 0)
|
||||
return e1 % e2;
|
||||
} break;
|
||||
case NodeType::UnaryPlus: {
|
||||
int e1 = get<int>(eval(node.children[0]));
|
||||
return +e1;
|
||||
} break;
|
||||
case NodeType::UnaryMinus: {
|
||||
int e1 = get<int>(eval(node.children[0]));
|
||||
return -e1;
|
||||
} break;
|
||||
case NodeType::Declaration: {
|
||||
Token typeTok = get<Token>(node.children[0]);
|
||||
Token identifierTok = get<Token>(node.children[1]);
|
||||
string identifier = get<string>(identifierTok.data);
|
||||
|
||||
memory[identifier] = 0;
|
||||
|
||||
return {};
|
||||
} break;
|
||||
case NodeType::AssignedDeclaration: {
|
||||
Token typeTok = get<Token>(node.children[0]);
|
||||
Token identifierTok = get<Token>(node.children[1]);
|
||||
string identifier = get<string>(identifierTok.data);
|
||||
int expr = get<int>(eval(node.children[2]));
|
||||
|
||||
memory[identifier] = expr;
|
||||
|
||||
return expr;
|
||||
} break;
|
||||
case NodeType::Assignment: {
|
||||
Token identifierTok = get<Token>(node.children[0]);
|
||||
string identifier = get<string>(identifierTok.data);
|
||||
int expr = get<int>(eval(node.children[1]));
|
||||
|
||||
memory[identifier] = expr;
|
||||
|
||||
return expr;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Token token = get<Token>(ast);
|
||||
switch (token.type) {
|
||||
case TokenType::Int: {
|
||||
return get<int>(token.data);
|
||||
} break;
|
||||
case TokenType::Identifier: {
|
||||
string identifier = get<string>(token.data);
|
||||
// if (!memory.contains(identifier)) return;
|
||||
return memory[identifier];
|
||||
} break;
|
||||
default:
|
||||
throw;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
Token oneTok = {
|
||||
.type = TokenType::Number,
|
||||
.data = 1.0
|
||||
};
|
||||
Node one = oneTok;
|
||||
return {};
|
||||
}
|
16
src/main.cpp
16
src/main.cpp
@ -2,9 +2,21 @@
|
||||
using namespace std;
|
||||
|
||||
#include "include/input.h"
|
||||
#include "include/tokenize.h"
|
||||
#include "include/parser.h"
|
||||
|
||||
#include "include/interpreter.h"
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
return 0;
|
||||
while (true) {
|
||||
try {
|
||||
string input = get_input();
|
||||
vector<Token> tokens = tokenize(input);
|
||||
Node ast = parse(tokens);
|
||||
EvalResult res = eval(ast);
|
||||
cout << get<int>(res) << endl;
|
||||
}
|
||||
catch (...) { // temp
|
||||
cout << "err" << endl;
|
||||
}
|
||||
}
|
||||
}
|
@ -271,7 +271,7 @@ ParseReturn parse_f(vector<Token> tokens) {
|
||||
throw new ParseException;
|
||||
|
||||
switch (tokens.back().type) {
|
||||
case TokenType::Number: { //* U -> Number
|
||||
case TokenType::Int: { //* U -> Number
|
||||
Token number = tokens.back();
|
||||
tokens.pop_back();
|
||||
return {
|
||||
@ -288,12 +288,9 @@ ParseReturn parse_f(vector<Token> tokens) {
|
||||
throw new ParseException;
|
||||
|
||||
tokens.pop_back();
|
||||
InnerNode node = {
|
||||
.type=NodeType::Parenthesis,
|
||||
.children={ ret.node }
|
||||
};
|
||||
|
||||
return {
|
||||
.node=node,
|
||||
.node=ret.node,
|
||||
.tokens=tokens
|
||||
};
|
||||
}
|
||||
|
@ -9,14 +9,14 @@ regex NUMBER_REGEX ("\\d+(\\.\\d+)?");
|
||||
regex TYPE_INT_REGEX ("int\\s");
|
||||
regex IDENTIFIER_REGEX ("[A-Za-z_]\\w*");
|
||||
|
||||
void print_tokens(vector<Token> tokens) {
|
||||
void _debug_print_tokens(vector<Token> tokens) {
|
||||
for (Token token : tokens) {
|
||||
switch (token.type) {
|
||||
case TokenType::Type:
|
||||
cout << "Type(INT)";
|
||||
break;
|
||||
case TokenType::Number:
|
||||
cout << "Number(" << get<double>(token.data) << ")";
|
||||
case TokenType::Int:
|
||||
cout << "Number(" << get<int>(token.data) << ")";
|
||||
break;
|
||||
case TokenType::Identifier:
|
||||
cout << "Identifier(" << get<string>(token.data) << ")";
|
||||
@ -61,8 +61,8 @@ vector<Token> tokenize(string str) {
|
||||
smatch m;
|
||||
if (regex_search(str, m, NUMBER_REGEX, regex_constants::match_continuous)) {
|
||||
Token token = {
|
||||
.type = TokenType::Number,
|
||||
.data = stod(m.str())
|
||||
.type = TokenType::Int,
|
||||
.data = stoi(m.str())
|
||||
};
|
||||
tokens.emplace_back(token);
|
||||
str.erase(0, m.str().length());
|
||||
|
Loading…
Reference in New Issue
Block a user