Skip to content

Commit 29876a0

Browse files
authored
feat: add support for until keyword (#122)
* feat * add tests for until
1 parent 9fcd493 commit 29876a0

File tree

11 files changed

+70
-6
lines changed

11 files changed

+70
-6
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ Scarlet currently supports the following architectures:
8686
- [x] Add support for compound operators (+=,-=,*=,/=,<<=,>>=,%=)
8787
- [x] Add support for goto statement
8888
- [x] Add support for compound statements
89-
- [x] Add support for Loops (for, while, do-while)
89+
- [x] Add support for Loops (for, while, do-while, until, do-until)
9090
- [x] Add support for switch-case
9191
- [x] Add support for Functions
9292
- [x] Add support for static keyword and global scope

expected_results.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

lexer/lexer.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,8 @@ void lexer::tokenize() {
319319
tokens.emplace_back(token::TOKEN::DO);
320320
} else if (identifier == "while") {
321321
tokens.emplace_back(token::TOKEN::WHILE);
322+
} else if (identifier == "until") {
323+
tokens.emplace_back(token::TOKEN::UNTIL);
322324
} else if (identifier == "for") {
323325
tokens.emplace_back(token::TOKEN::FOR);
324326
} else if (identifier == "break") {

parser/parse_statement.cc

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,16 +90,35 @@ void parser::parse_statement(
9090
block_stmt->set_type(ast::statementType::BLOCK);
9191
block_stmt->set_block(std::move(block_node));
9292
statement = std::static_pointer_cast<ast::AST_Statement_Node>(block_stmt);
93-
} else if (tokens[0].get_token() == token::TOKEN::WHILE) {
93+
} else if (tokens[0].get_token() == token::TOKEN::WHILE or
94+
tokens[0].get_token() == token::TOKEN::UNTIL) {
9495
MAKE_SHARED(ast::AST_while_statement_Node, while_statement);
96+
bool is_until = false;
97+
if (tokens[0].get_token() == token::TOKEN::UNTIL)
98+
is_until = true;
9599
while_statement->set_type(ast::statementType::WHILE);
96100
tokens.erase(tokens.begin());
97101
while_statement->set_labels(get_loop_labels());
98102

99103
EXPECT(token::TOKEN::OPEN_PARANTHESES);
100104
MAKE_SHARED(ast::AST_exp_Node, exp);
101105
parse_exp(tokens, exp);
102-
while_statement->set_exp(std::move(exp));
106+
if (is_until) {
107+
MAKE_SHARED(ast::AST_exp_Node, not_exp);
108+
MAKE_SHARED(ast::AST_factor_Node, not_factor);
109+
MAKE_SHARED(ast::AST_unop_Node, not_op);
110+
MAKE_SHARED(ast::AST_factor_Node, child_factor);
111+
112+
child_factor->set_exp_node(std::move(exp));
113+
not_op->set_op(unop::UNOP::NOT);
114+
not_factor->set_unop_node(std::move(not_op));
115+
not_factor->set_child(std::move(child_factor));
116+
not_exp->set_factor_node(std::move(not_factor));
117+
118+
while_statement->set_exp(std::move(not_exp));
119+
} else {
120+
while_statement->set_exp(std::move(exp));
121+
}
103122

104123
EXPECT(token::TOKEN::CLOSE_PARANTHESES);
105124

@@ -220,11 +239,32 @@ void parser::parse_statement(
220239
parse_statement(tokens, stmt);
221240
while_statement->set_stmt(std::move(stmt));
222241

223-
EXPECT(token::TOKEN::WHILE);
242+
bool is_until = false;
243+
if (tokens[0].get_token() == token::TOKEN::UNTIL) {
244+
is_until = true;
245+
tokens.erase(tokens.begin());
246+
} else {
247+
EXPECT(token::TOKEN::WHILE);
248+
}
224249
EXPECT(token::TOKEN::OPEN_PARANTHESES);
225250
MAKE_SHARED(ast::AST_exp_Node, exp);
226251
parse_exp(tokens, exp);
227-
while_statement->set_exp(std::move(exp));
252+
if (is_until) {
253+
MAKE_SHARED(ast::AST_exp_Node, not_exp);
254+
MAKE_SHARED(ast::AST_factor_Node, not_factor);
255+
MAKE_SHARED(ast::AST_unop_Node, not_op);
256+
MAKE_SHARED(ast::AST_factor_Node, child_factor);
257+
258+
child_factor->set_exp_node(std::move(exp));
259+
not_op->set_op(unop::UNOP::NOT);
260+
not_factor->set_unop_node(std::move(not_op));
261+
not_factor->set_child(std::move(child_factor));
262+
not_exp->set_factor_node(std::move(not_factor));
263+
264+
while_statement->set_exp(std::move(not_exp));
265+
} else
266+
while_statement->set_exp(std::move(exp));
267+
228268
EXPECT(token::TOKEN::CLOSE_PARANTHESES);
229269
EXPECT(token::TOKEN::SEMICOLON);
230270

0 Bytes
Binary file not shown.
Binary file not shown.
-171 Bytes
Binary file not shown.

tests/chapter_8/valid/do_until.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
int main(void) {
2+
int a = 1;
3+
do {
4+
a = a * 2;
5+
}
6+
until(a >= 11);
7+
8+
return a;
9+
}

tests/chapter_8/valid/until.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
int main(void) {
2+
int count = 0;
3+
4+
until(count >= 5) { count = count + 1; }
5+
6+
return count;
7+
}

token/token.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ void print_token(TOKEN token) {
5050
case TOKEN::WHILE:
5151
std::cerr << "while ";
5252
break;
53+
case TOKEN::UNTIL:
54+
std::cerr << "until ";
55+
break;
5356
case TOKEN::FOR:
5457
std::cerr << "for ";
5558
break;
@@ -289,6 +292,8 @@ std::string to_string(TOKEN token) {
289292
return "do";
290293
case TOKEN::WHILE:
291294
return "while";
295+
case TOKEN::UNTIL:
296+
return "until";
292297
case TOKEN::FOR:
293298
return "for";
294299
case TOKEN::BREAK:

token/token.hh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ enum class TOKEN {
2929
ELSE,
3030
DO,
3131
WHILE,
32+
UNTIL,
3233
FOR,
3334
BREAK,
3435
CONTINUE,

0 commit comments

Comments
 (0)