Add var assign expression

Signed-off-by: CHatingPython <chatingpython@gmail.com>
This commit is contained in:
CHatingPython
2026-05-30 12:50:44 +02:00
committed by CHatingPython
parent 8d162f926a
commit f4efb53531
6 changed files with 162 additions and 28 deletions
+12
View File
@@ -75,6 +75,8 @@ bool unaryop_expression_node::equal(const node& rhsNode) const {
std::ostream& operator<<(std::ostream& os, binop_expression_node_t type) {
switch (type) {
default:
case binop_expression_node_t::None: return os;
case binop_expression_node_t::Add: return os << '+';
case binop_expression_node_t::Sub: return os << '-';
case binop_expression_node_t::Mul: return os << '*';
@@ -84,6 +86,7 @@ std::ostream& operator<<(std::ostream& os, binop_expression_node_t type) {
}
std::ostream& binop_expression_node::print(std::ostream& os) const {
if (m_type == binop_expression_node_t::None) return os;
return os << '(' << *m_lhs << ' ' << m_type << ' ' << *m_rhs << ')';
}
@@ -92,6 +95,15 @@ bool binop_expression_node::equal(const node& rhsNode) const {
return expression_node::equal(rhsNode) && m_type == rhs.m_type && m_lhs == rhs.m_lhs && m_rhs == rhs.m_rhs;
}
std::ostream& var_assign_expression_node::print(std::ostream& os) const {
return os << *m_lhs << " = " << *m_rhs;
}
bool var_assign_expression_node::equal(const node& rhsNode) const {
const auto& rhs = reinterpret_cast<const var_assign_expression_node&>(rhsNode);
return expression_node::equal(rhsNode) && m_compound == rhs.m_compound && m_lhs == rhs.m_lhs && m_rhs == rhs.m_rhs;
}
bool declaration_node::equal(const node& rhs) const {
return declaration_type() == reinterpret_cast<const declaration_node&>(rhs).declaration_type();
}
+6
View File
@@ -121,6 +121,12 @@ token_handle<> lexer::next_token() {
{ "%", token_t::Percent },
{ "++", token_t::DPlus },
{ "--", token_t::DMinus },
{ "=", token_t::Eq },
{ "+=", token_t::PlusEq },
{ "-=", token_t::MinusEq },
{ "*=", token_t::StarEq },
{ "/=", token_t::SlashEq },
{ "%=", token_t::PercentEq },
};
token_t type = token_t::None;
+39 -10
View File
@@ -212,6 +212,7 @@ enum class associativity {
enum class rhsop_info_t {
Unaryop,
Binop,
Assignment,
};
struct rhsop_info {
@@ -221,6 +222,7 @@ struct rhsop_info {
union {
ast::unaryop_expression_node_t unary;
ast::binop_expression_node_t binary;
ast::binop_expression_node_t assignment;
};
static rhsop_info create(ast::unaryop_expression_node_t type, std::uint32_t precedence) {
@@ -242,6 +244,15 @@ struct rhsop_info {
info.binary = type;
return info;
}
static rhsop_info create(ast::binop_expression_node_t compound = ast::binop_expression_node_t::None) {
rhsop_info info{};
info.type = rhsop_info_t::Assignment;
info.precedence = 14;
info.associativity = associativity::Right;
info.assignment = compound;
return info;
}
};
ast::expression_node_h parser::parse_expression_rhs(ast::expression_node_h&& init, std::uint32_t precedence) {
@@ -253,6 +264,13 @@ ast::expression_node_h parser::parse_expression_rhs(ast::expression_node_h&& ini
{ token_t::Percent, rhsop_info::create(ast::binop_expression_node_t::Mod, 5, associativity::Left) },
{ token_t::DPlus, rhsop_info::create(ast::unaryop_expression_node_t::PostfixIncrement, 1) },
{ token_t::DMinus, rhsop_info::create(ast::unaryop_expression_node_t::PostfixDecrement, 1) },
{ token_t::DMinus, rhsop_info::create(ast::unaryop_expression_node_t::PostfixDecrement, 1) },
{ token_t::Eq, rhsop_info::create() },
{ token_t::PlusEq, rhsop_info::create(ast::binop_expression_node_t::Add) },
{ token_t::MinusEq, rhsop_info::create(ast::binop_expression_node_t::Sub) },
{ token_t::StarEq, rhsop_info::create(ast::binop_expression_node_t::Mul) },
{ token_t::SlashEq, rhsop_info::create(ast::binop_expression_node_t::Div) },
{ token_t::PercentEq, rhsop_info::create(ast::binop_expression_node_t::Mod) },
};
ast::expression_node_h lhs = std::move(init);
@@ -265,7 +283,7 @@ ast::expression_node_h parser::parse_expression_rhs(ast::expression_node_h&& ini
auto opToken = next_token();
ast::expression_node_h rhs;
if (current.type == rhsop_info_t::Binop) {
if (current.type != rhsop_info_t::Unaryop) {
rhs = parse_expression_unary(current.precedence + 1); // unary prefix is always right-associative
}
@@ -273,7 +291,7 @@ ast::expression_node_h parser::parse_expression_rhs(ast::expression_node_h&& ini
if (nextIt != s_rhsops.end()) {
rhsop_info next = nextIt->second;
if (current.type == rhsop_info_t::Binop) {
if (current.type != rhsop_info_t::Unaryop) {
rhs = std::move(parse_expression_rhs(std::move(rhs),
current.precedence + static_cast<std::uint32_t>(current.associativity == associativity::Right)));
} else {
@@ -281,14 +299,25 @@ ast::expression_node_h parser::parse_expression_rhs(ast::expression_node_h&& ini
}
}
lhs = current.type == rhsop_info_t::Binop
? ast::expression_node_h(ast::binop_expression_node_h{ opToken.location(),
m_arena,
current.binary,
std::move(lhs),
std::move(rhs) })
: ast::expression_node_h(
ast::unaryop_expression_node_h{ opToken.location(), m_arena, current.unary, std::move(lhs) });
switch (current.type) {
case rhsop_info_t::Unaryop:
lhs = ast::unaryop_expression_node_h{ opToken.location(), m_arena, current.unary, std::move(lhs) };
break;
case rhsop_info_t::Binop:
lhs = ast::binop_expression_node_h{ opToken.location(),
m_arena,
current.binary,
std::move(lhs),
std::move(rhs) };
break;
case rhsop_info_t::Assignment:
lhs = ast::var_assign_expression_node_h{ opToken.location(),
m_arena,
current.assignment,
std::move(lhs),
std::move(rhs) };
break;
}
}
return lhs;
}