diff --git a/libjlx/modules/ast.cppm b/libjlx/modules/ast.cppm index 195c128..585d2b5 100644 --- a/libjlx/modules/ast.cppm +++ b/libjlx/modules/ast.cppm @@ -16,13 +16,21 @@ namespace jlx { Expression, Block, FunctionDeclaration, - SimpleIdentifier, - LiteralValue + VariableDeclaration, + LiteralValue, + IfStatement, + }; + + export enum class literal_value_type { + Boolean, + Numeric, + String, + Character, }; export template concept token_iterator = requires() { - requires std::same_as; + requires std::same_as; std::bidirectional_iterator; }; @@ -32,6 +40,8 @@ namespace jlx { statement(ast_type type) : type(type) { } + + virtual ~statement() = default; }; struct root_statement : public statement { @@ -39,20 +49,35 @@ namespace jlx { } + root_statement(std::vector> statements) : statement(Root), statements(std::move(statements)) { + + } + std::vector> statements; + + ~root_statement() override = default; }; struct expression : public statement { expression() : statement(Expression) { } + + ~expression() override = default; }; struct block : public statement { block() : statement(Block) { } + + block(std::vector> statements) : statement(Block), statements(std::move(statements)) { + + } + std::vector> statements; + + ~block() override = default; }; struct function_parameter { @@ -65,12 +90,41 @@ namespace jlx { } + function_declaration(std::string name, std::vector parameters, std::optional return_type, std::unique_ptr body) : + statement(FunctionDeclaration), name(std::move(name)), parameters(std::move(parameters)), return_type(std::move(return_type)), body(std::move(body)) { + + } + std::string name; std::vector parameters; std::optional return_type; std::unique_ptr body; + + + ~function_declaration() override = default; }; + struct variable_declaration : public statement { + variable_declaration() : statement(VariableDeclaration) { + + } + + bool constant; + std::string name; + std::optional type; + std::unique_ptr initial_expression; + + ~variable_declaration() override = default; + }; + + struct if_statement : public statement { + if_statement() : statement(IfStatement) { + + } + + std::unique_ptr condition; + std::unique_ptr block; + }; export template E> class parser { @@ -99,9 +153,101 @@ namespace jlx { } next(); - while(current->type != Punctuation && current->type != "}") { + while(current->type != Punctuation && current->content != "}") { } + + return nullptr; + } + + std::unique_ptr parse_variable_declaration() { + if (current->type != Keyword) { + fail_invalid_token(*current); + } + + std::string name; + std::optional type = std::nullopt; + std::unique_ptr starting_value = nullptr; + bool constant; + + if (current->content == "let") { + constant = true; + } else if (current->content == "var") { + constant = false; + } else { + fail_invalid_token(*current); + return nullptr; + } + + next(); + + if (current->type != Identifier) { + fail_invalid_token(*current); + } + + name = current->content; + + next(); + + if (current->type == Punctuation && current->content == ":") { + next(); + + if (current->type != Identifier) { + fail_invalid_token(*current); + } + + type = current->content; + + next(); + } + + if (current->type == Operator && current->content == "=") { + next(); + + starting_value = parse_expression(); + } + + auto var = std::make_unique(); + var->constant = constant; + var->name = std::move(name); + var->type = std::move(type); + var->initial_expression = std::move(starting_value); + + return var; + } + + std::unique_ptr parse_if_statement() { + if (current->type != Keyword || current->content != "if") { + fail_invalid_token(*current); + } + + next(); + + if (current->type != Punctuation || current->content != "(") { + fail_invalid_token(*current); + } + + next(); + + auto expr = parse_expression(); + + if (current->type != Punctuation || current->content != ")") { + fail_invalid_token(*current); + } + + next(); + + auto block = parse_block(); + + auto statement = std::make_unique(); + statement->block = std::move(block); + statement->condition = std::move(expr); + + return statement; + } + + std::unique_ptr parse_expression() { + return nullptr; } std::unique_ptr parse_function() { @@ -154,8 +300,8 @@ namespace jlx { next(); - auto param_type = parse_type(current, last); - params.push_back(std::move(name), std::move(param_type)); + auto param_type = parse_type(); + params.emplace_back(std::move(name), std::move(param_type)); next(); first = false; @@ -165,7 +311,7 @@ namespace jlx { if (current->type == Punctuation && current->content == ":") { next(); - return_type = parse_type(current, last); + return_type = parse_type(); next(); } @@ -188,36 +334,35 @@ namespace jlx { } if (current->type == token_type::Keyword) { - switch(current->content) { - case "let": - case "var": - parse_variable_declaration(current, last); - break; - case "if": - parse_if_statement(current, last); - break; - case "fun": - return parse_function(current, last); + if (current->content == "let" || current->content == "var") { + return parse_variable_declaration(); + } else if (current->content == "if") { + return parse_if_statement(); + } else if (current->content == "fun") { + return parse_function(); } } + + return nullptr; } - public: - parser(T current, E last) : current(current), last(last) { - } + public: + parser(T current, E last) : current(current), last(last) { - std::unique_ptr parse() { + } - std::vector> top_level_statements; - while(current != last) { - auto s = parse_top_level_statement(); - if (s == nullptr) { - throw std::runtime_error("No statement parsed..."); - } - top_level_statements.push_back(std::move(s)); + std::unique_ptr parse() { + + std::vector> top_level_statements; + while(current != last) { + auto s = parse_top_level_statement(); + if (s == nullptr) { + throw std::runtime_error("No statement parsed..."); } - - return std::make_unique(top_level_statements); + top_level_statements.push_back(std::move(s)); } + + return std::make_unique(std::move(top_level_statements)); + } }; }