Compare commits
4 Commits
ecdf6944a7
...
7ebc27cab9
| Author | SHA1 | Date | |
|---|---|---|---|
|
7ebc27cab9
|
|||
|
1db13b4e10
|
|||
|
84c6795ff8
|
|||
|
212b1e2384
|
@@ -52,6 +52,9 @@ public:
|
|||||||
Expression,
|
Expression,
|
||||||
|
|
||||||
Compound,
|
Compound,
|
||||||
|
If,
|
||||||
|
While,
|
||||||
|
Return,
|
||||||
};
|
};
|
||||||
public:
|
public:
|
||||||
category_e category() const override { return ast_node_cat::Statement; }
|
category_e category() const override { return ast_node_cat::Statement; }
|
||||||
@@ -65,6 +68,29 @@ struct comp_stmt_node final : public stmt_node {
|
|||||||
std::vector<stmt_node*> stmts;
|
std::vector<stmt_node*> stmts;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class expr_node;
|
||||||
|
|
||||||
|
struct if_stmt_node final : public stmt_node {
|
||||||
|
stmt_type_e stmt_type() const override { return If; }
|
||||||
|
|
||||||
|
expr_node* cond = nullptr;
|
||||||
|
stmt_node* thenBranch = nullptr;
|
||||||
|
stmt_node* elseBranch = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct while_stmt_node final : public stmt_node {
|
||||||
|
stmt_type_e stmt_type() const override { return While; }
|
||||||
|
|
||||||
|
expr_node* cond = nullptr;
|
||||||
|
stmt_node* body = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct return_stmt_node final : public stmt_node {
|
||||||
|
stmt_type_e stmt_type() const override { return Return; }
|
||||||
|
|
||||||
|
expr_node* value = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
class decl_node : public stmt_node {
|
class decl_node : public stmt_node {
|
||||||
public:
|
public:
|
||||||
enum decl_type_e {
|
enum decl_type_e {
|
||||||
@@ -79,8 +105,6 @@ public:
|
|||||||
virtual decl_type_e decl_type() const = 0;
|
virtual decl_type_e decl_type() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class expr_node;
|
|
||||||
|
|
||||||
struct var_decl_node final : public decl_node {
|
struct var_decl_node final : public decl_node {
|
||||||
decl_type_e decl_type() const override { return Variable; }
|
decl_type_e decl_type() const override { return Variable; }
|
||||||
|
|
||||||
@@ -103,6 +127,8 @@ public:
|
|||||||
enum expr_type_e {
|
enum expr_type_e {
|
||||||
Literal,
|
Literal,
|
||||||
|
|
||||||
|
VarRead,
|
||||||
|
Group,
|
||||||
BinaryOp,
|
BinaryOp,
|
||||||
UnaryOp,
|
UnaryOp,
|
||||||
};
|
};
|
||||||
@@ -114,6 +140,21 @@ public:
|
|||||||
virtual expr_type_e expr_type() const = 0;
|
virtual expr_type_e expr_type() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct var_read_expr_node final : public expr_node {
|
||||||
|
expr_type_e expr_type() const override { return VarRead; }
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
var_read_expr_node(std::string&& name)
|
||||||
|
: name(std::move(name)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct group_expr_node final : public expr_node {
|
||||||
|
expr_type_e expr_type() const override { return Group; }
|
||||||
|
|
||||||
|
expr_node* inner = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
struct binary_op_expr_node final : public expr_node {
|
struct binary_op_expr_node final : public expr_node {
|
||||||
enum binary_op_type {
|
enum binary_op_type {
|
||||||
Add = 0,
|
Add = 0,
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ private:
|
|||||||
stmt_node* parse_stmt();
|
stmt_node* parse_stmt();
|
||||||
decl_node* parse_decl();
|
decl_node* parse_decl();
|
||||||
expr_node* parse_expr();
|
expr_node* parse_expr();
|
||||||
lit_node* parse_lit();
|
|
||||||
|
|
||||||
ast_type parse_type();
|
ast_type parse_type();
|
||||||
comp_stmt_node parse_comp();
|
comp_stmt_node parse_comp();
|
||||||
|
|||||||
+50
-14
@@ -24,6 +24,37 @@ ast parser::parse() {
|
|||||||
stmt_node* parser::parse_stmt() {
|
stmt_node* parser::parse_stmt() {
|
||||||
switch (m_lexer.peek_token().type) {
|
switch (m_lexer.peek_token().type) {
|
||||||
case token::LBrace: return m_arena->allocate<comp_stmt_node>(parse_comp());
|
case token::LBrace: return m_arena->allocate<comp_stmt_node>(parse_comp());
|
||||||
|
case token::Return: {
|
||||||
|
m_lexer.next_token();
|
||||||
|
return_stmt_node node;
|
||||||
|
if (m_lexer.peek_token().type != token::Semicolon) {
|
||||||
|
node.value = parse_expr();
|
||||||
|
}
|
||||||
|
eat_token(token::Semicolon);
|
||||||
|
return m_arena->allocate<return_stmt_node>(std::move(node));
|
||||||
|
}
|
||||||
|
case token::If: {
|
||||||
|
m_lexer.next_token();
|
||||||
|
eat_token(token::LParen);
|
||||||
|
if_stmt_node node;
|
||||||
|
node.cond = parse_expr();
|
||||||
|
eat_token(token::RParen);
|
||||||
|
node.thenBranch = parse_stmt();
|
||||||
|
if (m_lexer.peek_token().type == token::Else) {
|
||||||
|
m_lexer.next_token();
|
||||||
|
node.elseBranch = parse_stmt();
|
||||||
|
}
|
||||||
|
return m_arena->allocate<if_stmt_node>(std::move(node));
|
||||||
|
}
|
||||||
|
case token::While: {
|
||||||
|
m_lexer.next_token();
|
||||||
|
eat_token(token::LParen);
|
||||||
|
while_stmt_node node;
|
||||||
|
node.cond = parse_expr();
|
||||||
|
eat_token(token::RParen);
|
||||||
|
node.body = parse_stmt();
|
||||||
|
return m_arena->allocate<while_stmt_node>(std::move(node));
|
||||||
|
}
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,19 +120,6 @@ expr_node* parser::parse_expr() {
|
|||||||
return parse_expr_right(parse_expr_unary());
|
return parse_expr_right(parse_expr_unary());
|
||||||
}
|
}
|
||||||
|
|
||||||
lit_node* parser::parse_lit() {
|
|
||||||
auto token = eat_token(token::Integer, token::Char);
|
|
||||||
switch (token.type) {
|
|
||||||
case token::Integer: {
|
|
||||||
return m_arena->allocate<int_lit_node>(int_lit_node(token.value.integer));
|
|
||||||
}
|
|
||||||
case token::Char: {
|
|
||||||
return m_arena->allocate<char_lit_node>(char_lit_node(token.value.character));
|
|
||||||
}
|
|
||||||
default: throw std::runtime_error("unreachable");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ast_type parser::parse_type() {
|
ast_type parser::parse_type() {
|
||||||
auto token =
|
auto token =
|
||||||
eat_token(token::S8, token::U8, token::S16, token::U16, token::S32, token::U32, token::S64, token::U64);
|
eat_token(token::S8, token::U8, token::S16, token::U16, token::S32, token::U32, token::S64, token::U64);
|
||||||
@@ -131,7 +149,25 @@ comp_stmt_node parser::parse_comp() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
expr_node* parser::parse_expr_primary() {
|
expr_node* parser::parse_expr_primary() {
|
||||||
return parse_lit();
|
auto token = eat_token(token::Identifier, token::LParen, token::Integer, token::Char);
|
||||||
|
switch (token.type) {
|
||||||
|
case token::Identifier: {
|
||||||
|
return m_arena->allocate<var_read_expr_node>(std::string(token.value.string));
|
||||||
|
}
|
||||||
|
case token::LParen: {
|
||||||
|
group_expr_node group;
|
||||||
|
group.inner = parse_expr();
|
||||||
|
eat_token(token::RParen);
|
||||||
|
return m_arena->allocate<group_expr_node>(std::move(group));
|
||||||
|
}
|
||||||
|
case token::Integer: {
|
||||||
|
return m_arena->allocate<int_lit_node>(int_lit_node(token.value.integer));
|
||||||
|
}
|
||||||
|
case token::Char: {
|
||||||
|
return m_arena->allocate<char_lit_node>(char_lit_node(token.value.character));
|
||||||
|
}
|
||||||
|
default: throw std::runtime_error("unreachable");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
expr_node* parser::parse_expr_unary() {
|
expr_node* parser::parse_expr_unary() {
|
||||||
|
|||||||
+9
-1
@@ -5,7 +5,15 @@
|
|||||||
int main(void) {
|
int main(void) {
|
||||||
furlang::arena arena;
|
furlang::arena arena;
|
||||||
|
|
||||||
furc::lexer lexer = { "<AK>", "func main(argc: u64) -> s32 { x: s32 = 10 + 67 - 6 * 7; }" };
|
std::string_view content = R"(
|
||||||
|
func main(argc: u64) -> s32 {
|
||||||
|
x: s32 = 1 + 2 * 3;
|
||||||
|
if (x == 9) return 1;
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
furc::lexer lexer = { "<AK>", content };
|
||||||
furc::parser parser = { std::move(lexer), arena };
|
furc::parser parser = { std::move(lexer), arena };
|
||||||
|
|
||||||
auto program = parser.parse();
|
auto program = parser.parse();
|
||||||
|
|||||||
Reference in New Issue
Block a user