1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 09:58:11 +00:00

Shell: Add support for enumerating lists in for loops

With some odd syntax to boot:
```sh
$ for index i x in $whatever {}
```
This commit is contained in:
AnotherTest 2021-03-05 18:25:09 +03:30 committed by Andreas Kling
parent a45b2ea6fb
commit 13b65b632a
8 changed files with 133 additions and 23 deletions

View file

@ -592,16 +592,46 @@ RefPtr<AST::Node> Parser::parse_for_loop()
return nullptr;
}
auto variable_name = consume_while(is_word_character);
Optional<AST::Position> in_start_position;
if (variable_name.is_empty()) {
variable_name = "it";
} else {
Optional<AST::NameWithPosition> index_variable_name, variable_name;
Optional<AST::Position> in_start_position, index_start_position;
auto offset_before_index = current_position();
if (expect("index")) {
auto offset = current_position();
if (!consume_while(is_whitespace).is_empty()) {
auto offset_before_variable = current_position();
auto variable = consume_while(is_word_character);
if (!variable.is_empty()) {
index_start_position = AST::Position { offset_before_index.offset, offset.offset, offset_before_index.line, offset.line };
auto offset_after_variable = current_position();
index_variable_name = AST::NameWithPosition {
variable,
{ offset_before_variable.offset, offset_after_variable.offset, offset_before_variable.line, offset_after_variable.line },
};
consume_while(is_whitespace);
} else {
restore_to(offset_before_index.offset, offset_before_index.line);
}
} else {
restore_to(offset_before_index.offset, offset_before_index.line);
}
}
auto variable_name_start_offset = current_position();
auto name = consume_while(is_word_character);
auto variable_name_end_offset = current_position();
if (!name.is_empty()) {
variable_name = AST::NameWithPosition {
name,
{ variable_name_start_offset.offset, variable_name_end_offset.offset, variable_name_start_offset.line, variable_name_end_offset.line }
};
consume_while(is_whitespace);
auto in_error_start = push_start();
if (!expect("in")) {
auto syntax_error = create<AST::SyntaxError>("Expected 'in' after a variable name in a 'for' loop", true);
return create<AST::ForLoop>(move(variable_name), move(syntax_error), nullptr); // ForLoop Var Iterated Block
return create<AST::ForLoop>(move(variable_name), move(index_variable_name), move(syntax_error), nullptr); // ForLoop Var Iterated Block
}
in_start_position = AST::Position { in_error_start->offset, m_offset, in_error_start->line, line() };
}
@ -620,7 +650,7 @@ RefPtr<AST::Node> Parser::parse_for_loop()
auto obrace_error_start = push_start();
if (!expect('{')) {
auto syntax_error = create<AST::SyntaxError>("Expected an open brace '{' to start a 'for' loop body", true);
return create<AST::ForLoop>(move(variable_name), move(iterated_expression), move(syntax_error), move(in_start_position)); // ForLoop Var Iterated Block
return create<AST::ForLoop>(move(variable_name), move(index_variable_name), move(iterated_expression), move(syntax_error), move(in_start_position), move(index_start_position)); // ForLoop Var Iterated Block
}
}
@ -639,7 +669,7 @@ RefPtr<AST::Node> Parser::parse_for_loop()
}
}
return create<AST::ForLoop>(move(variable_name), move(iterated_expression), move(body), move(in_start_position)); // ForLoop Var Iterated Block
return create<AST::ForLoop>(move(variable_name), move(index_variable_name), move(iterated_expression), move(body), move(in_start_position), move(index_start_position)); // ForLoop Var Iterated Block
}
RefPtr<AST::Node> Parser::parse_loop_loop()
@ -657,7 +687,7 @@ RefPtr<AST::Node> Parser::parse_loop_loop()
auto obrace_error_start = push_start();
if (!expect('{')) {
auto syntax_error = create<AST::SyntaxError>("Expected an open brace '{' to start a 'loop' loop body", true);
return create<AST::ForLoop>(String::empty(), nullptr, move(syntax_error), Optional<AST::Position> {}); // ForLoop null null Block
return create<AST::ForLoop>(AST::NameWithPosition {}, AST::NameWithPosition {}, nullptr, move(syntax_error)); // ForLoop null null Block
}
}
@ -676,7 +706,7 @@ RefPtr<AST::Node> Parser::parse_loop_loop()
}
}
return create<AST::ForLoop>(String::empty(), nullptr, move(body), Optional<AST::Position> {}); // ForLoop null null Block
return create<AST::ForLoop>(AST::NameWithPosition {}, AST::NameWithPosition {}, nullptr, move(body)); // ForLoop null null Block
}
RefPtr<AST::Node> Parser::parse_if_expr()