namespace std

This commit is contained in:
Shautvast 2024-10-22 12:23:46 +02:00
parent 9477e68e18
commit b6309de7a2
7 changed files with 90 additions and 81 deletions

View file

@ -7,10 +7,12 @@
#include <string> #include <string>
#include <vector> #include <vector>
void print_tokens(std::vector<Token> *list); using namespace std;
int run_file(std::string file);
void print_tokens(vector<Token> *list);
int run_file(string file);
void run_prompt(void); void run_prompt(void);
ScanResult run(std::string source); ScanResult run(string source);
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
if (argc > 2) { if (argc > 2) {
@ -24,9 +26,9 @@ int main(int argc, char *argv[]) {
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
int run_file(std::string filename) { int run_file(string filename) {
std::string content; string content;
std::ifstream file; ifstream file;
file.open(filename); file.open(filename);
if (file.is_open()) { if (file.is_open()) {
file >> content; file >> content;
@ -40,33 +42,33 @@ int run_file(std::string filename) {
} }
void run_prompt(void) { void run_prompt(void) {
std::string line; string line;
for (;;) { for (;;) {
std::cout << ">"; cout << ">";
std::getline(std::cin, line); getline(cin, line);
ScanResult scan_result = run(line.substr(0, line.length())); ScanResult scan_result = run(line.substr(0, line.length()));
// print_tokens(&scan_result.token_list); // print_tokens(&scan_result.token_list);
if (!scan_result.had_error) { if (!scan_result.had_error) {
Expression *e = (new Parser())->parse(scan_result.token_list); Expression *e = (new Parser())->parse(scan_result.token_list);
std::cout << e->to_string(); cout << e->as_string();
std::cout << "\n"; cout << "\n";
} }
} }
} }
ScanResult run(std::string source) { ScanResult run(string source) {
Scanner *scanner = new Scanner(source); Scanner *scanner = new Scanner(source);
return scanner->scan_tokens(); return scanner->scan_tokens();
} }
void print_tokens(std::vector<Token> *list) { void print_tokens(vector<Token> *list) {
for (std::vector<Token>::iterator token = list->begin(); token != list->end(); for (vector<Token>::iterator token = list->begin(); token != list->end();
++token) { ++token) {
std::cout << token->to_string() << "(" << token->literal << "), "; cout << token->as_string() << "(" << token->literal << "), ";
} }
std::cout << "\n"; cout << "\n";
} }

View file

@ -1,13 +1,15 @@
#include "parser.hpp" #include "parser.hpp"
using namespace std;
Expression::~Expression() {} Expression::~Expression() {}
// class Binary // class Binary
ExprType Binary::get_type() { return ExprType::Binary; } ExprType Binary::get_type() { return ExprType::Binary; }
std::string Binary::to_string() { string Binary::as_string() {
return "(" + token_name(op->tokentype) + " " + left->to_string() + " " + return "(" + token_name(op->tokentype) + " " + left->as_string() + " " +
right->to_string() + ")"; right->as_string() + ")";
} }
Binary::Binary(Expression *_left, Token *_operator, Expression *_right) Binary::Binary(Expression *_left, Token *_operator, Expression *_right)
@ -22,7 +24,7 @@ Binary::~Binary() {
// class Grouping // class Grouping
ExprType Grouping::get_type() { return ExprType::Grouping; } ExprType Grouping::get_type() { return ExprType::Grouping; }
std::string Grouping::to_string() { return "(" + expr->to_string() + ")"; } string Grouping::as_string() { return "(" + expr->as_string() + ")"; }
Grouping::Grouping(Expression *_expr) : expr(_expr){}; Grouping::Grouping(Expression *_expr) : expr(_expr){};
@ -31,8 +33,8 @@ Grouping::~Grouping() { delete expr; }
// class Unary // class Unary
ExprType Unary::get_type() { return ExprType::Unary; } ExprType Unary::get_type() { return ExprType::Unary; }
std::string Unary::to_string() { string Unary::as_string() {
return token_name(op->tokentype) + right->to_string(); return token_name(op->tokentype) + right->as_string();
} }
Unary::Unary(Token *_operator, Expression *_right) Unary::Unary(Token *_operator, Expression *_right)
@ -44,14 +46,14 @@ Unary::~Unary() {
} }
// class Literal // class Literal
std::string Literal::to_string() { string Literal::as_string() {
std::string text; string text;
switch (valuetype) { switch (valuetype) {
case String: case String:
text = "\"" + value.str + "\""; text = "\"" + value.str + "\"";
break; break;
case Numeric: case Numeric:
text = std::to_string(value.numeric); text = to_string(value.numeric);
break; break;
case Boolean: case Boolean:
text = value.boolean ? "True" : "False"; text = value.boolean ? "True" : "False";
@ -63,7 +65,7 @@ std::string Literal::to_string() {
return text; return text;
} }
Expression *Parser::parse(std::vector<Token> tokenlist) { Expression *Parser::parse(vector<Token> tokenlist) {
tokens = tokenlist; tokens = tokenlist;
current_token = 0; current_token = 0;
return expression(); return expression();

View file

@ -7,49 +7,48 @@
enum class ExprType { Binary, Grouping, Unary, Literal, None }; enum class ExprType { Binary, Grouping, Unary, Literal, None };
using namespace std;
/// Base class for expressions /// Base class for expressions
class Expression { class Expression {
public: public:
virtual ExprType get_type() = 0; // abstract, getter for tyoe virtual ExprType get_type() = 0; // abstract, getter for tyoe
virtual std::string to_string() = 0; // abstract, string rep for debugging virtual string as_string() = 0; // abstract, string rep for debugging
virtual ~Expression(); // destructor virtual ~Expression(); // destructor
}; }; // namespace stdclass Expression
/// An expression with two operands /// An expression with two operands
class Binary : public Expression { class Binary : public Expression {
private:
Expression *left; Expression *left;
Token *op; Token *op;
Expression *right; Expression *right;
public: public:
ExprType get_type() override; ExprType get_type() override;
std::string to_string() override; string as_string() override;
Binary(Expression *_left, Token *_operator, Expression *_right); Binary(Expression *_left, Token *_operator, Expression *_right);
~Binary(); ~Binary();
}; };
/// An expression between parentheses /// An expression between parentheses
class Grouping : public Expression { class Grouping : public Expression {
private:
Expression *expr; Expression *expr;
public: public:
ExprType get_type() override; ExprType get_type() override;
std::string to_string() override; string as_string() override;
Grouping(Expression *_expr); Grouping(Expression *_expr);
~Grouping(); ~Grouping();
}; };
/// An expression with one operand (operator is `-` or `!`) /// An expression with one operand (operator is `-` or `!`)
class Unary : public Expression { class Unary : public Expression {
private:
Token *op; Token *op;
Expression *right; Expression *right;
public: public:
ExprType get_type() override; ExprType get_type() override;
std::string to_string() override; string as_string() override;
Unary(Token *_operator, Expression *_right); Unary(Token *_operator, Expression *_right);
~Unary(); ~Unary();
}; };
@ -67,28 +66,27 @@ public:
union Value { union Value {
double_t numeric; double_t numeric;
bool boolean; bool boolean;
std::string str; string str;
Void dummy; Void dummy;
Value(double_t _numeric) : numeric(_numeric) {} Value(double_t _numeric) : numeric(_numeric) {}
Value(bool _boolean) : boolean(_boolean) {} Value(bool _boolean) : boolean(_boolean) {}
Value(std::string _str) : str(_str) {} Value(string _str) : str(_str) {}
Value(Void v) : dummy(v) {} Value(Void v) : dummy(v) {}
~Value() {} ~Value() {}
} value; } value;
Literal(Void v) : valuetype(ValueType::Nil), value(v){}; Literal(Void v) : valuetype(ValueType::Nil), value(v){};
Literal(double_t _numeric) : valuetype(ValueType::Numeric), value(_numeric){}; Literal(double_t _numeric) : valuetype(ValueType::Numeric), value(_numeric){};
Literal(std::string _str) : valuetype(ValueType::String), value(_str){}; Literal(string _str) : valuetype(ValueType::String), value(_str){};
Literal(bool _boolean) : valuetype(ValueType::Boolean), value(_boolean){}; Literal(bool _boolean) : valuetype(ValueType::Boolean), value(_boolean){};
std::string to_string() override; string as_string() override;
}; };
class Parser { class Parser {
private: vector<Expression> expressions;
std::vector<Expression> expressions; vector<Token> tokens;
std::vector<Token> tokens;
int current_token; int current_token;
Token peek() { return tokens[current_token]; }; Token peek() { return tokens[current_token]; };
@ -116,7 +114,7 @@ private:
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
Token::Type ttc = va_arg(list, Token::Type); Token::Type ttc = va_arg(list, Token::Type);
// std::cout << token_name(ttc) << "\n"; // cout << token_name(ttc) << "\n";
if (check(ttc)) { if (check(ttc)) {
advance(); advance();
return true; return true;
@ -125,16 +123,16 @@ private:
return false; return false;
}; };
Token *consume(Token::Type typ, std::string message) { Token *consume(Token::Type typ, string message) {
if (check(typ)) { if (check(typ)) {
return advance(); return advance();
} }
throw error(peek(), message); throw error(peek(), message);
} }
std::runtime_error error(Token token, std::string message) { runtime_error error(Token token, string message) {
std::cout << token.to_string() << " " << message; cout << token.as_string() << " " << message;
return std::runtime_error(message); return runtime_error(message); // TODO no exceptions
} }
Expression *primary() { Expression *primary() {
@ -145,7 +143,7 @@ private:
if (match(1, Token::Type::NIL)) if (match(1, Token::Type::NIL))
return new Literal(new Void()); return new Literal(new Void());
if (match(1, Token::Type::NUMBER)) { if (match(1, Token::Type::NUMBER)) {
return new Literal(std::stod(previous()->literal)); return new Literal(stod(previous()->literal));
} }
if (match(1, Token::Type::STRING)) { if (match(1, Token::Type::STRING)) {
return new Literal(previous()->literal); return new Literal(previous()->literal);
@ -155,11 +153,11 @@ private:
consume(Token::Type::RIGHT_PAREN, "Expect ')'."); consume(Token::Type::RIGHT_PAREN, "Expect ')'.");
return new Grouping(e); return new Grouping(e);
} }
throw std::runtime_error("Expected an expression"); throw runtime_error("Expected an expression");
} }
public: public:
Expression *parse(std::vector<Token> tokenlist); Expression *parse(vector<Token> tokenlist);
Expression *unary() { Expression *unary() {
if (match(2, Token::BANG, Token::Type::MINUS)) { if (match(2, Token::BANG, Token::Type::MINUS)) {
Token *op = previous(); Token *op = previous();

View file

@ -6,7 +6,9 @@
#include <string> #include <string>
#include <vector> #include <vector>
static const std::map<std::string, Token::Type> keywords = { using namespace std;
static const map<string, Token::Type> keywords = {
{"and", Token::Type::AND}, {"class", Token::Type::CLASS}, {"and", Token::Type::AND}, {"class", Token::Type::CLASS},
{"else", Token::Type::ELSE}, {"false", Token::Type::FALSE}, {"else", Token::Type::ELSE}, {"false", Token::Type::FALSE},
{"for", Token::Type::FOR}, {"fun", Token::Type::FUN}, {"for", Token::Type::FOR}, {"fun", Token::Type::FUN},
@ -17,9 +19,9 @@ static const std::map<std::string, Token::Type> keywords = {
{"var", Token::Type::VAR}, {"while", Token::Type::WHILE}, {"var", Token::Type::VAR}, {"while", Token::Type::WHILE},
}; };
Scanner::Scanner(std::string s) Scanner::Scanner(string _source)
: had_error(false), current_pos(0), start(0), current_line(1), source(s), : had_error(false), current_pos(0), start(0), current_line(1),
token_list(std::vector<Token>()) {} source(_source), token_list(vector<Token>()) {}
ScanResult Scanner::scan_tokens() { ScanResult Scanner::scan_tokens() {
while (current_pos < source.length()) { while (current_pos < source.length()) {
@ -39,7 +41,7 @@ void Scanner::add_token(Token::Type type) {
token_list.push_back(token); token_list.push_back(token);
} }
void Scanner::add_token(Token::Type type, std::string literal) { void Scanner::add_token(Token::Type type, string literal) {
Token token = Token(type, literal, literal, current_line); Token token = Token(type, literal, literal, current_line);
token_list.push_back(token); token_list.push_back(token);
} }
@ -109,7 +111,7 @@ void Scanner::scan_token() {
current_line += 1; current_line += 1;
break; break;
case '"': case '"':
string(); scan_string();
break; break;
default: default:
if (is_digit(c)) { if (is_digit(c)) {
@ -128,7 +130,7 @@ void Scanner::identifier() {
advance(); advance();
} }
std::string text = source.substr(start, current_pos - start); string text = source.substr(start, current_pos - start);
auto it = keywords.find(text); auto it = keywords.find(text);
if (it != keywords.end()) { if (it != keywords.end()) {
add_token(it->second, text); add_token(it->second, text);
@ -149,7 +151,7 @@ void Scanner::number() {
bool Scanner::is_digit(char c) { return c >= '0' && c <= '9'; } bool Scanner::is_digit(char c) { return c >= '0' && c <= '9'; }
void Scanner::string() { void Scanner::scan_string() {
while (peek() != '"' && !is_at_end()) { while (peek() != '"' && !is_at_end()) {
if (peek() == '\n') if (peek() == '\n')
current_line += 1; current_line += 1;
@ -163,8 +165,8 @@ void Scanner::string() {
advance(); advance();
std::string string = source.substr(start + 1, current_pos - start - 2); string s = source.substr(start + 1, current_pos - start - 2);
add_token(Token::Type::STRING, string); add_token(Token::Type::STRING, s);
} }
bool Scanner::match(char expected) { bool Scanner::match(char expected) {
@ -200,10 +202,10 @@ bool Scanner::is_alphanumeric(char c) { return is_alpha(c) || is_digit(c); }
bool Scanner::is_at_end(void) { return current_pos >= source.length(); } bool Scanner::is_at_end(void) { return current_pos >= source.length(); }
void Scanner::error(std::string message) { report("", message); } void Scanner::error(string message) { report("", message); }
void Scanner::report(std::string where, std::string message) { void Scanner::report(string where, std::string message) {
std::cout << "*[Line " << current_line << "] Error " << where << " : " cout << "*[Line " << current_line << "] Error " << where << " : " << message
<< message << "\n"; << "\n";
had_error = true; had_error = true;
} }

View file

@ -5,9 +5,11 @@
#include <string> #include <string>
#include <vector> #include <vector>
using namespace std;
typedef struct { typedef struct {
bool had_error; bool had_error;
std::vector<Token> token_list; vector<Token> token_list;
} ScanResult; } ScanResult;
class Scanner { class Scanner {
@ -16,26 +18,26 @@ private:
size_t current_pos; size_t current_pos;
int start; int start;
int current_line; int current_line;
std::string source; string source;
std::vector<Token> token_list; vector<Token> token_list;
public: public:
Scanner(std::string s); Scanner(string s);
ScanResult scan_tokens(); ScanResult scan_tokens();
void add_token(Token::Type type); void add_token(Token::Type type);
void add_token(Token::Type type, std::string literal); void add_token(Token::Type type, string literal);
char advance(); char advance();
void scan_token(); void scan_token();
void identifier(); void identifier();
void number(); void number();
bool is_digit(char c); bool is_digit(char c);
void string(); void scan_string();
bool match(char expected); bool match(char expected);
char peek_next(); char peek_next();
char peek(); char peek();
bool is_alpha(char c); bool is_alpha(char c);
bool is_alphanumeric(char c); bool is_alphanumeric(char c);
bool is_at_end(void); bool is_at_end(void);
void error(std::string message); void error(string message);
void report(std::string where, std::string message); void report(string where, string message);
}; };

View file

@ -1,10 +1,11 @@
#include "tokens.hpp" #include "tokens.hpp"
Token::Token(Token::Type _tokentype, std::string _lexeme, std::string _literal, using namespace std;
int _line)
Token::Token(Token::Type _tokentype, string _lexeme, string _literal, int _line)
: lexeme(_lexeme), literal(_literal), line(_line), tokentype(_tokentype) {} : lexeme(_lexeme), literal(_literal), line(_line), tokentype(_tokentype) {}
std::string token_name(Token::Type tokentype) { string token_name(Token::Type tokentype) {
static const std::string tokens[] = { static const std::string tokens[] = {
"END_OF_FILE", "LEFT_PAREN", "RIGHT_PAREN", "LEFT_BRACE", "RIGHT_BRACE", "END_OF_FILE", "LEFT_PAREN", "RIGHT_PAREN", "LEFT_BRACE", "RIGHT_BRACE",
"COMMA", "DOT", "MINUS", "PLUS", "SEMICOLON", "COMMA", "DOT", "MINUS", "PLUS", "SEMICOLON",
@ -17,4 +18,4 @@ std::string token_name(Token::Type tokentype) {
return tokens[(int)tokentype]; return tokens[(int)tokentype];
} }
std::string Token::to_string() { return token_name(tokentype); } std::string Token::as_string() { return token_name(tokentype); }

View file

@ -2,10 +2,12 @@
#include <string> #include <string>
using namespace std;
class Token { class Token {
public: public:
std::string lexeme; string lexeme;
std::string literal; string literal;
int line; int line;
enum Type { enum Type {
END_OF_FILE = 0, END_OF_FILE = 0,
@ -49,10 +51,10 @@ public:
WHILE = 38, WHILE = 38,
} tokentype; } tokentype;
std::string to_string(); string as_string();
Token(Token::Type _tokentype, std::string _lexeme, std::string _literal, Token(Token::Type _tokentype, std::string _lexeme, std::string _literal,
int line); int line);
}; };
std::string token_name(Token::Type tokentype); string token_name(Token::Type tokentype);