[Parser] Start parser
This commit is contained in:
parent
e0a8808c31
commit
70e0dd3e01
1 changed files with 175 additions and 30 deletions
|
|
@ -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<class T>
|
||||
concept token_iterator = requires() {
|
||||
requires std::same_as<decltype(typename T::value_type), jlx::token>;
|
||||
requires std::same_as<typename T::value_type, jlx::token>;
|
||||
std::bidirectional_iterator<T>;
|
||||
};
|
||||
|
||||
|
|
@ -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<std::unique_ptr<statement>> statements) : statement(Root), statements(std::move(statements)) {
|
||||
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<statement>> 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<std::unique_ptr<statement>> statements) : statement(Block), statements(std::move(statements)) {
|
||||
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<statement>> statements;
|
||||
|
||||
~block() override = default;
|
||||
};
|
||||
|
||||
struct function_parameter {
|
||||
|
|
@ -65,12 +90,41 @@ namespace jlx {
|
|||
|
||||
}
|
||||
|
||||
function_declaration(std::string name, std::vector<function_parameter> parameters, std::optional<std::string> return_type, std::unique_ptr<block> 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<function_parameter> parameters;
|
||||
std::optional<std::string> return_type;
|
||||
std::unique_ptr<block> body;
|
||||
|
||||
|
||||
~function_declaration() override = default;
|
||||
};
|
||||
|
||||
struct variable_declaration : public statement {
|
||||
variable_declaration() : statement(VariableDeclaration) {
|
||||
|
||||
}
|
||||
|
||||
bool constant;
|
||||
std::string name;
|
||||
std::optional<std::string> type;
|
||||
std::unique_ptr<expression> initial_expression;
|
||||
|
||||
~variable_declaration() override = default;
|
||||
};
|
||||
|
||||
struct if_statement : public statement {
|
||||
if_statement() : statement(IfStatement) {
|
||||
|
||||
}
|
||||
|
||||
std::unique_ptr<expression> condition;
|
||||
std::unique_ptr<block> block;
|
||||
};
|
||||
|
||||
export template<token_iterator T, std::sentinel_for<T> 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<variable_declaration> parse_variable_declaration() {
|
||||
if (current->type != Keyword) {
|
||||
fail_invalid_token(*current);
|
||||
}
|
||||
|
||||
std::string name;
|
||||
std::optional<std::string> type = std::nullopt;
|
||||
std::unique_ptr<expression> 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<variable_declaration>();
|
||||
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<if_statement> 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<if_statement>();
|
||||
statement->block = std::move(block);
|
||||
statement->condition = std::move(expr);
|
||||
|
||||
return statement;
|
||||
}
|
||||
|
||||
std::unique_ptr<expression> parse_expression() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<function_declaration> 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<statement> parse() {
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<statement>> 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<statement> parse() {
|
||||
|
||||
std::vector<std::unique_ptr<statement>> 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<root_statement>(top_level_statements);
|
||||
top_level_statements.push_back(std::move(s));
|
||||
}
|
||||
|
||||
return std::make_unique<root_statement>(std::move(top_level_statements));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue