-
Notifications
You must be signed in to change notification settings - Fork 0
/
pcc.h
206 lines (176 loc) · 4.29 KB
/
pcc.h
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#define _POSIX_C_SOURCE 200809L // For strndup
#ifndef PCC_H_
#define PCC_H_
#include <ctype.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Tokenizer
/**
* The kind of tokens
*/
typedef enum {
TK_RESERVED, // Operator token
TK_IDENT, // Identifier
TK_NUM, // Number token
TK_RETURN, // "return" token
TK_EOF, // End of file, which is the end of the input
} TokenKind;
typedef struct Token Token;
/**
* Token type
*/
struct Token {
TokenKind kind; // The kind of the token
Token *next; // The next input token
int val; // The value of the number if the kind of the token is TK_NUM
char *str; // The token string
int len; // The length of the token
};
/**
* The current token
*/
extern Token *token;
/**
* The whole input
*/
extern char *user_input;
/**
* Report an error.
*
* This function takes the same arguments as printf.
*
* @param loc the error location in the input
* @param fmt the format string
* @param ... the parameters to be used for the formatting
*/
void error_at(char *loc, char *fmt, ...);
/**
* Consume a token
*
* If the next token is the expected operator, scan a token and return true.
* Otherwise return false.
*
* @param op the pointer to the operator string
* @return true if the next token is the expected operator, otherwise false
*/
bool consume(char *op);
/**
* Consumes an identifier token.
*
* If the next token is an identifier, scan a token and return the node
* constructed for the identifier.
*
* @return the current identifier token
*/
Token *consume_ident();
/**
* Expects a valid token
*
* If the next token is the expected operator, scan a token. Otherwise report the
* error.
*
* @param op the pointer to the operator string
*/
void expect(char *op);
/**
* Expects a number token
*
* If the token is a number, scan a token and return its value. Otherwise report
* the error.
*
* @return the value of the number token if the next token is a number
*/
int expect_number();
/**
* Examine if it is EOF
*
* @return true if it is EOF, otherwise false
*/
bool at_eof();
/**
* Tokenize the input string
*
* @param p the pointer to the input string
* @return the token tokenized from the input string
*/
Token *tokenize(char *p);
// Parser
/**
* The kind of abstract syntax tree (AST) nodes
*/
typedef enum {
ND_ADD, // +
ND_SUB, // -
ND_MUL, // *
ND_DIV, // /
ND_NUM, // Integer
ND_EQ, // ==
ND_NE, // !=
ND_LT, // <
ND_LE, // <=
ND_ASSIGN, // Variable assignment
ND_LVAR, // Local variable
ND_IF, // if statement
ND_WHILE, // while statement
ND_FOR, // for statement
ND_BLOCK, // blocks
ND_FUNCALL, // function call
ND_RETURN, // Return statement
} NodeKind;
typedef struct LVar LVar;
/**
* Local variable type
*/
struct LVar {
LVar *next; // The next local variable or NULL.
const char *name; // The name of the local variable.
int offset; // The offset from the base register, RBP.
};
typedef struct Node Node;
/**
* The AST node type
*/
struct Node {
NodeKind kind; // The kind of the node
Node *next; // The next AST node that contains another statement
const Node *lhs; // Left hand side
const Node *rhs; // Right hand side
int val; // The value of the integer if the kind is ND_NUM
LVar *lvar; // The local variable only if the kind is ND_LVAR
const char *name; // The name of the funciton only if kind is ND_FUNCALL
};
/**
* The entire parsed code in AST.
*/
extern Node *code[100];
typedef struct Function Function;
/**
* The function implementation consists of its parsed code, local variables
* and required stack size.
*/
struct Function {
Node *node;
LVar *locals;
int stack_size;
};
/**
* Parse tokens with the "program" production rule
*
* stmt = expr ";"
*
* The parsed result is store in the global variable "code".
*
* @return the parsed code as a function
*/
Function *program();
// Assembly code generator
/**
* Generate a series of assembly code that emulates stack machine from the AST
*
* @param program the function from which the assembly code is generated
*/
void codegen(const Function *program);
#endif // PCC_H_