diff --git a/furc/include/furc/ast/expression.hpp b/furc/include/furc/ast/expression.hpp index 1e6f0eb..58612ba 100644 --- a/furc/include/furc/ast/expression.hpp +++ b/furc/include/furc/ast/expression.hpp @@ -9,6 +9,7 @@ namespace ast { enum class expression_node_t { Literal, + VarRead, Unaryop, Binop, Paren, @@ -27,6 +28,25 @@ protected: using expression_node_h = node_handle; +class var_read_expression_node : public expression_node { +public: + var_read_expression_node(handle&& name) + : m_name(std::move(name)) {} + + const handle& get_name() const { return m_name; } + handle&& move_name() { return std::move(m_name); } +public: + expression_node_t expression_type() const override { return expression_node_t::VarRead; } + + std::ostream& print(std::ostream& os) const override; +protected: + bool equal(const node& rhs) const override; +private: + handle m_name; +}; + +using var_read_expression_node_h = node_handle; + enum class unaryop_expression_node_t { Positive, Negative, diff --git a/furc/src/ast.cpp b/furc/src/ast.cpp index 3496546..41e65e4 100644 --- a/furc/src/ast.cpp +++ b/furc/src/ast.cpp @@ -34,6 +34,16 @@ bool expression_node::equal(const node& rhs) const { return expression_type() == reinterpret_cast(rhs).expression_type(); } +std::ostream& var_read_expression_node::print(std::ostream& os) const { + if (m_name.present()) return os << *m_name; + return os << m_name.error(); +} + +bool var_read_expression_node::equal(const node& rhsNode) const { + const auto& rhs = reinterpret_cast(rhsNode); + return expression_node::equal(rhsNode) && m_name == rhs.m_name; +} + std::ostream& operator<<(std::ostream& os, unaryop_expression_node_t type) { switch (type) { case unaryop_expression_node_t::Positive: return os << "+"; diff --git a/furc/src/front/parser.cpp b/furc/src/front/parser.cpp index 02a5c94..e795818 100644 --- a/furc/src/front/parser.cpp +++ b/furc/src/front/parser.cpp @@ -146,6 +146,12 @@ ast::literal_node_h parser::parse_literal() { ast::expression_node_h parser::parse_expression_primary() { const auto& tok = peek_token(); switch (tok->type) { + case token_t::Identifier: { + auto tok = next_token(); + return ast::var_read_expression_node_h{ tok.location(), + m_arena, + handle{ tok.location(), (*tok)->string } }; + } case token_t::Lparen: { auto tok = next_token(); auto node = parse_expression(); diff --git a/furc/src/main.cpp b/furc/src/main.cpp index 9fa2732..7228623 100644 --- a/furc/src/main.cpp +++ b/furc/src/main.cpp @@ -5,7 +5,7 @@ #include int main(void) { - furc::front::parser parser("", "func main() {\n return (6 - -7) * 9++;\n}"); + furc::front::parser parser("", "func main() {\n return (x - -y) * z++;\n}"); std::cout << parser.parse() << '\n'; return 0; diff --git a/furc/test/parser.cpp b/furc/test/parser.cpp index 358170d..1c93ea6 100644 --- a/furc/test/parser.cpp +++ b/furc/test/parser.cpp @@ -64,7 +64,14 @@ TEST(Parser, Literals) { EXPECT_EQ(literal->literal_type(), literal_node_t::Integer); \ integer_literal_node_h intLit = literal; \ EXPECT_EQ(*intLit, (integer)); \ - } while (0); + } while (0) + +#define EXPECT_VARREAD(expr, varname) \ + do { \ + EXPECT_EQ((expr)->expression_type(), expression_node_t::VarRead); \ + var_read_expression_node_h varRead = (expr); \ + EXPECT_EQ(varRead->get_name(), (varname)); \ + } while (0) // TODO: Use arena (I am too exhausted rn to do it) TEST(Parser, OperatorPrecedence_AddMul) { @@ -181,7 +188,7 @@ TEST(Parser, UnaryOperator_PrePost) { } TEST(Parser, Paren) { - parser parser("", "func main() { return --(5++); }"); + parser parser("", "func main() { return --(x++); }"); auto program = parser.parse(); EXPECT_TRUE(program.present()); EXPECT_EQ(program->declarations().size(), 1); @@ -203,7 +210,7 @@ TEST(Parser, Paren) { EXPECT_EQ(dec->get_node()->expression_type(), expression_node_t::Unaryop); unaryop_expression_node_h inc = dec->get_node(); EXPECT_EQ(inc->type(), unaryop_expression_node_t::PostfixIncrement); - EXPECT_INTLIT(inc->get_node(), 5); + EXPECT_VARREAD(inc->get_node(), "x"); } } // namespace \ No newline at end of file