implemented infix operator parsing

This commit is contained in:
Karma Riuk
2025-07-11 10:30:37 +02:00
parent 6e471a91d5
commit a7f5950a55
7 changed files with 155 additions and 6 deletions

View File

@@ -4,6 +4,13 @@
namespace ast {
infix_expr::infix_expr(
token::token token, std::string op, ast::expression* left
)
: token(std::move(token)),
op(op),
left(left) {}
std::string infix_expr::token_literal() const {
return token.literal;
}

View File

@@ -5,6 +5,7 @@
namespace ast {
struct infix_expr : expression {
infix_expr(token::token, std::string, ast::expression*);
token::token token;
expression* left;
std::string op;

View File

@@ -2,6 +2,7 @@
#include "ast/errors/error.hpp"
#include "ast/expressions/identifier.hpp"
#include "ast/expressions/infix.hpp"
#include "ast/expressions/integer.hpp"
#include "ast/expressions/prefix.hpp"
#include "token/token.hpp"
@@ -36,6 +37,40 @@ namespace parser {
token::type::MINUS,
std::bind(&parser::parse_prefix_expr, this)
);
using namespace std::placeholders;
register_infix(
token::type::PLUS,
std::bind(&parser::parse_infix_expr, this, _1)
);
register_infix(
token::type::MINUS,
std::bind(&parser::parse_infix_expr, this, _1)
);
register_infix(
token::type::ASTERISK,
std::bind(&parser::parse_infix_expr, this, _1)
);
register_infix(
token::type::SLASH,
std::bind(&parser::parse_infix_expr, this, _1)
);
register_infix(
token::type::EQ,
std::bind(&parser::parse_infix_expr, this, _1)
);
register_infix(
token::type::NEQ,
std::bind(&parser::parse_infix_expr, this, _1)
);
register_infix(
token::type::GT,
std::bind(&parser::parse_infix_expr, this, _1)
);
register_infix(
token::type::LT,
std::bind(&parser::parse_infix_expr, this, _1)
);
}
void parser::next_token() {
@@ -72,15 +107,27 @@ namespace parser {
}
}
ast::expression* parser::parse_expression(precedence) {
auto it = prefix_parse_fns.find(current.type);
if (it == prefix_parse_fns.end()) {
ast::expression* parser::parse_expression(precedence prec) {
auto prefix_it = prefix_parse_fns.find(current.type);
if (prefix_it == prefix_parse_fns.end()) {
unkown_prefix_error(current);
return nullptr;
}
prefix_parse_fn func = it->second;
return func();
prefix_parse_fn prefix = prefix_it->second;
ast::expression* left = prefix();
while (next.type != token::type::SEMICOLON
&& prec < precedence_for(next.type)) {
auto infix_it = infix_parse_fns.find(next.type);
if (infix_it == infix_parse_fns.end())
return left;
next_token();
infix_parse_fn infix = infix_it->second;
left = infix(left);
}
return left;
};
ast::return_stmt* parser::parse_return() {
@@ -178,4 +225,13 @@ namespace parser {
ret->right = parse_expression(precedence::PREFIX);
return ret;
};
ast::expression* parser::parse_infix_expr(ast::expression* left) {
ast::infix_expr* ret =
new ast::infix_expr(current, current.literal, left);
precedence prec = precedence_for(current.type);
next_token();
ret->right = parse_expression(prec);
return ret;
};
} // namespace parser

View File

@@ -49,5 +49,7 @@ namespace parser {
ast::expression* parse_identifier();
ast::expression* parse_integer();
ast::expression* parse_prefix_expr();
ast::expression* parse_infix_expr(ast::expression*);
};
} // namespace parser

22
src/parser/precedence.cpp Normal file
View File

@@ -0,0 +1,22 @@
#include "precedence.hpp"
namespace parser {
precedence precedence_for(token::type type) {
switch (type) {
case token::type::EQ:
case token::type::NEQ:
return precedence::EQUALS;
case token::type::LT:
case token::type::GT:
return precedence::LESS_GREATER;
case token::type::PLUS:
case token::type::MINUS:
return precedence::SUM;
case token::type::ASTERISK:
case token::type::SLASH:
return precedence::PRODUCT;
default:
return precedence::LOWEST;
}
}
} // namespace parser

View File

@@ -1,3 +1,7 @@
#include "token/type.hpp"
#include <ostream>
namespace parser {
enum class precedence {
LOWEST,
@@ -8,4 +12,10 @@ namespace parser {
PREFIX,
CALL
};
}
precedence precedence_for(token::type);
inline std::ostream& operator<<(std::ostream& os, precedence& p) {
return os << static_cast<int>(p);
}
} // namespace parser