summaryrefslogtreecommitdiff
path: root/masm/parse.h
blob: ea8f9291812ca9e454dff9900f72ffc5b3833327 (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
/* 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_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 section_entry_type {
	ENT_INS,
	ENT_WORD,
	ENT_HALF,
	ENT_BYTE,
	ENT_NO_DATA,
};

struct section_entry {
	enum section_entry_type type;
	size_t size;

	union {
		char data; // to get memory address
		union mips_instruction ins;
		int32_t word;
		int16_t half;
		int8_t byte;
	};
};

struct section {
	uint32_t count;
	uint32_t len;
	uint32_t alignment;
	uint32_t index; // what index is my section
	char name[MAX_LEX_LENGTH];
	bool read;
	bool write;
	bool execute;
	struct section_entry *entries;
};

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

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_get(struct section_table *sec_tbl, struct section **sec,
	       const char name[MAX_LEX_LENGTH]);
int sec_push(struct section *section, struct section_entry entry);
size_t sec_size(struct section *section);
size_t sec_index(struct section *section, uint32_t index);

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;

	// 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__ */