Add paren expression
Signed-off-by: CHatingPython <chatingpython@gmail.com>
This commit is contained in:
@@ -11,6 +11,7 @@ enum class expression_node_t {
|
||||
Literal,
|
||||
Unaryop,
|
||||
Binop,
|
||||
Paren,
|
||||
};
|
||||
|
||||
class expression_node : public statement_node {
|
||||
@@ -50,6 +51,8 @@ public:
|
||||
expression_node_t expression_type() const override { return expression_node_t::Unaryop; }
|
||||
|
||||
std::ostream& print(std::ostream& os) const override;
|
||||
protected:
|
||||
bool equal(const node& rhs) const override;
|
||||
private:
|
||||
unaryop_expression_node_t m_type;
|
||||
expression_node_h m_node;
|
||||
@@ -91,6 +94,26 @@ private:
|
||||
|
||||
using binop_expression_node_h = node_handle<binop_expression_node>;
|
||||
|
||||
class paren_expression_node : public expression_node {
|
||||
public:
|
||||
paren_expression_node(expression_node_h&& node)
|
||||
: m_node(std::move(node)) {}
|
||||
|
||||
const expression_node_h& get_node() const { return m_node; }
|
||||
expression_node_h& get_node() { return m_node; }
|
||||
expression_node_h&& move_node() { return std::move(m_node); }
|
||||
public:
|
||||
expression_node_t expression_type() const override { return expression_node_t::Paren; }
|
||||
|
||||
std::ostream& print(std::ostream& os) const override;
|
||||
protected:
|
||||
bool equal(const node& rhs) const override;
|
||||
private:
|
||||
expression_node_h m_node;
|
||||
};
|
||||
|
||||
using paren_expression_node_h = node_handle<paren_expression_node>;
|
||||
|
||||
} // namespace ast
|
||||
} // namespace furc
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ public:
|
||||
private:
|
||||
ast::declaration_node_h parse_declaration();
|
||||
ast::statement_node_h parse_statement();
|
||||
ast::expression_node_h parse_expression();
|
||||
ast::expression_node_h parse_expression(std::uint32_t precedence = 16);
|
||||
ast::literal_node_h parse_literal();
|
||||
|
||||
ast::expression_node_h parse_expression_primary();
|
||||
|
||||
@@ -58,6 +58,11 @@ std::ostream& unaryop_expression_node::print(std::ostream& os) const {
|
||||
return os;
|
||||
}
|
||||
|
||||
bool unaryop_expression_node::equal(const node& rhsNode) const {
|
||||
const auto& rhs = reinterpret_cast<const unaryop_expression_node&>(rhsNode);
|
||||
return expression_node::equal(rhsNode) && m_type == rhs.m_type && m_node == rhs.m_node;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, binop_expression_node_t type) {
|
||||
switch (type) {
|
||||
case binop_expression_node_t::Add: return os << '+';
|
||||
@@ -77,6 +82,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& paren_expression_node::print(std::ostream& os) const {
|
||||
return os << *m_node;
|
||||
}
|
||||
|
||||
bool paren_expression_node::equal(const node& rhsNode) const {
|
||||
const auto& rhs = reinterpret_cast<const paren_expression_node&>(rhsNode);
|
||||
return expression_node::equal(rhsNode) && m_node == rhs.m_node;
|
||||
}
|
||||
|
||||
bool declaration_node::equal(const node& rhs) const {
|
||||
return declaration_type() == reinterpret_cast<const declaration_node&>(rhs).declaration_type();
|
||||
}
|
||||
|
||||
@@ -118,8 +118,8 @@ ast::statement_node_h parser::parse_statement() {
|
||||
return { token.location(), "unexpected token "s + token->type + ", expected statement, declaration or expression" };
|
||||
}
|
||||
|
||||
ast::expression_node_h parser::parse_expression() {
|
||||
return parse_expression_rhs(parse_expression_unary(16), 16);
|
||||
ast::expression_node_h parser::parse_expression(std::uint32_t precedence) {
|
||||
return parse_expression_rhs(parse_expression_unary(precedence), precedence);
|
||||
}
|
||||
|
||||
ast::literal_node_h parser::parse_literal() {
|
||||
@@ -145,10 +145,20 @@ 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::Lparen: {
|
||||
auto tok = next_token();
|
||||
auto node = parse_expression();
|
||||
auto err = eat_token(token_t::Rparen);
|
||||
if (err.has_error()) return err;
|
||||
return ast::paren_expression_node_h{ tok.location(), m_arena, std::move(node) };
|
||||
}
|
||||
default: {
|
||||
auto literal = parse_literal();
|
||||
if (literal.present()) return std::move(literal);
|
||||
return { tok.location(), "unexpected token"s + tok->type + ", expected expression or literal" };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct unaryop_info {
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
#include <iostream>
|
||||
|
||||
int main(void) {
|
||||
furc::front::parser parser("<TEMP>", "func main() {\n return 6 - -7 * 9++;\n}");
|
||||
furc::front::parser parser("<TEMP>", "func main() {\n return (6 - -7) * 9++;\n}");
|
||||
std::cout << parser.parse() << '\n';
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -180,4 +180,33 @@ TEST(Parser, UnaryOperator_PrePost) {
|
||||
EXPECT_INTLIT(dec->get_node(), 5);
|
||||
}
|
||||
|
||||
TEST(Parser, Paren) {
|
||||
parser parser("<TEMP>", "func main() { return --(5++); }");
|
||||
auto program = parser.parse();
|
||||
EXPECT_TRUE(program.present());
|
||||
EXPECT_EQ(program->declarations().size(), 1);
|
||||
auto func = program->declarations()[0];
|
||||
EXPECT_TRUE(func.present());
|
||||
EXPECT_EQ(func->declaration_type(), declaration_node_t::FunctionDefinition);
|
||||
function_definition_node_h funcDef = func;
|
||||
EXPECT_EQ(funcDef->name()->string, "main");
|
||||
EXPECT_EQ(funcDef->body()->statements.size(), 1);
|
||||
return_statement_node_h ret = funcDef->body()->statements[0];
|
||||
|
||||
auto retVal = ret->value();
|
||||
EXPECT_TRUE(retVal.present());
|
||||
|
||||
EXPECT_EQ(retVal->expression_type(), expression_node_t::Unaryop);
|
||||
unaryop_expression_node_h dec = retVal;
|
||||
EXPECT_EQ(dec->type(), unaryop_expression_node_t::PrefixDecrement);
|
||||
|
||||
EXPECT_EQ(dec->get_node()->expression_type(), expression_node_t::Paren);
|
||||
paren_expression_node_h paren = dec->get_node();
|
||||
|
||||
EXPECT_EQ(paren->get_node()->expression_type(), expression_node_t::Unaryop);
|
||||
unaryop_expression_node_h inc = paren->get_node();
|
||||
EXPECT_EQ(inc->type(), unaryop_expression_node_t::PostfixIncrement);
|
||||
EXPECT_INTLIT(inc->get_node(), 5);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
Reference in New Issue
Block a user