Skip to content

Commit 82e0b34

Browse files
author
Heitor Danilo
committed
refactor: organization folders
1 parent 7e95f33 commit 82e0b34

File tree

3 files changed

+249
-0
lines changed

3 files changed

+249
-0
lines changed

src/parser/error_operations.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#include <stdlib.h>
2+
#include <stdio.h>
3+
#include <string.h>
4+
5+
#include <parser/lib.h>
6+
7+
/**
8+
* This function generates an error message and adds it to the parser's error list.
9+
* The template string should contain placeholders for line, column, and literal in that order.
10+
* Memory allocated for the error message is automatically freed.
11+
* Example: `__PARSER_push_error(parser, "Error at line %d, column %d. Found: %s.");`
12+
*
13+
* @param self - The Parser object.
14+
* @param template - The template string for the error message.
15+
*/
16+
void __PARSE_push_error(struct Parser *self, char *template) {
17+
int error_lenght = snprintf(NULL, 0, template, self->curr_token->line, self->curr_token->column, self->curr_token->literal);
18+
char *error = malloc(error_lenght + 1);
19+
sprintf(error, template, self->curr_token->line, self->curr_token->column, self->curr_token->literal);
20+
21+
struct Parser_error *error_node = malloc(sizeof(struct Parser_error));
22+
error_node->error = strdup(error);
23+
error_node->next = self->errors;
24+
self->errors = error_node;
25+
26+
free(error);
27+
}
28+
29+
void __PARSE_print_error(struct Parser *self) {
30+
struct Parser_error *current = self->errors;
31+
32+
while (current != NULL) {
33+
printf("Error: %s\n", current->error);
34+
current = current->next;
35+
}
36+
}

src/parser/parse_operations.c

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
#include <stdlib.h>
2+
3+
#include <ast/lib.h>
4+
#include <parser/lib.h>
5+
6+
7+
struct Statement* __PARSER_parse_expression_statement(struct Parser* self) {
8+
struct Statement* expression_statement = (struct Statement*)malloc(sizeof(struct Statement));
9+
10+
expression_statement->type = 100;
11+
expression_statement->token = self->curr_token;
12+
expression_statement->mut = 0;
13+
expression_statement->to_string = __AST_expression_statement_to_string;
14+
expression_statement->identifier = NULL;
15+
16+
// expression_statement->expression = (struct Expression*)malloc(sizeof(struct Expression));
17+
18+
if (self->next_token_is(self, SEMICOLON)) {
19+
self->consume_token(self);
20+
}
21+
22+
return expression_statement;
23+
}
24+
25+
/**
26+
* Parses a variable declaration statement from the current and following tokens.
27+
*
28+
* This function creates a new variable statement and fills its properties based on
29+
* the current and following tokens. Errors are pushed to the parser's error list if
30+
* the expected tokens are not found. It keeps consuming tokens until a semicolon is found.
31+
*
32+
* @param self The parser object.
33+
*
34+
* @return The parsed variable statement, or NULL if an error occurs.
35+
*/
36+
struct Statement* __PARSER_parse_var_statement(struct Parser* self) {
37+
struct Statement* var_statement = (struct Statement*)malloc(sizeof(struct Statement));
38+
39+
var_statement->type = VARIABLE;
40+
var_statement->token = self->curr_token;
41+
var_statement->mut = 0;
42+
var_statement->to_string = __AST_var_statement_to_string;
43+
44+
if (self->consume_or_ignore_if_next_token_is(self, MUTABLE)) {
45+
var_statement->mut = 1;
46+
}
47+
48+
if (!self->consume_or_ignore_if_next_token_is(self, IDENT)) {
49+
__PARSE_push_error(self, "After \"var\" or \"mut\" keyword, the name of the variable is expected. Line %d, column %d, found: %s.");
50+
return NULL;
51+
}
52+
53+
var_statement->identifier = (struct Identifier*)malloc(sizeof(struct Identifier));
54+
var_statement->identifier->token = self->curr_token;
55+
var_statement->identifier->value = self->curr_token->literal;
56+
57+
if (!self->consume_or_ignore_if_next_token_is(self, ASSIGN)) {
58+
__PARSE_push_error(self, "After variable name, \"=\" is expected. Line %d, column %d, found: %s.");
59+
return NULL;
60+
}
61+
62+
while (!self->curr_token_is(self, SEMICOLON)) {
63+
self->consume_token(self);
64+
}
65+
66+
return var_statement;
67+
}
68+
69+
/**
70+
* Parses a return statement from the current and following tokens.
71+
*
72+
* This function creates a new return statement and fills its properties based on
73+
* the current state of the parser. It keeps consuming tokens until a semicolon is found.
74+
*
75+
* @param self The parser object.
76+
*
77+
* @return The parsed return statement.
78+
*/
79+
struct Statement* __PARSER_parse_return_statement(struct Parser* self) {
80+
struct Statement* return_statement = (struct Statement*)malloc(sizeof(struct Statement));
81+
82+
return_statement->type = RETURN;
83+
return_statement->identifier = NULL;
84+
return_statement->token = self->curr_token;
85+
return_statement->mut = 0;
86+
return_statement->to_string = __AST_return_statement_to_string;
87+
88+
self->consume_token(self);
89+
90+
while (!self->curr_token_is(self, SEMICOLON)) {
91+
self->consume_token(self);
92+
}
93+
94+
return return_statement;
95+
}
96+
97+
/**
98+
* Parses a statement based on the type of the current token.
99+
*
100+
* If the current token represents a variable declaration, it calls the function to
101+
* parse variable declarations. If it's a return statement, it calls the function to
102+
* parse return statements. Otherwise, it assumes the statement is an expression
103+
* statement and calls the function to parse expression statements.
104+
*
105+
* @param self The parser object.
106+
*
107+
* @return The parsed statement.
108+
*/
109+
struct Statement* __PARSER_parse_statement(struct Parser* self) {
110+
if (self->curr_token->code == VARIABLE) {
111+
return self->parse_var_statement(self);
112+
}
113+
114+
if (self->curr_token->code == RETURN) {
115+
return self->parse_return_statement(self);
116+
}
117+
118+
return self->parse_expression_statement(self);
119+
}
120+
121+
/**
122+
* Parses a program, which is a series of statements until the end of file token.
123+
*
124+
* This function creates a new program object and continuously parses statements,
125+
* adding them to the program, until it reaches the end of file token. It consumes
126+
* a token after each statement is parsed.
127+
*
128+
* @param self The parser object.
129+
*
130+
* @return The parsed program.
131+
*/
132+
struct Program* __PARSER_parse_program(struct Parser* self) {
133+
struct Program *program = malloc(sizeof(struct Program));
134+
135+
program->statements_capacity = 10;
136+
program->statements_size = 0;
137+
program->statements = malloc(program->statements_capacity * sizeof(struct Statement *));
138+
program->to_string = __AST_program_to_string;
139+
140+
while (!self->curr_token_is(self, END_OF_FILE)) {
141+
struct Statement *statement = self->parse_statement(self);
142+
143+
if (statement != NULL) {
144+
__AST_push_statement_to_program(program, statement);
145+
}
146+
147+
self->consume_token(self);
148+
}
149+
150+
return program;
151+
}

src/parser/token_operations.c

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#include <stdlib.h>
2+
#include <stdio.h>
3+
#include <string.h>
4+
#include <langdef.h>
5+
6+
#include <token/def.h>
7+
8+
#include <ast/lib.h>
9+
#include <lexer/lib.h>
10+
#include <parser/lib.h>
11+
#include <token/lib.h>
12+
13+
/**
14+
* Consumes the current token and advances the lexer.
15+
*
16+
* @param self - The Parser object.
17+
*/
18+
void __PARSER_consume_token(struct Parser *self) {
19+
self->curr_token = self->next_token;
20+
self->next_token = self->lexer->next_token(self->lexer);
21+
}
22+
23+
/**
24+
* Checks if the current token's code matches the provided code.
25+
*
26+
* @param self - The Parser object.
27+
* @param code - The code to be compared with the current token's code.
28+
*
29+
* @return 1 if the codes match, 0 otherwise.
30+
*/
31+
int __PARSER_curr_token_is(struct Parser *self, uint8 code) {
32+
return self->curr_token->code == code;
33+
}
34+
35+
/**
36+
* Checks if the next token's code matches the provided code.
37+
*
38+
* @param self - The Parser object.
39+
* @param code - The code to be compared with the next token's code.
40+
*
41+
* @return 1 if the codes match, 0 otherwise.
42+
*/
43+
int __PARSER_next_token_is(struct Parser *self, uint8 code) {
44+
return self->next_token->code == code;
45+
}
46+
47+
/**
48+
* Consumes the next token if its code matches the provided code, or does nothing otherwise.
49+
*
50+
* @param self - The Parser object.
51+
* @param code - The code to be compared with the next token's code.
52+
*
53+
* @return 1 if the next token was consumed, 0 otherwise.
54+
*/
55+
int __PARSER_consume_or_ignore_if_next_token_is(struct Parser *self, uint8 code) {
56+
if (__PARSER_next_token_is(self, code)) {
57+
self->consume_token(self);
58+
return 1;
59+
}
60+
61+
return 0;
62+
}

0 commit comments

Comments
 (0)