summaryrefslogtreecommitdiff
path: root/masm/parse.h
blob: 2aea0befb20f77cc1bd540730e782957165d5951 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/* Copyright (c) 2024 Freya Murphy */

#ifndef __PARSE_H__
#define __PARSE_H__

#include "lex.h"

#include <mlimits.h>
#include <mips.h>
#include <stdint.h>

struct const_expr {
	char name[MAX_LEX_LENGTH];
	uint32_t value;
};

enum expr_type {
	EXPR_INS,
	EXPR_DIRECTIVE,
	EXPR_CONSTANT,
	EXPR_SEGMENT,
	EXPR_LABEL,
};

struct expr {
	enum expr_type type;
	union {
		// instruction
		union mips_instruction ins;
		// directive
		union mips_directive directive;
		// constant
		struct const_expr constant;
		// segment or label
		char text[MAX_LEX_LENGTH];
	};
};

enum symbol_flag {
	SYM_LOCAL,
	SYM_GLOBAL,
	SYM_EXTERNAL,
};

struct symbol {
	char name[MAX_LEX_LENGTH];
	uint32_t position;
	enum symbol_flag flag;

};

struct symbol_table {
	uint32_t count;
	uint32_t len;
	struct symbol *symbols;
};

int symtbl_init(struct symbol_table *sym_tbl);
void symtbl_free(struct symbol_table *sym_tbl);

int symtbl_push(struct symbol_table *sym_tbl, struct symbol sym);
int symtbl_find(struct symbol_table *sym_tbl, struct symbol **sym,
		const char name[MAX_LEX_LENGTH]);

struct section {
	uint32_t count;
	uint32_t len;
	uint32_t start;
	uint32_t alignment;
	union mips_instruction *ins;
	char name[MAX_LEX_LENGTH];
};

struct section_table {
	uint32_t count;
	uint32_t len;
	struct section *sections;
	struct section *current;
	char name[MAX_LEX_LENGTH];
	uint32_t total_ins;
};

int sectbl_init(struct section_table *sec_tbl);
void sectbl_free(struct section_table *sec_tbl);

int sectbl_alloc(struct section_table *sec_tbl, struct section **sec,
		 const char name[MAX_LEX_LENGTH]);
int sectbl_push(struct section_table *sec_tbl, struct section *section,
		union mips_instruction ins);
int sectbl_get(struct section_table *sec_tbl, struct section **sec,
	       const char name[MAX_LEX_LENGTH]);

enum reference_type {
	REF_OFFESET,
	REF_TARGET,
};

struct reference {
	enum reference_type type;
	struct section *section;
	uint32_t index;
	char name[MAX_LEX_LENGTH];
};

struct reference_table {
	uint32_t count;
	uint32_t len;
	struct reference *references;
};

int reftbl_init(struct reference_table *ref_tbl);
void reftbl_free(struct reference_table *ref_tbl);
int reftbl_push(struct reference_table *ref_tbl, struct reference reference);

struct parser {
	struct lexer *lexer;
	struct token peek;

	// sections
	struct section_table sec_tbl;

	// symbols
	struct symbol_table sym_tbl;

	// references
	struct reference_table ref_tbl;

	int (*parse_instruction)(struct parser *, union mips_instruction *,
			  struct token);
	int (*parse_directive)(struct parser *, union mips_directive *);
	int (*is_instruction)(const char *ident);
};

/* get the next token in the parser */
int next_token(struct parser *parser, struct token *tok);

/* peek the next token in the parser */
int peek_token(struct parser *parser, struct token *tok);

/* assert the next token is a specific type */
int assert_token(struct parser *parser, enum token_type type,
		 struct token *tok);

/* assert the next token is EOF or NL */
int assert_eol(struct parser *parser);

/* get the next expression in the parser */
int parser_next(struct parser *parser, struct expr *expr);

/* initalize the base parser */
int parser_init(struct lexer *lexer, struct parser *parser);

/* free the base parser */
void parser_free(struct parser *parser);

#endif /* __PARSE_H__ */