libmya 0.1.0
Library to parse Mya language.
Loading...
Searching...
No Matches
parser.h File Reference
#include "types/err.h"
#include "types/module.h"
#include "types/token.h"
Include dependency graph for parser.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

unsigned int parse_statement (module_t *module, ast_node_t *parent, token_t *token)
 Parse a statement adding it as a children on parent AST node.
 
unsigned int parse_statement_include (module_t *module, ast_node_t *parent, token_t *token)
 Parse a include statement adding it as a children on parent AST node.
 
unsigned int parse_statement_set (module_t *module, ast_node_t *parent, token_t *token)
 Parse a set statement adding it as a children on parent AST node.
 
unsigned int parse_statement_bitfield (module_t *module, ast_node_t *parent, token_t *token)
 Parse a bitfield statement adding it as a children on parent AST node.
 
unsigned int parse_statement_register (module_t *module, ast_node_t *parent, token_t *token)
 Parse a register statement adding it as a children on parent AST node.
 
unsigned int parse_statement_inst (module_t *module, ast_node_t *parent, token_t *token)
 Parse a inst statement adding it as a children on parent AST node.
 
unsigned int parse_expression (module_t *module, ast_node_t *parent, token_t *token)
 Parse a mathematical expression adding it as a children on parent AST node.
 
unsigned int parse_size_spec (module_t *module, ast_node_t *parent, token_t *token, const char *example)
 Parse a size specification in the format [ EXPRESSION ] adding it as a children on parent AST node.
 
unsigned int parse_bitfield_spec (module_t *module, ast_node_t *parent, token_t *token)
 Parse a bitfield specification in the format Bitfield { FIELD_LIST } or Bitfield { EXPRESSION } adding it as a children on parent AST node.
 
unsigned int parse_fieldlist_spec (module_t *module, ast_node_t *parent, token_t *token)
 Parse a field list specification in the format field = EXPRESSION, ... adding it as a children on parent AST node.
 
unsigned int parse_advance (token_t *token, token_type_t *types, size_t ntypes)
 Finds the next token TK_EOF or any of the specified types and then returns the number of tokens traveled.
 

Function Documentation

◆ parse_advance()

unsigned int parse_advance ( token_t * token,
token_type_t * types,
size_t ntypes )

Finds the next token TK_EOF or any of the specified types and then returns the number of tokens traveled.

This function could be used to skip wrong tokens when a error as found on parsing a statement. So it's avoid a lot of useless error messages.

Parameters
tokenPointer for the first token where to start searching.
typesArray of token types to search.
ntypesSize of types array.

Definition at line 125 of file parse_common.c.

126{
127 int ntokens = 0;
128
129 while (token[ntokens].type != TK_EOF) {
130 for (int i = 0; i < ntypes; i++) {
131 if (token[ntokens].type == types[i]) {
132 return ntokens;
133 }
134 }
135
136 ntokens++;
137 }
138
139 return ntokens;
140}
Struct for a Mya token.
Definition token.h:34
@ TK_EOF
Definition token.h:17

◆ parse_bitfield_spec()

unsigned int parse_bitfield_spec ( module_t * module,
ast_node_t * parent,
token_t * token )

Parse a bitfield specification in the format Bitfield { FIELD_LIST } or Bitfield { EXPRESSION } adding it as a children on parent AST node.

Parameters
moduleThe module where the AST is.
parentThe AST node parent for the bitfield specification.
tokenThe token where to start parsing the bitfield specification.
Returns
The number of tokens used on the bitfield specification.

Definition at line 47 of file parse_common.c.

48{
49 ast_node_t* node_statement = ast_add_children(parent, NT_BITFIELD_SPEC, token);
50 token_t* tkid = token;
51 token_t* tkopen_braces = token + 1;
52
53 if (tkid->type != TK_IDENTIFIER) {
55 module,
56 tkid->line,
57 tkid->column,
58 tkid->lexeme.length,
59 "Expected a bitfield identifier here. Example: Reg{1}"
60 );
61
62 return 1;
63 }
64
65 if (tkopen_braces->type != TK_OPEN_BRACES) {
67 module,
68 tkopen_braces->line,
69 tkopen_braces->column,
70 tkopen_braces->lexeme.length,
71 "Expected a open braces after bitfield name. Examples:\n"
72 " Reg{1}\n"
73 "\n"
74 " Opcode {\n"
75 " opcode = 0x01,\n"
76 " reg = Reg{arg1}\n"
77 " }"
78 );
79
80 return 2;
81 }
82
83 unsigned int ntokens = 1 + parse_fieldlist_spec(module, node_statement, tkopen_braces);
84
85 token_t* tkclose_braces = token + ntokens - 1;
86 if (tkclose_braces->type != TK_CLOSE_BRACES) {
88 module,
89 tkclose_braces->line,
90 tkclose_braces->column,
91 tkclose_braces->lexeme.length,
92 "Expected a close braces at end of field specification list. Examples:\n"
93 " Reg{1}\n"
94 "\n"
95 " Opcode {\n"
96 " opcode = 0x01,\n"
97 " reg = Reg{arg1},\n"
98 " }"
99 );
100 }
101
102 return ntokens;
103}
ast_node_t * ast_add_children(ast_node_t *parent, node_type_t type, token_t *token)
Add a new children for the given AST node.
Definition ast.c:40
void module_add_error(module_t *module, unsigned int line, unsigned int column, unsigned int length, const char *message)
Add error for the given module.
Definition module.c:97
unsigned int parse_fieldlist_spec(module_t *module, ast_node_t *parent, token_t *token)
Parse a field list specification in the format field = EXPRESSION, ... adding it as a children on par...
unsigned int length
The length of the string.
Definition dstring.h:13
Struct that represents a Mya module.
Definition module.h:34
token_type_t type
Token type.
Definition token.h:35
dstring_t lexeme
Lexeme of the token.
Definition token.h:41
unsigned int line
Token line inside the module.
Definition token.h:36
unsigned int column
Column of the token position on the line.
Definition token.h:37
struct ast_node ast_node_t
@ NT_BITFIELD_SPEC
Definition ast.h:13
struct token token_t
Struct for a Mya token.
@ TK_IDENTIFIER
Definition token.h:19
@ TK_OPEN_BRACES
Definition token.h:22
@ TK_CLOSE_BRACES
Definition token.h:12

◆ parse_expression()

unsigned int parse_expression ( module_t * module,
ast_node_t * parent,
token_t * token )

Parse a mathematical expression adding it as a children on parent AST node.

Parameters
moduleThe module where the AST is.
parentThe AST node parent for the expression.
tokenThe token where to start parsing the expression.
Returns
The number of tokens used on the expression.

Definition at line 17 of file parse_expression.c.

18{
20 ast_node_t node;
21 token_t* current_token;
22 ast_node_t* child;
23 unsigned int ntokens = 0;
24
26 return parse_bitfield_spec(module, parent, token);
27 }
28
30
31 for (;;) {
32 current_token = &token[ntokens];
33
34 switch (current_token->type) {
35 case TK_OPEN_PARENS:
36 child = stack_push(&stack, NT_EXPRESSION, current_token);
37 ntokens += 1 + parse_expression(module, child, current_token + 1);
38
39 if (token[ntokens].type != TK_CLOSE_PARENS) {
41 module,
42 child->token->line,
43 child->token->column,
44 child->token->lexeme.length,
45 "Open parentheses starting here has not a expected close parentheses matching it."
46 );
47
48 return ntokens;
49 }
50
51 ntokens++;
52 break;
53 case TK_IDENTIFIER:
54 case TK_NUMBER:
55 stack_push(&stack, NT_EXPRESSION, current_token);
56 ntokens++;
57 break;
58 case TK_OPERATOR:
59 ntokens += _parse_operator(module, parent, &stack, current_token);
60 break;
61 case TK_EQUAL:
62 ntokens += _parse_binary_operator(module, parent, &stack, current_token);
63 break;
64 case TK_SEMICOLON:
65 case TK_CLOSE_PARENS:
66 case TK_CLOSE_BRACES:
68 case TK_COMMA:
69 case TK_EOF:
70 goto finish_expression;
71 default:
73 module,
74 current_token->line,
75 current_token->column,
76 current_token->lexeme.length,
77 "Unexpected token inside an expression."
78 );
79
80 ntokens++;
81 goto finish_expression;
82 }
83 }
84
85
86finish_expression:
87 // We expect to only have one expression on stack at end. It's the root node of the expression.
88
89 if (stack_isempty(&stack)) {
90 module_add_error(module, token->line, token->column, token->lexeme.length, "Malformed expression starting here.");
92 return ntokens;
93 }
94
95 stack_pop(&stack, &node);
96
97 if (! stack_isempty(&stack)) {
98 stack_pop(&stack, &node);
99
101 module,
102 node.token->line,
103 node.token->column,
104 node.token->lexeme.length,
105 "Unexpected expression starting here."
106 );
107
109 return ntokens;
110 }
111
112 ast_insert_children(parent, &node);
114 return ntokens;
115}
ast_node_t * ast_insert_children(ast_node_t *parent, ast_node_t *child)
Insert a exitent AST node as children of the given parent node.
Definition ast.c:51
unsigned int parse_expression(module_t *module, ast_node_t *parent, token_t *token)
Parse a mathematical expression adding it as a children on parent AST node.
unsigned int parse_bitfield_spec(module_t *module, ast_node_t *parent, token_t *token)
Parse a bitfield specification in the format Bitfield { FIELD_LIST } or Bitfield { EXPRESSION }...
void stack_init(stack_t *stack)
Initializes the given stack.
Definition stack.c:11
ast_node_t * stack_push(stack_t *stack, node_type_t type, token_t *token)
Push a new value on the stack.
Definition stack.c:27
void stack_close(stack_t *stack)
Closes the given stack.
Definition stack.c:20
error_code_t stack_pop(stack_t *stack, ast_node_t *value)
Pop a value from the stack.
Definition stack.c:47
bool stack_isempty(stack_t *stack)
Check if the given stack is empty.
Definition stack.c:59
token_t * token
Definition ast.h:30
A struct representing a dynamic stack.
Definition stack.h:12
@ NT_EXPRESSION
Definition ast.h:14
struct stack stack_t
A struct representing a dynamic stack.
@ TK_NUMBER
Definition token.h:21
@ TK_OPEN_PARENS
Definition token.h:24
@ TK_COMMA
Definition token.h:16
@ TK_CLOSE_PARENS
Definition token.h:14
@ TK_OPERATOR
Definition token.h:25
@ TK_CLOSE_BRACKET
Definition token.h:13
@ TK_EQUAL
Definition token.h:18
@ TK_SEMICOLON
Definition token.h:26

◆ parse_fieldlist_spec()

unsigned int parse_fieldlist_spec ( module_t * module,
ast_node_t * parent,
token_t * token )

Parse a field list specification in the format field = EXPRESSION, ... adding it as a children on parent AST node.

Parameters
moduleThe module where the AST is.
parentThe AST node parent for the field list specification.
tokenThe token where to start parsing the field list specification. It should be the open braces ({).
Returns
The number of tokens used on the field list specification.

Definition at line 106 of file parse_common.c.

107{
108 ast_node_t* node_statement = ast_add_children(parent, NT_FIELD_SPEC, token);
109 unsigned int ntokens = 0;
110
111 do {
112 ntokens++;
113
114 if (token[ntokens].type == TK_CLOSE_BRACES) {
115 break;
116 }
117
118 ntokens += parse_expression(module, node_statement, &token[ntokens]);
119 } while (token[ntokens].type == TK_COMMA);
120
121 return ntokens + 1;
122}
unsigned int parse_expression(module_t *module, ast_node_t *parent, token_t *token)
Parse a mathematical expression adding it as a children on parent AST node.
@ NT_FIELD_SPEC
Definition ast.h:15

◆ parse_size_spec()

unsigned int parse_size_spec ( module_t * module,
ast_node_t * parent,
token_t * token,
const char * example )

Parse a size specification in the format [ EXPRESSION ] adding it as a children on parent AST node.

Parameters
moduleThe module where the AST is.
parentThe AST node parent for the size specification.
tokenThe token where to start parsing the size specification.
exampleA code example printed on error messages when the size spec is syntactically wrong.
Returns
The number of tokens used on the size specification.

Definition at line 7 of file parse_common.c.

8{
9 char message[128];
10 token_t* tkopen_bracket = token;
11 token_t* tkexpr = token + 1;
12
13 if (tkopen_bracket->type != TK_OPEN_BRACKET) {
14 snprintf(
15 message,
16 sizeof message - 1,
17 "Expected a size specifier after the %s name. Example: %s",
19 example
20 );
21
22 module_add_error(module, tkopen_bracket->line, tkopen_bracket->column, tkopen_bracket->lexeme.length, message);
23
24 return 2;
25 }
26
27 unsigned int ntokens = parse_expression(module, parent, tkexpr);
28
29 token_t* tkclose_bracket = token + ntokens + 1;
30
31 if (tkclose_bracket->type != TK_CLOSE_BRACKET) {
32 snprintf(message, sizeof message - 1, "Expected a close bracket here. Example: %s", example);
33
35 module,
36 tkclose_bracket->line,
37 tkclose_bracket->column,
38 tkclose_bracket->lexeme.length,
39 "Expected a close bracket here. Example: bitfield Name[4]"
40 );
41 }
42
43 return ntokens + 2;
44}
const char * mya_keywords[]
Definition globals.c:11
long long int value
Integer value of the token.
Definition token.h:38
@ TK_OPEN_BRACKET
Definition token.h:23

◆ parse_statement()

unsigned int parse_statement ( module_t * module,
ast_node_t * parent,
token_t * token )

Parse a statement adding it as a children on parent AST node.

Parameters
moduleThe module where the AST is.
parentThe AST node parent for the statement.
tokenThe token where to start parsing the statement.
Returns
The number of tokens used on the statement.

Definition at line 8 of file parse_statement.c.

9{
10 if (token->type != TK_KEYWORD) {
12 module,
13 token->line,
16 "This token is unexpected here. It's expected to be a valid statement keyword."
17 );
18
19 return 1;
20 }
21
22 switch (token->value) {
23 case KEY_INCLUDE:
24 return parse_statement_include(module, parent, token);
25 case KEY_SET:
26 return parse_statement_set(module, parent, token);
27 case KEY_BITFIELD:
28 return parse_statement_bitfield(module, parent, token);
29 case KEY_REGISTER:
30 return parse_statement_register(module, parent, token);
31 case KEY_INST:
32 return parse_statement_inst(module, parent, token);
33 default:
35 module,
36 token->line,
39 "It's an invalid statement keyword. Are you sure it's a valid command or declaration?"
40 );
41
42 return 1;
43 }
44}
@ KEY_INST
Definition keywords.h:8
@ KEY_SET
Definition keywords.h:10
@ KEY_BITFIELD
Definition keywords.h:5
@ KEY_REGISTER
Definition keywords.h:9
@ KEY_INCLUDE
Definition keywords.h:7
unsigned int parse_statement_inst(module_t *module, ast_node_t *parent, token_t *token)
Parse a inst statement adding it as a children on parent AST node.
unsigned int parse_statement_include(module_t *module, ast_node_t *parent, token_t *token)
Parse a include statement adding it as a children on parent AST node.
unsigned int parse_statement_register(module_t *module, ast_node_t *parent, token_t *token)
Parse a register statement adding it as a children on parent AST node.
unsigned int parse_statement_set(module_t *module, ast_node_t *parent, token_t *token)
Parse a set statement adding it as a children on parent AST node.
unsigned int parse_statement_bitfield(module_t *module, ast_node_t *parent, token_t *token)
Parse a bitfield statement adding it as a children on parent AST node.
@ TK_KEYWORD
Definition token.h:20

◆ parse_statement_bitfield()

unsigned int parse_statement_bitfield ( module_t * module,
ast_node_t * parent,
token_t * token )

Parse a bitfield statement adding it as a children on parent AST node.

Parameters
moduleThe module where the AST is.
parentThe AST node parent for the statement.
tokenThe token where to start parsing the statement.
Returns
The number of tokens used on the statement.

Definition at line 10 of file parse_statement_bitfield.c.

11{
12 ast_node_t* node_statement = ast_add_children(parent, NT_STATEMENT, token);
13 token_t* tkid = token + 1;
14
15 if (tkid->type != TK_IDENTIFIER) {
17 module,
18 tkid->line,
19 tkid->column,
20 tkid->lexeme.length,
21 "Expected an identifier here. Example: bitfield Name[4]"
22 );
23
24 return 1;
25 }
26
27 ast_add_children(node_statement, NT_IDENTIFIER, tkid);
28 unsigned int ntokens = 2 + parse_size_spec(module, node_statement, token + 2, "bitfield Name[4]");
29
30 token_t* tkopen_braces = token + ntokens;
31
32 if (tkopen_braces->type == TK_OPEN_BRACES) {
33 ast_node_t* body = ast_add_children(node_statement, NT_BITFIELD_BODY, tkopen_braces);
34 ntokens += 1 + _parse_bitfield_body(module, body, tkopen_braces + 1);
35 }
36
37 return ntokens;
38}
unsigned int parse_size_spec(module_t *module, ast_node_t *parent, token_t *token, const char *example)
Parse a size specification in the format [ EXPRESSION ] adding it as a children on parent AST node.
Definition parse_common.c:7
@ NT_IDENTIFIER
Definition ast.h:17
@ NT_STATEMENT
Definition ast.h:21
@ NT_BITFIELD_BODY
Definition ast.h:12

◆ parse_statement_include()

unsigned int parse_statement_include ( module_t * module,
ast_node_t * parent,
token_t * token )

Parse a include statement adding it as a children on parent AST node.

Parameters
moduleThe module where the AST is.
parentThe AST node parent for the statement.
tokenThe token where to start parsing the statement.
Returns
The number of tokens used on the statement.

Definition at line 6 of file parse_statement_include.c.

7{
8 ast_node_t* node_statement = ast_add_children(parent, NT_STATEMENT, token);
9 token_t* tkstring = token + 1;
10 token_t* tksemicolon = token + 2;
11
12 if (tkstring->type != TK_STRING) {
14 module,
15 tkstring->line,
16 tkstring->column,
17 tkstring->lexeme.length,
18 "Expected literal string here. Example: include \"module.mya\";"
19 );
20
21 return 1;
22 }
23
24 if (tksemicolon->type != TK_SEMICOLON) {
26 module,
27 tkstring->line,
28 tkstring->column + tkstring->lexeme.length + 1,
29 1,
30 "Expected semicolon at end of the include command. Example: include \"module.mya\";"
31 );
32 }
33
34 ast_add_children(node_statement, NT_STRING, tkstring);
35
36 return 2 + (tksemicolon->type == TK_SEMICOLON);
37}
@ NT_STRING
Definition ast.h:22
@ TK_STRING
Definition token.h:27

◆ parse_statement_inst()

unsigned int parse_statement_inst ( module_t * module,
ast_node_t * parent,
token_t * token )

Parse a inst statement adding it as a children on parent AST node.

Parameters
moduleThe module where the AST is.
parentThe AST node parent for the statement.
tokenThe token where to start parsing the statement.
Returns
The number of tokens used on the statement.

Definition at line 14 of file parse_statement_inst.c.

15{
16 ast_node_t* node_statement = ast_add_children(parent, NT_STATEMENT, token);
17 token_t* tkid = token + 1;
18
19 if (tkid->type != TK_IDENTIFIER) {
21 module,
22 tkid->line,
23 tkid->column,
24 tkid->lexeme.length,
25 "Expected an identifier here. Example: inst mov[16](arg1: register[32], arg2: immediate[8]) { ... }"
26 );
27
28 return 1;
29 }
30
31 ast_add_children(node_statement, NT_IDENTIFIER, tkid);
32 unsigned int ntokens =
33 2 +
34 parse_size_spec(module, node_statement, token + 2, "inst mov[16](arg1: register[32], arg2: immediate[8]) { ... }");
35
36 token_t* tkopen_parens = token + ntokens;
37
38 if (tkopen_parens->type != TK_OPEN_PARENS) {
40 module,
41 tkopen_parens->line,
42 tkopen_parens->column,
43 tkopen_parens->lexeme.length,
44 "Expected a list of arguments for the instruction inside parentheses. Example: inst mov[16](arg1: register[32], "
45 "arg2: immediate[8]) { ... }"
46 );
47
48 return ntokens + 1;
49 }
50
51 ntokens += _parse_inst_args(module, node_statement, tkopen_parens);
52
53 token_t* tkopen_braces = token + ntokens;
54 if (tkopen_braces->type != TK_OPEN_BRACES) {
56 module,
57 tkopen_braces->line,
58 tkopen_braces->column,
59 tkopen_braces->lexeme.length,
60 "Expected an open braces at start of the body of the instruction. Example: inst mov[16](arg1: register[32], "
61 "arg2: immediate[8]) { ... }"
62 );
63
64 return ntokens;
65 }
66
67 ntokens += parse_fieldlist_spec(module, node_statement, token + ntokens);
68
69 return ntokens;
70}
unsigned int parse_fieldlist_spec(module_t *module, ast_node_t *parent, token_t *token)
Parse a field list specification in the format field = EXPRESSION, ... adding it as a children on par...

◆ parse_statement_register()

unsigned int parse_statement_register ( module_t * module,
ast_node_t * parent,
token_t * token )

Parse a register statement adding it as a children on parent AST node.

Parameters
moduleThe module where the AST is.
parentThe AST node parent for the statement.
tokenThe token where to start parsing the statement.
Returns
The number of tokens used on the statement.

Definition at line 6 of file parse_statement_register.c.

7{
8 ast_node_t* node_statement = ast_add_children(parent, NT_STATEMENT, token);
9 token_t* tkid = token + 1;
10
11 if (tkid->type != TK_IDENTIFIER) {
13 module,
14 tkid->line,
15 tkid->column,
16 tkid->lexeme.length,
17 "Expected an identifier here. Example: register r1[32] = Reg{1}"
18 );
19
20 return 1;
21 }
22
23 ast_add_children(node_statement, NT_IDENTIFIER, tkid);
24 unsigned int ntokens = 2 + parse_size_spec(module, node_statement, token + 2, "register r1[32] = Reg{1}");
25
26 token_t* tkequal = token + ntokens;
27
28 if (tkequal->type != TK_EQUAL) {
30 module,
31 tkequal->line,
32 tkequal->column,
33 tkequal->lexeme.length,
34 "Expected an equal symbol here. Example: register r1[32] = Reg{1}"
35 );
36
37 return ntokens + 1;
38 }
39
40 return ntokens + 1 + parse_bitfield_spec(module, node_statement, tkequal + 1);
41}

◆ parse_statement_set()

unsigned int parse_statement_set ( module_t * module,
ast_node_t * parent,
token_t * token )

Parse a set statement adding it as a children on parent AST node.

Parameters
moduleThe module where the AST is.
parentThe AST node parent for the statement.
tokenThe token where to start parsing the statement.
Returns
The number of tokens used on the statement.

Definition at line 6 of file parse_statement_set.c.

7{
8 ast_node_t* node_statement = ast_add_children(parent, NT_STATEMENT, token);
9 token_t* tkid = token + 1;
10 token_t* tkequal = token + 2;
11 token_t* tkexpr = token + 3;
12
13 if (tkid->type != TK_IDENTIFIER) {
15 module,
16 tkid->line,
17 tkid->column,
18 tkid->lexeme.length,
19 "Expected an identifier here. Example: set NAME = value;"
20 );
21
22 return 1;
23 }
24
25 if (tkequal->type != TK_EQUAL) {
27 module,
28 tkequal->line,
29 tkequal->column,
30 tkequal->lexeme.length,
31 "Expected an equal operator here. Example: set NAME = value;"
32 );
33 }
34
35 ast_add_children(node_statement, NT_IDENTIFIER, tkid);
36
37 unsigned int ntokens = 3 + parse_expression(module, node_statement, tkexpr);
38
39 token_t* tksemicolon = token + ntokens;
40
41 if (tksemicolon->type != TK_SEMICOLON) {
43 module,
44 tksemicolon->line,
45 tksemicolon->column,
46 1,
47 "Expected semicolon at end of the set command. Example: set NUMBER = 1;"
48 );
49 }
50
51 return ntokens + 1;
52}