Skip to content

Commit 7f02f0e

Browse files
committed
[#57] Added parsing for structs with cases
1 parent c514daf commit 7f02f0e

File tree

7 files changed

+75
-18
lines changed

7 files changed

+75
-18
lines changed

src/ast.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -948,14 +948,20 @@ void ast::print(Node* node, PrintContext context) {
948948
case TypeDef: {
949949
auto& type = std::get<TypeNode>(*node);
950950

951-
put_indent_level(context.indent_level, append(context.last, type.fields.size() == 0));
951+
put_indent_level(context.indent_level, append(context.last, type.fields.size() == 0 && type.cases.size() == 0));
952952
std::cout << "type " << type.identifier->value << '\n';
953953

954954
for (size_t i = 0; i < type.fields.size(); i++) {
955-
bool is_last = i == type.fields.size() - 1;
955+
bool is_last = i == type.fields.size() - 1 && type.cases.size() == 0;
956956
print((Node*) type.fields[i], PrintContext{context.indent_level + 1, append(context.last, is_last), context.concrete, context.type_bindings});
957957
}
958958

959+
for (size_t i = 0; i < type.cases.size(); i++) {
960+
bool is_last = i == type.cases.size() - 1;
961+
put_indent_level(context.indent_level + 1, append(context.last, is_last));
962+
std::cout << "case " << type.cases[i]->identifier->value << '\n';
963+
}
964+
959965
break;
960966
}
961967

src/ast.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ namespace ast {
338338

339339
IdentifierNode* identifier;
340340
std::vector<IdentifierNode*> fields;
341+
std::vector<TypeNode*> cases;
341342
std::filesystem::path module_path; // Used in to tell from which module the type comes from
342343

343344
size_t get_index_of_field(std::string field_name);

src/lexer.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ Result<token::Token, Error> lexer::get_identifier(Source& source) {
332332
if (literal == "interface") return token::Token(token::Interface, "interface", line, column);
333333
if (literal == "builtin") return token::Token(token::Builtin, "builtin", line, column);
334334
if (literal == "type") return token::Token(token::Type, "type", line, column);
335+
if (literal == "case") return token::Token(token::Case, "case", line, column);
335336
if (literal == "be") return token::Token(token::Be, "be", line, column);
336337
if (literal == "true") return token::Token(token::True, "true", line, column);
337338
if (literal == "false") return token::Token(token::False, "false", line, column);

src/parser.cpp

Lines changed: 49 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ struct Parser {
3131
Result<ast::Node*, Error> parse_extern();
3232
Result<ast::Node*, Error> parse_link_with();
3333
Result<ast::Node*, Error> parse_type_definition();
34+
Result<Ok, Error> parse_type_definition_body(ast::TypeNode* node);
3435
Result<ast::Type, Error> parse_type();
3536
Result<ast::Node*, Error> parse_interface();
3637
Result<ast::Node*, Error> parse_statement();
@@ -870,13 +871,26 @@ Result<ast::Node*, Error> Parser::parse_type_definition() {
870871
if (identifier.is_error()) return identifier;
871872
type.identifier = (ast::IdentifierNode*) identifier.get_value();
872873

874+
// Parse body
875+
auto body = this->parse_type_definition_body(&type);
876+
if (body.is_error()) return body.get_error();
877+
878+
// return
879+
this->ast.push_back(type);
880+
return this->ast.last_element();
881+
}
882+
883+
// type_definition_body → (("\n"+ IDENTIFIER ": " type)|(CASE IDENTIFIER type_defintion_body))*
884+
Result<Ok, Error> Parser::parse_type_definition_body(ast::TypeNode* node) {
873885
// Set new indentation level
886+
size_t backup = this->position;
874887
this->advance_until_next_statement();
875888
size_t previous = this->current_indentation();
876889
this->indentation_level.push_back(this->current().column);
877890
if (previous >= this->current_indentation()) {
878-
this->errors.push_back(errors::expecting_new_indentation_level(this->location())); // tested in errors/expecting_new_indentation_level.dm
879-
return Error {};
891+
this->indentation_level.pop_back();
892+
this->position = backup;
893+
return Ok{};
880894
}
881895

882896
while (!this->at_end()) {
@@ -895,28 +909,47 @@ Result<ast::Node*, Error> Parser::parse_type_definition() {
895909
return Error {};
896910
}
897911

898-
// Parse field
899-
auto field = this->parse_identifier();
900-
if (field.is_error()) return Error {};
912+
if (this->current() == token::Identifier) {
913+
// Parse field
914+
auto field = this->parse_identifier();
915+
if (field.is_error()) return Error {};
901916

902-
// Parse colon
903-
auto colon = this->parse_token(token::Colon);
904-
if (colon.is_error()) return Error {};
917+
// Parse colon
918+
auto colon = this->parse_token(token::Colon);
919+
if (colon.is_error()) return Error {};
905920

906-
auto type_annotation = this->parse_type();
907-
if (type_annotation.is_error()) return Error {};
921+
auto type_annotation = this->parse_type();
922+
if (type_annotation.is_error()) return Error {};
908923

909-
ast::set_type(field.get_value(), type_annotation.get_value());
910-
911-
this->ast.push_back(*field.get_value());
912-
type.fields.push_back((ast::IdentifierNode*) this->ast.last_element());
924+
ast::set_type(field.get_value(), type_annotation.get_value());
925+
node->fields.push_back((ast::IdentifierNode*) field.get_value());
926+
}
927+
else if (this->current() == token::Case) {
928+
// Parse keyword
929+
auto keyword = this->parse_token(token::Case);
930+
if (keyword.is_error()) return Error {};
931+
932+
// Parse identifier
933+
auto identifier = this->parse_identifier();
934+
if (identifier.is_error()) return Error {};
935+
936+
// Parse body
937+
ast::TypeNode new_case = ast::TypeNode{this->location().line, this->location().column};
938+
this->ast.push_back(new_case);
939+
node->cases.push_back((ast::TypeNode*) this->ast.last_element());
940+
node->cases[node->cases.size() - 1]->identifier = (ast::IdentifierNode*) identifier.get_value();
941+
auto body = this->parse_type_definition_body(node->cases[node->cases.size() - 1]);
942+
if (body.is_error()) return body.get_error();
943+
}
944+
else {
945+
assert(false);
946+
}
913947
}
914948

915949
// Pop indentation level
916950
this->indentation_level.pop_back();
917951

918-
this->ast.push_back(type);
919-
return this->ast.last_element();
952+
return Ok{};
920953
}
921954

922955
// type → IDENTIFIER ("[" type (", " type)* "]")*

src/tokens.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,10 @@ void token::print(std::vector<Token> token) {
162162
std::cout << "token::Type";
163163
break;
164164
}
165+
case Case: {
166+
std::cout << "token::Case";
167+
break;
168+
}
165169
case True: {
166170
std::cout << "token::True";
167171
break;

src/tokens.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ namespace token {
4646
Interface,
4747
Builtin,
4848
Type,
49+
Case,
4950
True,
5051
False,
5152
Or,
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
type Weekday
2+
case Monday
3+
case Tuesday
4+
case Wednesday
5+
case Thursday
6+
case Friday
7+
case Saturday
8+
case Sunday
9+
10+
--day = Weekday::Monday
11+
print(day)

0 commit comments

Comments
 (0)