Matt Coles 8 年之前
父節點
當前提交
4395577753
共有 40 個文件被更改,包括 13099 次插入2 次删除
  1. 0 1
      cw
  2. 2 0
      cw/.gitignore
  3. 138 0
      cw/C.flex
  4. 1998 0
      cw/C.tab.c
  5. 88 0
      cw/C.tab.h
  6. 270 0
      cw/C.y
  7. 28 0
      cw/Makefile
  8. 3 0
      cw/README.md
  9. 1832 0
      cw/lex.yy.c
  10. 67 0
      cw/list.c
  11. 12 0
      cw/list.h
  12. 295 0
      cw/main.c
  13. 31 0
      cw/nodes.c
  14. 13 0
      cw/nodes.h
  15. 11 0
      cw/prog.c
  16. 9 0
      cw/simple.c
  17. 58 0
      cw/symbol_table.c
  18. 18 0
      cw/token.h
  19. 21 0
      cw/types.h
  20. 0 1
      tac
  21. 2 0
      tac/.gitignore
  22. 144 0
      tac/C.flex
  23. 2551 0
      tac/C.output
  24. 2297 0
      tac/C.tab.c
  25. 83 0
      tac/C.tab.h
  26. 275 0
      tac/C.y
  27. 30 0
      tac/Makefile
  28. 3 0
      tac/README.md
  29. 2086 0
      tac/lex.yy.c
  30. 142 0
      tac/list.c
  31. 15 0
      tac/list.h
  32. 375 0
      tac/main.c
  33. 31 0
      tac/nodes.c
  34. 13 0
      tac/nodes.h
  35. 11 0
      tac/prog.c
  36. 6 0
      tac/simple.c
  37. 58 0
      tac/symbol_table.c
  38. 18 0
      tac/test.asm
  39. 18 0
      tac/token.h
  40. 47 0
      tac/types.h

+ 0 - 1
cw

@@ -1 +0,0 @@
1
-Subproject commit c853190fe5ac63dc0c95ff62146b750e1f116d8b

+ 2 - 0
cw/.gitignore

@@ -0,0 +1,2 @@
1
+*.o
2
+mycc

+ 138 - 0
cw/C.flex

@@ -0,0 +1,138 @@
1
+D			[0-9]
2
+L			[a-zA-Z_]
3
+H			[a-fA-F0-9]
4
+E			[Ee][+-]?{D}+
5
+FS			(f|F|l|L)
6
+IS			(u|U|l|L)*
7
+
8
+%{
9
+#include <stdio.h>
10
+#include "C.tab.h"
11
+#include <string.h>
12
+#include <stdlib.h>
13
+#include "token.h"
14
+TOKEN* make_string(char*);
15
+extern TOKEN* lookup_token(char*);
16
+TOKEN* make_int(char*);
17
+TOKEN* lasttok;
18
+
19
+void count(void);
20
+void comment(void);
21
+%}
22
+
23
+%%
24
+"/*"			{ comment(); }
25
+
26
+"auto"			{ count(); return(AUTO); }
27
+"break"			{ count(); return(BREAK); }
28
+"continue"		{ count(); return(CONTINUE); }
29
+"else"			{ count(); return(ELSE); }
30
+"extern"		{ count(); return(EXTERN); }
31
+"if"			{ count(); return(IF); }
32
+"int"			{ count(); return(INT); }
33
+"function"		{ count(); return(FUNCTION); }
34
+"return"		{ count(); return(RETURN); }
35
+"void"			{ count(); return(VOID); }
36
+"while"			{ count(); return(WHILE); }
37
+
38
+{L}({L}|{D})*		{ count(); lasttok = lookup_token(yytext);
39
+                          return(IDENTIFIER); }
40
+
41
+{D}+{IS}?		{ count(); lasttok = make_int(yytext);return(CONSTANT); }
42
+L?'(\\.|[^\\'])+'	{ count(); lasttok = make_int(yytext);return(CONSTANT); }
43
+
44
+L?\"(\\.|[^\\"])*\"	{ count(); lasttok = make_string(yytext);
45
+                          return(STRING_LITERAL); }
46
+
47
+"<="			{ count(); return(LE_OP); }
48
+">="			{ count(); return(GE_OP); }
49
+"=="			{ count(); return(EQ_OP); }
50
+"!="			{ count(); return(NE_OP); }
51
+";"			{ count(); return(';'); }
52
+"{"     		{ count(); return('{'); }
53
+"}"     		{ count(); return('}'); }
54
+","			{ count(); return(','); }
55
+":"			{ count(); return(':'); }
56
+"="			{ count(); return('='); }
57
+"("			{ count(); return('('); }
58
+")"			{ count(); return(')'); }
59
+"!"			{ count(); return('!'); }
60
+"-"			{ count(); return('-'); }
61
+"+"			{ count(); return('+'); }
62
+"*"			{ count(); return('*'); }
63
+"/"			{ count(); return('/'); }
64
+"%"			{ count(); return('%'); }
65
+"<"			{ count(); return('<'); }
66
+">"			{ count(); return('>'); }
67
+
68
+[ \t\v\n\f]		{ count(); }
69
+.			{ /* ignore bad characters */ }
70
+
71
+%%
72
+
73
+int yywrap(void)
74
+{
75
+	return(1);
76
+}
77
+
78
+
79
+void comment(void)
80
+{
81
+	char c, c1;
82
+
83
+loop:
84
+	while ((c = input()) != '*' && c != 0)
85
+		putchar(c);
86
+
87
+	if ((c1 = input()) != '/' && c != 0)
88
+	{
89
+		unput(c1);
90
+		goto loop;
91
+	}
92
+
93
+	if (c != 0)
94
+		putchar(c1);
95
+}
96
+
97
+
98
+int column = 0;
99
+
100
+void count()
101
+{
102
+	int i;
103
+
104
+	for (i = 0; yytext[i] != '\0'; i++)
105
+		if (yytext[i] == '\n')
106
+			column = 0;
107
+		else if (yytext[i] == '\t')
108
+			column += 8 - (column % 8);
109
+		else
110
+			column++;
111
+
112
+	ECHO;
113
+}
114
+
115
+
116
+TOKEN *new_token(int type)
117
+{
118
+    TOKEN *ans = (TOKEN*)malloc(sizeof(TOKEN));
119
+    ans->type = type;
120
+    return ans;
121
+}
122
+
123
+TOKEN *make_string(char *s)
124
+{
125
+    TOKEN *ans = new_token(STRING_LITERAL);
126
+    int len = strlen(s);
127
+    ans->lexeme = (char*)calloc(1, len-1);
128
+    strncpy(ans->lexeme, s+1, len-2);
129
+    return ans;
130
+}
131
+
132
+TOKEN *make_int(char *s)
133
+{
134
+    int n = *s!='\'' ? atoi(s) : *(s+1);
135
+    TOKEN *ans = new_token(CONSTANT);
136
+    ans->value = n;
137
+    return ans;
138
+}

文件差異過大導致無法顯示
+ 1998 - 0
cw/C.tab.c


+ 88 - 0
cw/C.tab.h

@@ -0,0 +1,88 @@
1
+/* A Bison parser, made by GNU Bison 1.875.  */
2
+
3
+/* Skeleton parser for Yacc-like parsing with Bison,
4
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc.
5
+
6
+   This program is free software; you can redistribute it and/or modify
7
+   it under the terms of the GNU General Public License as published by
8
+   the Free Software Foundation; either version 2, or (at your option)
9
+   any later version.
10
+
11
+   This program is distributed in the hope that it will be useful,
12
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+   GNU General Public License for more details.
15
+
16
+   You should have received a copy of the GNU General Public License
17
+   along with this program; if not, write to the Free Software
18
+   Foundation, Inc., 59 Temple Place - Suite 330,
19
+   Boston, MA 02111-1307, USA.  */
20
+
21
+/* As a special exception, when this file is copied by Bison into a
22
+   Bison output file, you may use that output file without restriction.
23
+   This special exception was added by the Free Software Foundation
24
+   in version 1.24 of Bison.  */
25
+
26
+/* Tokens.  */
27
+#ifndef YYTOKENTYPE
28
+# define YYTOKENTYPE
29
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
30
+      know about them.  */
31
+   enum yytokentype {
32
+     IDENTIFIER = 258,
33
+     CONSTANT = 259,
34
+     STRING_LITERAL = 260,
35
+     LE_OP = 261,
36
+     GE_OP = 262,
37
+     EQ_OP = 263,
38
+     NE_OP = 264,
39
+     EXTERN = 265,
40
+     AUTO = 266,
41
+     INT = 267,
42
+     VOID = 268,
43
+     FUNCTION = 269,
44
+     APPLY = 270,
45
+     LEAF = 271,
46
+     IF = 272,
47
+     ELSE = 273,
48
+     WHILE = 274,
49
+     CONTINUE = 275,
50
+     BREAK = 276,
51
+     RETURN = 277
52
+   };
53
+#endif
54
+#define IDENTIFIER 258
55
+#define CONSTANT 259
56
+#define STRING_LITERAL 260
57
+#define LE_OP 261
58
+#define GE_OP 262
59
+#define EQ_OP 263
60
+#define NE_OP 264
61
+#define EXTERN 265
62
+#define AUTO 266
63
+#define INT 267
64
+#define VOID 268
65
+#define FUNCTION 269
66
+#define APPLY 270
67
+#define LEAF 271
68
+#define IF 272
69
+#define ELSE 273
70
+#define WHILE 274
71
+#define CONTINUE 275
72
+#define BREAK 276
73
+#define RETURN 277
74
+
75
+
76
+
77
+
78
+#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
79
+typedef int YYSTYPE;
80
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
81
+# define YYSTYPE_IS_DECLARED 1
82
+# define YYSTYPE_IS_TRIVIAL 1
83
+#endif
84
+
85
+extern YYSTYPE yylval;
86
+
87
+
88
+

+ 270 - 0
cw/C.y

@@ -0,0 +1,270 @@
1
+%{
2
+#include "nodes.h"
3
+#define YYSTYPE NODE*
4
+#define YYDEBUG 1
5
+extern TOKEN *int_token, *void_token, *function_token, *lasttok;
6
+NODE *ans;
7
+%}
8
+
9
+%token IDENTIFIER CONSTANT STRING_LITERAL
10
+%token LE_OP GE_OP EQ_OP NE_OP
11
+
12
+%token EXTERN AUTO
13
+%token INT VOID FUNCTION
14
+%token APPLY LEAF
15
+
16
+%token  IF ELSE WHILE CONTINUE BREAK RETURN
17
+
18
+%start goal
19
+%%
20
+
21
+goal    :  translation_unit { ans = $$ = $1;}
22
+        ;
23
+
24
+primary_expression
25
+	: IDENTIFIER 			{ $$ = make_leaf(lasttok); }
26
+	| CONSTANT 			{ $$ = make_leaf(lasttok); }
27
+	| STRING_LITERAL 		{ $$ = make_leaf(lasttok); }
28
+	| '(' expression ')' 		{ $$ = $2; }
29
+	;
30
+
31
+postfix_expression
32
+	: primary_expression		{ $$ = $1; }
33
+	| postfix_expression '(' ')'    { $$ = make_node(APPLY, $1, NULL); }
34
+	| postfix_expression '(' argument_expression_list ')' {
35
+				          $$ = make_node(APPLY, $1, $3); }
36
+	;
37
+
38
+argument_expression_list
39
+	: assignment_expression		{ $$ = $1; }
40
+	| argument_expression_list ',' assignment_expression {
41
+          $$ = make_node(',', $1, $3); }
42
+	;
43
+
44
+unary_expression
45
+	: postfix_expression		{ $$ = $1; }
46
+	| unary_operator unary_expression { $$ = make_node((int)$1, $2, NULL); }
47
+	;
48
+
49
+unary_operator
50
+	: '&'		{ $$ = $1; }
51
+	| '*'		{ $$ = $1; }
52
+	| '+'		{ $$ = $1; }
53
+	| '-'		{ $$ = $1; }
54
+	| '!'		{ $$ = $1; }
55
+	;
56
+
57
+multiplicative_expression
58
+	: unary_expression		{ $$ = $1; }
59
+	| multiplicative_expression '*' unary_expression {
60
+                                          $$ = make_node('*', $1, $3); }
61
+	| multiplicative_expression '/' unary_expression {
62
+                                          $$ = make_node('/', $1, $3); }
63
+	| multiplicative_expression '%' unary_expression {
64
+                                          $$ = make_node('%', $1, $3); }
65
+	;
66
+
67
+additive_expression
68
+	: multiplicative_expression		{ $$ = $1; }
69
+	| additive_expression '+' multiplicative_expression {
70
+                                          $$ = make_node('+', $1, $3); }
71
+	| additive_expression '-' multiplicative_expression {
72
+                                          $$ = make_node('-', $1, $3); }
73
+	;
74
+
75
+relational_expression
76
+	: additive_expression		{ $$ = $1; }
77
+	| relational_expression '<' additive_expression	{
78
+                                          $$ = make_node('<', $1, $3); }
79
+	| relational_expression '>' additive_expression {
80
+                                          $$ = make_node('>', $1, $3); }
81
+	| relational_expression LE_OP additive_expression {
82
+                                          $$ = make_node(LE_OP, $1, $3); }
83
+	| relational_expression GE_OP additive_expression {
84
+                                          $$ = make_node(GE_OP, $1, $3); }
85
+	;
86
+
87
+equality_expression
88
+	: relational_expression		{ $$ = $1; }
89
+	| equality_expression EQ_OP relational_expression {
90
+                                          $$ = make_node(EQ_OP, $1, $3); }
91
+	| equality_expression NE_OP relational_expression {
92
+                                          $$ = make_node(NE_OP, $1, $3); }
93
+	;
94
+
95
+assignment_expression
96
+	: equality_expression		{ $$ = $1; }
97
+	| unary_expression '=' assignment_expression {
98
+                                          $$ = make_node('=', $1, $3); }
99
+	;
100
+
101
+expression
102
+	: assignment_expression		{ $$ = $1; }
103
+	| expression ',' assignment_expression { $$ = make_node(',', $1, $3); }
104
+	;
105
+
106
+declaration
107
+	: declaration_specifiers ';'		{ $$ = $1; }
108
+	| function_definition			{ $$ = $1; }
109
+	| declaration_specifiers init_declarator_list ';' {
110
+                                                  $$ = make_node('~', $1, $2); }
111
+	;
112
+
113
+declaration_specifiers
114
+	: storage_class_specifier		{ $$ = $1; }
115
+	| storage_class_specifier declaration_specifiers { 
116
+                                                  $$ = make_node('~', $1, $2); }
117
+	| type_specifier	        	{ $$ = $1; }
118
+	| type_specifier declaration_specifiers { $$ = make_node('~', $1, $2); }
119
+	;
120
+
121
+init_declarator_list
122
+	: init_declarator		{ $$ = $1; }
123
+	| init_declarator_list ',' init_declarator { $$ = make_node(',', $1, $3); }
124
+	;
125
+
126
+init_declarator
127
+	: declarator		{ $$ = $1; }
128
+	| declarator '=' assignment_expression { $$ = make_node('=', $1, $3); }
129
+	;
130
+
131
+storage_class_specifier
132
+	: EXTERN	{ $$ = $1; }
133
+	| AUTO		{ $$ = $1; }
134
+	;
135
+
136
+type_specifier
137
+	: VOID		{ $$ = make_leaf(void_token); }
138
+	| INT		{ $$ = make_leaf(int_token); }
139
+	| FUNCTION	{ $$ = make_leaf(function_token); }
140
+	;
141
+
142
+declarator
143
+	: pointer direct_declarator	{ $$ = make_node('~', $1, $2); }
144
+	| direct_declarator		{ $$ = $1; }
145
+	;
146
+
147
+direct_declarator
148
+	: IDENTIFIER		{ $$ = make_leaf(lasttok); }
149
+	| '(' declarator ')'	{ $$ = $2; }
150
+        | direct_declarator '(' parameter_list ')' { $$ = make_node('F', $1, $3); }
151
+	| direct_declarator '(' identifier_list ')'{ $$ = make_node('F', $1, $3); }
152
+	| direct_declarator '(' ')'                { $$ = make_node('F', $1, NULL); }
153
+	;
154
+
155
+pointer
156
+	: '*'                   { $$ = (NODE*)1; }
157
+	| '*' pointer           { $$ = (NODE*)((int)$2+1); }
158
+	;
159
+
160
+parameter_list
161
+	: parameter_declaration		{ $$ = $1; }
162
+	| parameter_list ',' parameter_declaration { $$ = make_node(',', $1, $3); }
163
+	;
164
+
165
+parameter_declaration
166
+	: declaration_specifiers declarator { $$ = make_node('~', $1, $2); }
167
+	| declaration_specifiers abstract_declarator { $$ = make_node('~', $1, $2); }
168
+	| declaration_specifiers	{ $$ = $1; }
169
+	;
170
+
171
+identifier_list
172
+	: IDENTIFIER                    { $$ = make_leaf(lasttok); }
173
+	| identifier_list ',' IDENTIFIER {
174
+                                          $$ = make_node(',', $1,
175
+                                                              make_leaf(lasttok)); }
176
+	;
177
+
178
+abstract_declarator
179
+	: pointer		        { $$ = $1; }
180
+	| direct_abstract_declarator    { $$ = $1; }
181
+	| pointer direct_abstract_declarator { $$ = make_node('G', $1, $2); }
182
+	;
183
+
184
+direct_abstract_declarator
185
+	: '(' abstract_declarator ')'    { $$ = $2; }
186
+	| '(' ')'    { $$ = NULL; }
187
+	| '(' parameter_list ')'    { $$ = $2; }
188
+	| direct_abstract_declarator '(' ')'    { $$ = make_node(APPLY, $1, NULL); }
189
+	| direct_abstract_declarator '(' parameter_list ')'   { $$ = make_node(APPLY, $1, $3); }
190
+	;
191
+
192
+statement
193
+	: compound_statement		{ $$ = $1; }
194
+	| expression_statement		{ $$ = $1; }
195
+	| selection_statement		{ $$ = $1; }
196
+	| iteration_statement		{ $$ = $1; }
197
+	| jump_statement		{ $$ = $1; }
198
+	;
199
+
200
+compound_statement
201
+	: '{' '}'                       { $$ = NULL; }
202
+	| '{' statement_list '}'	{ $$ = $2; }
203
+	| '{' declaration_list '}'	{ $$ = $2; }
204
+	| '{' declaration_list statement_list '}' { $$ = make_node(';', $2, $3); }
205
+	;
206
+
207
+declaration_list
208
+	: declaration			{ $$ = $1; }
209
+	| declaration_list declaration { $$ = make_node(';', $1, $2); }
210
+	;
211
+
212
+statement_list
213
+	: statement			{ $$ = $1; }
214
+	| statement_list statement 	{ $$ = make_node(';', $1, $2); }
215
+	;
216
+
217
+expression_statement
218
+	: ';'				{ $$ = NULL; }
219
+	| expression ';'		{ $$ = $1; }
220
+	;
221
+
222
+selection_statement
223
+	: IF '(' expression ')' statement { $$ = make_node(IF, $3, $5); }
224
+	| IF '(' expression ')' statement ELSE statement
225
+                                          { $$ = make_node(IF, $3,
226
+                                                        make_node(ELSE, $5, $7)); }
227
+	;
228
+
229
+iteration_statement
230
+	: WHILE '(' expression ')' statement { $$ = make_node(WHILE, $3, $5); }
231
+	;
232
+
233
+jump_statement
234
+	: CONTINUE ';'                  { $$ = make_node(CONTINUE, NULL, NULL); }
235
+	| BREAK ';'                     { $$ = make_node(BREAK, NULL, NULL); }
236
+	| RETURN ';'	                { $$ = make_node(RETURN, NULL, NULL); }
237
+	| RETURN expression ';'		{ $$ = make_node(RETURN, $2, NULL); }
238
+	;
239
+
240
+translation_unit
241
+	: external_declaration		{ $$ = $1; }
242
+	| translation_unit external_declaration { $$ = make_node('~', $1, $2);}
243
+	;
244
+
245
+external_declaration
246
+	: function_definition            { $$ = $1; }
247
+	| declaration                    { $$ = $1; }
248
+	;
249
+
250
+function_definition
251
+	: declaration_specifiers declarator declaration_list compound_statement {
252
+          $$ = make_node('D', make_node('d', $1, make_node('e', $2, $3)), $4); }
253
+	| declaration_specifiers declarator compound_statement  {
254
+          $$ = make_node('D', make_node('d', $1, $2), $3); }
255
+	| declarator declaration_list compound_statement  {
256
+          $$ = make_node('D', make_node('d', $1, $2), $3); }
257
+	| declarator compound_statement { $$ = make_node('D', $1, $2); }
258
+        ;
259
+%%
260
+#include <stdio.h>
261
+
262
+extern char yytext[];
263
+extern int column;
264
+
265
+int yyerror(char *s)
266
+{
267
+	fflush(stdout);
268
+	printf("\n%*s\n%*s\n", column, "^", column, s);
269
+}
270
+

+ 28 - 0
cw/Makefile

@@ -0,0 +1,28 @@
1
+OBJS = lex.yy.o C.tab.o symbol_table.o nodes.o main.o list.o
2
+SRCS = lex.yy.c C.tab.c symbol_table.c nodes.c main.c list.c
3
+CC = gcc -Wall -Wextra -Wpedantic -g
4
+
5
+all:	mycc
6
+
7
+clean:
8
+	rm ${OBJS}
9
+
10
+mycc:	${OBJS}
11
+	${CC} -g -o mycc ${OBJS} 
12
+
13
+lex.yy.c: C.flex
14
+	flex C.flex
15
+
16
+C.tab.c:	C.y
17
+	bison -d -t -v C.y
18
+
19
+.c.o:
20
+	${CC} -g -c $*.c
21
+
22
+depend:	
23
+	${CC} -M $(SRCS) > .deps
24
+	cat Makefile .deps > makefile
25
+
26
+dist:	symbol_table.c nodes.c main.c Makefile C.flex C.y nodes.h token.h
27
+	tar cvfz mycc.tgz symbol_table.c nodes.c main.c Makefile C.flex C.y \
28
+		nodes.h token.h

+ 3 - 0
cw/README.md

@@ -0,0 +1,3 @@
1
+# mips-c-compiler
2
+
3
+A MIPS compiler for a subset of C that includes closures, for 3rd year compilers coursework

文件差異過大導致無法顯示
+ 1832 - 0
cw/lex.yy.c


+ 67 - 0
cw/list.c

@@ -0,0 +1,67 @@
1
+#include "list.h"
2
+#include <stdio.h>
3
+#include <stdlib.h>
4
+#include <string.h>
5
+
6
+BLIST* create_list(BIND *binding, BLIST *second) {
7
+  BLIST *head = (BLIST*) malloc(sizeof(BLIST));
8
+  if (head == NULL) {
9
+    perror("Failed to create list: ");
10
+    exit(1);
11
+  }
12
+  head->binding = binding;
13
+  head->next = second;
14
+  return head;
15
+}
16
+
17
+ENV* create_new_function_env(ENV* env) {
18
+  ENV* n_env = (ENV*) malloc(sizeof(ENV));
19
+  if (n_env == NULL) {
20
+    perror("Failed to create environment");
21
+    exit(1);
22
+  }
23
+  n_env->bindings = NULL;
24
+  n_env->parent = env;
25
+  return n_env;
26
+}
27
+
28
+BIND* create_binding(TOKEN* name, NODE* tree, ENV* env_ptr) {
29
+  BIND* n_bind = (BIND*) malloc(sizeof(BIND));
30
+  if (n_bind == NULL) {
31
+    perror("Failed to create binding: ");
32
+    exit(1);
33
+  }
34
+  n_bind->name = name;
35
+  n_bind->tree = tree;
36
+  n_bind->env  = env_ptr;
37
+
38
+  return n_bind;
39
+}
40
+
41
+void append_list(BLIST *head, BIND *binding) {
42
+  BLIST *ptr = head;
43
+  while (ptr->next != NULL) {
44
+    ptr = ptr->next;
45
+  }
46
+  ptr->next = create_list(binding, NULL);
47
+}
48
+
49
+BIND* find_name_in_list(TOKEN* name, BLIST *head) {
50
+  BLIST *ptr = head;
51
+  while (ptr != NULL) {
52
+    if (ptr->binding->name == name) {
53
+      return ptr->binding;
54
+    }
55
+    ptr = ptr->next;
56
+  }
57
+  return NULL;
58
+}
59
+
60
+  BIND* find_name_in_env(TOKEN* name, ENV* env) {
61
+    BIND* ptr = NULL;
62
+    ENV* env_ptr = env;
63
+    while (env_ptr != NULL && 
64
+        (ptr = find_name_in_list(name, env_ptr->bindings)) == NULL) env_ptr = env_ptr->parent;
65
+  return ptr;
66
+}
67
+

+ 12 - 0
cw/list.h

@@ -0,0 +1,12 @@
1
+#ifndef LIST_H
2
+#define LIST_H
3
+#include "types.h"
4
+
5
+BLIST* create_list(BIND*, BLIST*);
6
+BIND* create_binding(TOKEN*, NODE*, ENV*);
7
+void append_list(BLIST*, BIND*);
8
+BIND* find_name_in_list(TOKEN*, BLIST*);
9
+BIND* find_name_in_env(TOKEN*, ENV*);
10
+ENV* create_new_function_env(ENV*);
11
+#endif
12
+

+ 295 - 0
cw/main.c

@@ -0,0 +1,295 @@
1
+#include <stdio.h>
2
+#include <stdlib.h>
3
+#include <ctype.h>
4
+#include <string.h>
5
+#include "nodes.h"
6
+#include "C.tab.h"
7
+#include "types.h"
8
+#include "list.h"
9
+
10
+TOKEN* lookup_token(char *s);
11
+
12
+/*
13
+ * Existing problems/todo:
14
+ * return from control block, need a "return address" to jump to -- call levels
15
+ * --multiple assignments `int x,y,z = 1`--
16
+ * new block scope for if statements?
17
+ * arguments for functions
18
+ * difference between tilde and semicolon
19
+ * while loops
20
+ * control flow `continue` and `break` linked to return address sort of? call levels
21
+ */
22
+
23
+char *named(int t) {
24
+    static char b[100];
25
+    if (isgraph(t) || t==' ') {
26
+      sprintf(b, "%c", t);
27
+      return b;
28
+    }
29
+    switch (t) {
30
+      default: return "???";
31
+    case IDENTIFIER:
32
+      return "id";
33
+    case CONSTANT:
34
+      return "constant";
35
+    case STRING_LITERAL:
36
+      return "string";
37
+    case LE_OP:
38
+      return "<=";
39
+    case GE_OP:
40
+      return ">=";
41
+    case EQ_OP:
42
+      return "==";
43
+    case NE_OP:
44
+      return "!=";
45
+    case EXTERN:
46
+      return "extern";
47
+    case AUTO:
48
+      return "auto";
49
+    case INT:
50
+      return "int";
51
+    case VOID:
52
+      return "void";
53
+    case APPLY:
54
+      return "apply";
55
+    case LEAF:
56
+      return "leaf";
57
+    case IF:
58
+      return "if";
59
+    case ELSE:
60
+      return "else";
61
+    case WHILE:
62
+      return "while";
63
+    case CONTINUE:
64
+      return "continue";
65
+    case BREAK:
66
+      return "break";
67
+    case RETURN:
68
+      return "return";
69
+    }
70
+}
71
+
72
+
73
+
74
+void print_leaf(NODE *tree, int level) {
75
+    TOKEN *t = (TOKEN *)tree;
76
+    int i;
77
+    for (i=0; i<level; i++) putchar(' ');
78
+    if (t->type == CONSTANT) printf("%d\n", t->value);
79
+    else if (t->type == STRING_LITERAL) printf("\"%s\"\n", t->lexeme);
80
+    else if (t) puts(t->lexeme);
81
+}
82
+
83
+void print_tree0(NODE *tree, int level) {
84
+    int i;
85
+    if (tree==NULL) return;
86
+    if (tree->type==LEAF) {
87
+      print_leaf(tree->left, level);
88
+    }
89
+    else {
90
+      for(i=0; i<level; i++) putchar(' ');
91
+      printf("%s\n", named(tree->type));
92
+
93
+/*       if (tree->type=='~') { */
94
+/*         for(i=0; i<level+2; i++) putchar(' '); */
95
+/*         printf("%p\n", tree->left); */
96
+/*       } */
97
+/*       else */
98
+        print_tree0(tree->left, level+2);
99
+      print_tree0(tree->right, level+2);
100
+    }
101
+}
102
+
103
+// forward declare because it is used in add_var_to_env
104
+int recursive_interpret(NODE*, ENV*);
105
+
106
+void print_tree(NODE *tree) {
107
+    print_tree0(tree, 0);
108
+}
109
+
110
+void add_function_to_env(NODE *tree, ENV *env_ptr) {
111
+  BIND* existing;
112
+  NODE* func_name = tree->left->right->left->left;
113
+  TOKEN* name_token = (TOKEN*) func_name;
114
+  if ((existing = find_name_in_env(name_token, env_ptr)) == NULL) {
115
+    printf("Added function name %s to environment with value: \n", name_token->lexeme);
116
+    print_tree(tree);
117
+    if (env_ptr->bindings == NULL) {
118
+      env_ptr->bindings = create_list(create_binding(name_token, tree, env_ptr), NULL);
119
+    } else {
120
+      append_list(env_ptr->bindings, create_binding(name_token, tree, env_ptr));
121
+    }
122
+  } else {
123
+    printf("Updating function name %s with value: \n", name_token->lexeme);
124
+    print_tree(tree);
125
+    existing->tree = tree;
126
+    existing->env = env_ptr;
127
+  }
128
+}
129
+
130
+
131
+void add_var_to_env(NODE *tree, ENV *env_ptr) {
132
+  BIND* existing;
133
+  NODE* var_name = tree->left->left;
134
+  TOKEN* name_token = (TOKEN*) var_name;
135
+  TOKEN* tok = new_token(INT);
136
+  tok->value = recursive_interpret(tree->right, env_ptr);
137
+  asprintf(&tok->lexeme, "%d", tok->value);
138
+  if ((existing = find_name_in_env(name_token, env_ptr)) == NULL) {
139
+    printf("Added variable name %s to environment with value: %s\n", name_token->lexeme, tok->lexeme);
140
+    if (env_ptr->bindings == NULL) {
141
+      env_ptr->bindings = create_list(create_binding(name_token, (NODE*) tok, NULL), NULL);
142
+    } else {
143
+      append_list(env_ptr->bindings, create_binding(name_token, (NODE*) tok, NULL));
144
+    }
145
+  } else {
146
+    printf("Updating variable name %s with value: %s\n", name_token->lexeme, tok->lexeme);
147
+    existing->tree = (NODE *) tok;
148
+  } 
149
+}
150
+
151
+int recursive_interpret(NODE *tree, ENV *env_ptr) {
152
+  if (tree==NULL) return 0;
153
+  if (tree->type==LEAF) {
154
+    if (tree->left->type == CONSTANT) {
155
+      return ((TOKEN *) tree->left)->value;
156
+    } else if (tree->left->type == STRING_LITERAL) {
157
+      printf("Not implemented\n");
158
+      exit(1);
159
+    } else if (tree->left->type == INT || tree->left->type == FUNCTION) {
160
+      // do nothing we dont care about types
161
+      return 0;
162
+    } else {
163
+      // an identifier
164
+      TOKEN* tok = (TOKEN *) tree->left;
165
+      BIND* var_bind = find_name_in_env(tok, env_ptr);
166
+      if (var_bind == NULL) {
167
+        printf("Could not find variable %s\n", tok->lexeme);
168
+        exit(1);
169
+      }
170
+      if (var_bind->tree->type == INT) {
171
+        TOKEN* var_tok = (TOKEN *) var_bind->tree;
172
+        return var_tok->value;
173
+      } else {
174
+        printf("Maybe got a function?\n");
175
+        return 0;
176
+      }
177
+    }
178
+  }
179
+  if (tree->type=='D') {
180
+    // this is a function definition
181
+    add_function_to_env(tree, env_ptr);
182
+    return 0;
183
+  }
184
+  if (tree->type=='=') {
185
+    // this is a variable definition
186
+    add_var_to_env(tree, env_ptr);
187
+    return 0;
188
+  }
189
+  if (tree->type==APPLY) {
190
+    TOKEN* func_name = ((TOKEN*) tree->left->left);
191
+    BIND* func = find_name_in_env(func_name, env_ptr);
192
+    if (func == NULL) {
193
+      printf("Could not find binding for function with name %s\n", func_name->lexeme);
194
+      exit(1);
195
+    }
196
+    return recursive_interpret(func->tree->right, func->env);
197
+  }
198
+  if (tree->type == IF) {
199
+    if (recursive_interpret(tree->left, env_ptr) == 1) {
200
+      if (tree->right->type == ELSE) {
201
+        return recursive_interpret(tree->right->left, env_ptr);
202
+      } else {
203
+        return recursive_interpret(tree->right, env_ptr);
204
+      }
205
+    } else {
206
+      if (tree->right->type == ELSE) {
207
+        return recursive_interpret(tree->right->right, env_ptr);
208
+      }
209
+      return 0;
210
+    }
211
+  }
212
+  if (tree->type == LE_OP) {
213
+    return (int)recursive_interpret(tree->left, env_ptr) <= recursive_interpret(tree->right, env_ptr);
214
+  }
215
+  if (tree->type == GE_OP) {
216
+    return (int)recursive_interpret(tree->left, env_ptr) >= recursive_interpret(tree->right, env_ptr);
217
+  }
218
+  if (tree->type == EQ_OP) {
219
+    return (int)recursive_interpret(tree->left, env_ptr) == recursive_interpret(tree->right, env_ptr);
220
+  }
221
+  if (tree->type == NE_OP) {
222
+    return (int)recursive_interpret(tree->left, env_ptr) != recursive_interpret(tree->right, env_ptr);
223
+  }
224
+  if (tree->type == '>') {
225
+    return (int)recursive_interpret(tree->left, env_ptr) > recursive_interpret(tree->right, env_ptr);
226
+  }
227
+  if (tree->type == '<') {
228
+    return (int)recursive_interpret(tree->left, env_ptr) < recursive_interpret(tree->right, env_ptr);
229
+  }
230
+  if (tree->type == '+') {
231
+    return recursive_interpret(tree->left, env_ptr) + recursive_interpret(tree->right, env_ptr);
232
+  }
233
+  if (tree->type == '-') {
234
+    return recursive_interpret(tree->left, env_ptr) - recursive_interpret(tree->right, env_ptr);
235
+  }
236
+  if (tree->type == '*') {
237
+    return recursive_interpret(tree->left, env_ptr) * recursive_interpret(tree->right, env_ptr);
238
+  }
239
+  if (tree->type == '/') {
240
+    return recursive_interpret(tree->left, env_ptr) / recursive_interpret(tree->right, env_ptr);
241
+  }
242
+  if (tree->type == '%') {
243
+    return recursive_interpret(tree->left, env_ptr) % recursive_interpret(tree->right, env_ptr);
244
+  }
245
+  if (tree->type == '~') {
246
+    if (tree->left->type == INT || tree->left->type == FUNCTION) {
247
+      return recursive_interpret(tree->right, env_ptr);
248
+    } else {
249
+      recursive_interpret(tree->left, env_ptr);
250
+      return recursive_interpret(tree->right, env_ptr);
251
+    }
252
+  }
253
+  if (tree->type == RETURN) {
254
+    return recursive_interpret(tree->left, env_ptr);
255
+  }
256
+  recursive_interpret(tree->left, env_ptr);
257
+  return recursive_interpret(tree->right, env_ptr);
258
+}
259
+
260
+ENV* cons_global_env(NODE *tree) {
261
+  ENV* global = create_new_function_env(NULL);
262
+  recursive_interpret(tree, global);
263
+  return global;
264
+}
265
+
266
+void interpret_tree(NODE *tree) {
267
+  ENV* global_env = cons_global_env(tree);
268
+  BIND* ref_main = find_name_in_env(lookup_token("main"), global_env);
269
+  if (ref_main == NULL) {
270
+    printf("Could not find main, cannot run!\n");
271
+    exit(1);
272
+  }
273
+  // print ref_main to make sure we really got it
274
+  printf("Located %s, ready to run!\n", ref_main->name->lexeme);
275
+  printf("%d\n", recursive_interpret(ref_main->tree->right, ref_main->env));
276
+}
277
+
278
+extern int yydebug;
279
+extern NODE* yyparse(void);
280
+extern NODE* ans;
281
+extern void init_symbtable(void);
282
+
283
+int main(int argc, char** argv)
284
+{
285
+    NODE* tree;
286
+    if (argc>1 && strcmp(argv[1],"-d")==0) yydebug = 1;
287
+    init_symbtable();
288
+    printf("--C COMPILER\n");
289
+    yyparse();
290
+    tree = ans;
291
+    printf("parse finished\n");
292
+    print_tree(tree);
293
+    interpret_tree(tree);
294
+    return 0;
295
+}

+ 31 - 0
cw/nodes.c

@@ -0,0 +1,31 @@
1
+#include <stdio.h>
2
+#include <stdlib.h>
3
+#include "nodes.h"
4
+#include "C.tab.h"
5
+
6
+NODE* make_node(int t, NODE* left, NODE* right)
7
+{
8
+    NODE *a = (NODE*)malloc(sizeof(NODE));
9
+    if (a==NULL) {
10
+      perror("Cannot make node");
11
+      exit(1);
12
+    }
13
+    a->type = t;
14
+    a->left = left;
15
+    a->right = right;
16
+    return a;
17
+}
18
+
19
+NODE* make_leaf(TOKEN* l)
20
+{
21
+    NODE *a = (NODE*)malloc(sizeof(NODE));
22
+/*     printf("make_leaf: %p -> %p\n", l, a); */
23
+    if (a==NULL) {
24
+      perror("Cannot make leaf");
25
+      exit(1);
26
+    }
27
+    a->type = LEAF;
28
+    a->left = (NODE*)l;
29
+    a->right = NULL;
30
+    return a;
31
+}

+ 13 - 0
cw/nodes.h

@@ -0,0 +1,13 @@
1
+#ifndef NODES_H
2
+#define NODES_H
3
+#include "token.h"
4
+
5
+typedef struct node {
6
+  int          type;
7
+  struct node *left;
8
+  struct node *right;
9
+} NODE;
10
+
11
+NODE* make_leaf(TOKEN*);
12
+NODE* make_node(int, NODE*, NODE*);
13
+#endif

+ 11 - 0
cw/prog.c

@@ -0,0 +1,11 @@
1
+int main() {
2
+  int a = 1;
3
+  int d = 1;
4
+
5
+  return 1;
6
+}
7
+
8
+int other_f() {
9
+  int b = 2;
10
+  return 2;
11
+}

+ 9 - 0
cw/simple.c

@@ -0,0 +1,9 @@
1
+int main() {
2
+
3
+  int foo = 1 + 4;
4
+  int bar = 2 + foo;
5
+
6
+  int baz = foo + bar;
7
+
8
+  return baz;
9
+}

+ 58 - 0
cw/symbol_table.c

@@ -0,0 +1,58 @@
1
+/*
2
+ * Adapted from 
3
+ * CM20029 Coursework Assignment 1
4
+ * Tom Crick
5
+ * cs1tc@bath.ac.uk
6
+ * 30 Apr 2003
7
+ *
8
+ * symbol_table.c
9
+ */
10
+
11
+#include <stdio.h>
12
+#include <stdlib.h>
13
+#include <string.h>
14
+#include "token.h"
15
+#include "C.tab.h"
16
+
17
+static TOKEN** symbtable;
18
+#define HASH_SIZE (1000)
19
+TOKEN *int_token, *void_token, *function_token;
20
+
21
+void init_symbtable(void)
22
+{
23
+    symbtable = (TOKEN**)calloc(HASH_SIZE, sizeof(TOKEN*));
24
+    int_token = new_token(INT);
25
+    int_token->lexeme = "int";
26
+    function_token = new_token(FUNCTION);
27
+    function_token->lexeme = "function";
28
+    void_token = new_token(VOID);
29
+    void_token->lexeme = "void";
30
+}
31
+
32
+int hash(char *s)
33
+{
34
+    int h = 0;
35
+    while (*s != '\0') {
36
+      h = (h<<4) ^ *s++;
37
+    }
38
+    return (0x7fffffff&h) % HASH_SIZE;
39
+}
40
+
41
+TOKEN* lookup_token(char *s)
42
+{
43
+    int	h = hash(s);
44
+    TOKEN *a = symbtable[h];
45
+    TOKEN *ans;
46
+/*     printf("\nLookup: %s\n", s); */
47
+    while (a!=NULL) {
48
+      if (strcmp(a->lexeme, s)==0) return a;
49
+      a = a->next;
50
+    }
51
+    ans = new_token(IDENTIFIER);
52
+    ans->lexeme = (char*)malloc(1+strlen(s));
53
+    strcpy(ans->lexeme, s);
54
+    ans->next = symbtable[h];
55
+    symbtable[h] = ans;
56
+/*     printf(" stored at %p\n", ans); */
57
+    return ans;
58
+}

+ 18 - 0
cw/token.h

@@ -0,0 +1,18 @@
1
+#ifndef __TOKEN_H
2
+#define __TOKEN_H
3
+
4
+#define TRUE 1
5
+#define FALSE 0
6
+#define TEST_MODE 0
7
+
8
+typedef struct TOKEN
9
+{
10
+  int           type;
11
+  char          *lexeme;
12
+  int           value;
13
+  struct TOKEN  *next;
14
+} TOKEN;
15
+
16
+extern TOKEN* new_token(int);
17
+
18
+#endif

+ 21 - 0
cw/types.h

@@ -0,0 +1,21 @@
1
+#ifndef TYPES_H
2
+#define TYPES_H
3
+#include "nodes.h"
4
+
5
+typedef struct binding {
6
+  TOKEN* name;
7
+  NODE* tree;
8
+  struct environ *env;
9
+} BIND;
10
+
11
+typedef struct blist {
12
+  BIND* binding;
13
+  struct blist *next;
14
+} BLIST;
15
+
16
+typedef struct environ {
17
+  BLIST *bindings;
18
+  struct environ *parent;
19
+} ENV;
20
+
21
+#endif

+ 0 - 1
tac

@@ -1 +0,0 @@
1
-Subproject commit c853190fe5ac63dc0c95ff62146b750e1f116d8b

+ 2 - 0
tac/.gitignore

@@ -0,0 +1,2 @@
1
+*.o
2
+mycc

+ 144 - 0
tac/C.flex

@@ -0,0 +1,144 @@
1
+D			[0-9]
2
+L			[a-zA-Z_]
3
+H			[a-fA-F0-9]
4
+E			[Ee][+-]?{D}+
5
+FS			(f|F|l|L)
6
+IS			(u|U|l|L)*
7
+
8
+%{
9
+#pragma GCC diagnostic ignored "-Wall"
10
+#pragma GCC diagnostic ignored "-Wextra"
11
+#pragma GCC diagnostic ignored "-Wconversion"
12
+#pragma GCC diagnostic ignored "-Wpedantic"
13
+#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
14
+#include <stdio.h>
15
+#include "C.tab.h"
16
+#include <string.h>
17
+#include <stdlib.h>
18
+#include "token.h"
19
+TOKEN* make_string(char*);
20
+extern TOKEN* lookup_token(char*);
21
+TOKEN* make_int(char*);
22
+TOKEN* lasttok;
23
+
24
+void count(void);
25
+void comment(void);
26
+%}
27
+
28
+%%
29
+"/*"			{ comment(); }
30
+
31
+"auto"			{ count(); return(AUTO); }
32
+"break"			{ count(); return(BREAK); }
33
+"continue"		{ count(); return(CONTINUE); }
34
+"else"			{ count(); return(ELSE); }
35
+"extern"		{ count(); return(EXTERN); }
36
+"if"			{ count(); return(IF); }
37
+"int"			{ count(); return(INT); }
38
+"function"		{ count(); return(FUNCTION); }
39
+"return"		{ count(); return(RETURN); }
40
+"void"			{ count(); return(VOID); }
41
+"while"			{ count(); return(WHILE); }
42
+
43
+{L}({L}|{D})*		{ count(); lasttok = lookup_token(yytext);
44
+                          return(IDENTIFIER); }
45
+
46
+{D}+{IS}?		{ count(); lasttok = make_int(yytext);return(CONSTANT); }
47
+L?'(\\.|[^\\'])+'	{ count(); lasttok = make_int(yytext);return(CONSTANT); }
48
+
49
+L?\"(\\.|[^\\"])*\"	{ count(); lasttok = make_string(yytext);
50
+                          return(STRING_LITERAL); }
51
+
52
+"<="			{ count(); return(LE_OP); }
53
+">="			{ count(); return(GE_OP); }
54
+"=="			{ count(); return(EQ_OP); }
55
+"!="			{ count(); return(NE_OP); }
56
+";"			{ count(); return(';'); }
57
+"{"     		{ count(); return('{'); }
58
+"}"     		{ count(); return('}'); }
59
+","			{ count(); return(','); }
60
+":"			{ count(); return(':'); }
61
+"="			{ count(); return('='); }
62
+"("			{ count(); return('('); }
63
+")"			{ count(); return(')'); }
64
+"!"			{ count(); return('!'); }
65
+"-"			{ count(); return('-'); }
66
+"+"			{ count(); return('+'); }
67
+"*"			{ count(); return('*'); }
68
+"/"			{ count(); return('/'); }
69
+"%"			{ count(); return('%'); }
70
+"<"			{ count(); return('<'); }
71
+">"			{ count(); return('>'); }
72
+
73
+[ \t\v\n\f]		{ count(); }
74
+.			{ /* ignore bad characters */ }
75
+
76
+%%
77
+
78
+int yywrap(void)
79
+{
80
+	return(1);
81
+}
82
+
83
+
84
+void comment(void)
85
+{
86
+	char c, c1;
87
+
88
+loop:
89
+	while ((c = input()) != '*' && c != 0)
90
+		putchar(c);
91
+
92
+	if ((c1 = input()) != '/' && c != 0)
93
+	{
94
+		unput(c1);
95
+		goto loop;
96
+	}
97
+
98
+	if (c != 0)
99
+		putchar(c1);
100
+}
101
+
102
+
103
+int column = 0;
104
+
105
+void count()
106
+{
107
+	int i;
108
+
109
+	for (i = 0; yytext[i] != '\0'; i++)
110
+		if (yytext[i] == '\n')
111
+			column = 0;
112
+		else if (yytext[i] == '\t')
113
+			column += 8 - (column % 8);
114
+		else
115
+			column++;
116
+
117
+	ECHO;
118
+}
119
+
120
+
121
+TOKEN *new_token(int type)
122
+{
123
+    TOKEN *ans = (TOKEN*)malloc(sizeof(TOKEN));
124
+    ans->type = type;
125
+    return ans;
126
+}
127
+
128
+TOKEN *make_string(char *s)
129
+{
130
+    TOKEN *ans = new_token(STRING_LITERAL);
131
+    int len = strlen(s);
132
+    ans->lexeme = (char*)calloc(1, len-1);
133
+    strncpy(ans->lexeme, s+1, len-2);
134
+    return ans;
135
+}
136
+
137
+TOKEN *make_int(char *s)
138
+{
139
+    int n = *s!='\'' ? atoi(s) : *(s+1);
140
+    TOKEN *ans = new_token(CONSTANT);
141
+    ans->value = n;
142
+    asprintf(&ans->lexeme, "%d", n);
143
+    return ans;
144
+}

文件差異過大導致無法顯示
+ 2551 - 0
tac/C.output


文件差異過大導致無法顯示
+ 2297 - 0
tac/C.tab.c


+ 83 - 0
tac/C.tab.h

@@ -0,0 +1,83 @@
1
+/* A Bison parser, made by GNU Bison 3.0.4.  */
2
+
3
+/* Bison interface for Yacc-like parsers in C
4
+
5
+   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
6
+
7
+   This program is free software: you can redistribute it and/or modify
8
+   it under the terms of the GNU General Public License as published by
9
+   the Free Software Foundation, either version 3 of the License, or
10
+   (at your option) any later version.
11
+
12
+   This program is distributed in the hope that it will be useful,
13
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+   GNU General Public License for more details.
16
+
17
+   You should have received a copy of the GNU General Public License
18
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
+
20
+/* As a special exception, you may create a larger work that contains
21
+   part or all of the Bison parser skeleton and distribute that work
22
+   under terms of your choice, so long as that work isn't itself a
23
+   parser generator using the skeleton or a modified version thereof
24
+   as a parser skeleton.  Alternatively, if you modify or redistribute
25
+   the parser skeleton itself, you may (at your option) remove this
26
+   special exception, which will cause the skeleton and the resulting
27
+   Bison output files to be licensed under the GNU General Public
28
+   License without this special exception.
29
+
30
+   This special exception was added by the Free Software Foundation in
31
+   version 2.2 of Bison.  */
32
+
33
+#ifndef YY_YY_C_TAB_H_INCLUDED
34
+# define YY_YY_C_TAB_H_INCLUDED
35
+/* Debug traces.  */
36
+#ifndef YYDEBUG
37
+# define YYDEBUG 1
38
+#endif
39
+#if YYDEBUG
40
+extern int yydebug;
41
+#endif
42
+
43
+/* Token type.  */
44
+#ifndef YYTOKENTYPE
45
+# define YYTOKENTYPE
46
+  enum yytokentype
47
+  {
48
+    IDENTIFIER = 258,
49
+    CONSTANT = 259,
50
+    STRING_LITERAL = 260,
51
+    LE_OP = 261,
52
+    GE_OP = 262,
53
+    EQ_OP = 263,
54
+    NE_OP = 264,
55
+    EXTERN = 265,
56
+    AUTO = 266,
57
+    INT = 267,
58
+    VOID = 268,
59
+    FUNCTION = 269,
60
+    APPLY = 270,
61
+    LEAF = 271,
62
+    IF = 272,
63
+    ELSE = 273,
64
+    WHILE = 274,
65
+    CONTINUE = 275,
66
+    BREAK = 276,
67
+    RETURN = 277
68
+  };
69
+#endif
70
+
71
+/* Value type.  */
72
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
73
+typedef int YYSTYPE;
74
+# define YYSTYPE_IS_TRIVIAL 1
75
+# define YYSTYPE_IS_DECLARED 1
76
+#endif
77
+
78
+
79
+extern YYSTYPE yylval;
80
+
81
+int yyparse (void);
82
+
83
+#endif /* !YY_YY_C_TAB_H_INCLUDED  */

+ 275 - 0
tac/C.y

@@ -0,0 +1,275 @@
1
+%{
2
+#pragma GCC diagnostic ignored "-Wall"
3
+#pragma GCC diagnostic ignored "-Wconversion"
4
+#pragma GCC diagnostic ignored "-Wpedantic"
5
+#pragma GCC diagnostic ignored "-Wextra"
6
+#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
7
+#include "nodes.h"
8
+#define YYSTYPE NODE*
9
+#define YYDEBUG 1
10
+extern TOKEN *int_token, *void_token, *function_token, *lasttok;
11
+NODE *ans;
12
+%}
13
+
14
+%token IDENTIFIER CONSTANT STRING_LITERAL
15
+%token LE_OP GE_OP EQ_OP NE_OP
16
+
17
+%token EXTERN AUTO
18
+%token INT VOID FUNCTION
19
+%token APPLY LEAF
20
+
21
+%token  IF ELSE WHILE CONTINUE BREAK RETURN
22
+
23
+%start goal
24
+%%
25
+
26
+goal    :  translation_unit { ans = $$ = $1;}
27
+        ;
28
+
29
+primary_expression
30
+	: IDENTIFIER 			{ $$ = make_leaf(lasttok); }
31
+	| CONSTANT 			{ $$ = make_leaf(lasttok); }
32
+	| STRING_LITERAL 		{ $$ = make_leaf(lasttok); }
33
+	| '(' expression ')' 		{ $$ = $2; }
34
+	;
35
+
36
+postfix_expression
37
+	: primary_expression		{ $$ = $1; }
38
+	| postfix_expression '(' ')'    { $$ = make_node(APPLY, $1, NULL); }
39
+	| postfix_expression '(' argument_expression_list ')' {
40
+				          $$ = make_node(APPLY, $1, $3); }
41
+	;
42
+
43
+argument_expression_list
44
+	: assignment_expression		{ $$ = $1; }
45
+	| argument_expression_list ',' assignment_expression {
46
+          $$ = make_node(',', $1, $3); }
47
+	;
48
+
49
+unary_expression
50
+	: postfix_expression		{ $$ = $1; }
51
+	| unary_operator unary_expression { $$ = make_node((int)$1, $2, NULL); }
52
+	;
53
+
54
+unary_operator
55
+	: '&'		{ $$ = $1; }
56
+	| '*'		{ $$ = $1; }
57
+	| '+'		{ $$ = $1; }
58
+	| '-'		{ $$ = $1; }
59
+	| '!'		{ $$ = $1; }
60
+	;
61
+
62
+multiplicative_expression
63
+	: unary_expression		{ $$ = $1; }
64
+	| multiplicative_expression '*' unary_expression {
65
+                                          $$ = make_node('*', $1, $3); }
66
+	| multiplicative_expression '/' unary_expression {
67
+                                          $$ = make_node('/', $1, $3); }
68
+	| multiplicative_expression '%' unary_expression {
69
+                                          $$ = make_node('%', $1, $3); }
70
+	;
71
+
72
+additive_expression
73
+	: multiplicative_expression		{ $$ = $1; }
74
+	| additive_expression '+' multiplicative_expression {
75
+                                          $$ = make_node('+', $1, $3); }
76
+	| additive_expression '-' multiplicative_expression {
77
+                                          $$ = make_node('-', $1, $3); }
78
+	;
79
+
80
+relational_expression
81
+	: additive_expression		{ $$ = $1; }
82
+	| relational_expression '<' additive_expression	{
83
+                                          $$ = make_node('<', $1, $3); }
84
+	| relational_expression '>' additive_expression {
85
+                                          $$ = make_node('>', $1, $3); }
86
+	| relational_expression LE_OP additive_expression {
87
+                                          $$ = make_node(LE_OP, $1, $3); }
88
+	| relational_expression GE_OP additive_expression {
89
+                                          $$ = make_node(GE_OP, $1, $3); }
90
+	;
91
+
92
+equality_expression
93
+	: relational_expression		{ $$ = $1; }
94
+	| equality_expression EQ_OP relational_expression {
95
+                                          $$ = make_node(EQ_OP, $1, $3); }
96
+	| equality_expression NE_OP relational_expression {
97
+                                          $$ = make_node(NE_OP, $1, $3); }
98
+	;
99
+
100
+assignment_expression
101
+	: equality_expression		{ $$ = $1; }
102
+	| unary_expression '=' assignment_expression {
103
+                                          $$ = make_node('=', $1, $3); }
104
+	;
105
+
106
+expression
107
+	: assignment_expression		{ $$ = $1; }
108
+	| expression ',' assignment_expression { $$ = make_node(',', $1, $3); }
109
+	;
110
+
111
+declaration
112
+	: declaration_specifiers ';'		{ $$ = $1; }
113
+	| function_definition			{ $$ = $1; }
114
+	| declaration_specifiers init_declarator_list ';' {
115
+                                                  $$ = make_node('~', $1, $2); }
116
+	;
117
+
118
+declaration_specifiers
119
+	: storage_class_specifier		{ $$ = $1; }
120
+	| storage_class_specifier declaration_specifiers { 
121
+                                                  $$ = make_node('~', $1, $2); }
122
+	| type_specifier	        	{ $$ = $1; }
123
+	| type_specifier declaration_specifiers { $$ = make_node('~', $1, $2); }
124
+	;
125
+
126
+init_declarator_list
127
+	: init_declarator		{ $$ = $1; }
128
+	| init_declarator_list ',' init_declarator { $$ = make_node(',', $1, $3); }
129
+	;
130
+
131
+init_declarator
132
+	: declarator		{ $$ = $1; }
133
+	| declarator '=' assignment_expression { $$ = make_node('=', $1, $3); }
134
+	;
135
+
136
+storage_class_specifier
137
+	: EXTERN	{ $$ = $1; }
138
+	| AUTO		{ $$ = $1; }
139
+	;
140
+
141
+type_specifier
142
+	: VOID		{ $$ = make_leaf(void_token); }
143
+	| INT		{ $$ = make_leaf(int_token); }
144
+	| FUNCTION	{ $$ = make_leaf(function_token); }
145
+	;
146
+
147
+declarator
148
+	: pointer direct_declarator	{ $$ = make_node('~', $1, $2); }
149
+	| direct_declarator		{ $$ = $1; }
150
+	;
151
+
152
+direct_declarator
153
+	: IDENTIFIER		{ $$ = make_leaf(lasttok); }
154
+	| '(' declarator ')'	{ $$ = $2; }
155
+        | direct_declarator '(' parameter_list ')' { $$ = make_node('F', $1, $3); }
156
+	| direct_declarator '(' identifier_list ')'{ $$ = make_node('F', $1, $3); }
157
+	| direct_declarator '(' ')'                { $$ = make_node('F', $1, NULL); }
158
+	;
159
+
160
+pointer
161
+	: '*'                   { $$ = (NODE*)1; }
162
+	| '*' pointer           { $$ = (NODE*)((int)$2+1); }
163
+	;
164
+
165
+parameter_list
166
+	: parameter_declaration		{ $$ = $1; }
167
+	| parameter_list ',' parameter_declaration { $$ = make_node(',', $1, $3); }
168
+	;
169
+
170
+parameter_declaration
171
+	: declaration_specifiers declarator { $$ = make_node('~', $1, $2); }
172
+	| declaration_specifiers abstract_declarator { $$ = make_node('~', $1, $2); }
173
+	| declaration_specifiers	{ $$ = $1; }
174
+	;
175
+
176
+identifier_list
177
+	: IDENTIFIER                    { $$ = make_leaf(lasttok); }
178
+	| identifier_list ',' IDENTIFIER {
179
+                                          $$ = make_node(',', $1,
180
+                                                              make_leaf(lasttok)); }
181
+	;
182
+
183
+abstract_declarator
184
+	: pointer		        { $$ = $1; }
185
+	| direct_abstract_declarator    { $$ = $1; }
186
+	| pointer direct_abstract_declarator { $$ = make_node('G', $1, $2); }
187
+	;
188
+
189
+direct_abstract_declarator
190
+	: '(' abstract_declarator ')'    { $$ = $2; }
191
+	| '(' ')'    { $$ = NULL; }
192
+	| '(' parameter_list ')'    { $$ = $2; }
193
+	| direct_abstract_declarator '(' ')'    { $$ = make_node(APPLY, $1, NULL); }
194
+	| direct_abstract_declarator '(' parameter_list ')'   { $$ = make_node(APPLY, $1, $3); }
195
+	;
196
+
197
+statement
198
+	: compound_statement		{ $$ = $1; }
199
+	| expression_statement		{ $$ = $1; }
200
+	| selection_statement		{ $$ = $1; }
201
+	| iteration_statement		{ $$ = $1; }
202
+	| jump_statement		{ $$ = $1; }
203
+	;
204
+
205
+compound_statement
206
+	: '{' '}'                       { $$ = NULL; }
207
+	| '{' statement_list '}'	{ $$ = $2; }
208
+	| '{' declaration_list '}'	{ $$ = $2; }
209
+	| '{' declaration_list statement_list '}' { $$ = make_node(';', $2, $3); }
210
+	;
211
+
212
+declaration_list
213
+	: declaration			{ $$ = $1; }
214
+	| declaration_list declaration { $$ = make_node(';', $1, $2); }
215
+	;
216
+
217
+statement_list
218
+	: statement			{ $$ = $1; }
219
+	| statement_list statement 	{ $$ = make_node(';', $1, $2); }
220
+	;
221
+
222
+expression_statement
223
+	: ';'				{ $$ = NULL; }
224
+	| expression ';'		{ $$ = $1; }
225
+	;
226
+
227
+selection_statement
228
+	: IF '(' expression ')' statement { $$ = make_node(IF, $3, $5); }
229
+	| IF '(' expression ')' statement ELSE statement
230
+                                          { $$ = make_node(IF, $3,
231
+                                                        make_node(ELSE, $5, $7)); }
232
+	;
233
+
234
+iteration_statement
235
+	: WHILE '(' expression ')' statement { $$ = make_node(WHILE, $3, $5); }
236
+	;
237
+
238
+jump_statement
239
+	: CONTINUE ';'                  { $$ = make_node(CONTINUE, NULL, NULL); }
240
+	| BREAK ';'                     { $$ = make_node(BREAK, NULL, NULL); }
241
+	| RETURN ';'	                { $$ = make_node(RETURN, NULL, NULL); }
242
+	| RETURN expression ';'		{ $$ = make_node(RETURN, $2, NULL); }
243
+	;
244
+
245
+translation_unit
246
+	: external_declaration		{ $$ = $1; }
247
+	| translation_unit external_declaration { $$ = make_node('~', $1, $2);}
248
+	;
249
+
250
+external_declaration
251
+	: function_definition            { $$ = $1; }
252
+	| declaration                    { $$ = $1; }
253
+	;
254
+
255
+function_definition
256
+	: declaration_specifiers declarator declaration_list compound_statement {
257
+          $$ = make_node('D', make_node('d', $1, make_node('e', $2, $3)), $4); }
258
+	| declaration_specifiers declarator compound_statement  {
259
+          $$ = make_node('D', make_node('d', $1, $2), $3); }
260
+	| declarator declaration_list compound_statement  {
261
+          $$ = make_node('D', make_node('d', $1, $2), $3); }
262
+	| declarator compound_statement { $$ = make_node('D', $1, $2); }
263
+        ;
264
+%%
265
+#include <stdio.h>
266
+
267
+extern char yytext[];
268
+extern int column;
269
+
270
+int yyerror(char *s)
271
+{
272
+	fflush(stdout);
273
+	printf("\n%*s\n%*s\n", column, "^", column, s);
274
+}
275
+

+ 30 - 0
tac/Makefile

@@ -0,0 +1,30 @@
1
+CFLAGS := -g -std=gnu11
2
+OBJS := lex.yy.o C.tab.o symbol_table.o nodes.o main.o list.o
3
+SRCS := lex.yy.c C.tab.c symbol_table.c nodes.c main.c list.c
4
+CC := gcc
5
+
6
+all:	mycc
7
+
8
+clean:
9
+	rm -f ${OBJS}
10
+	rm -f C.tab.c lex.yy.c
11
+
12
+mycc:	${OBJS}
13
+	${CC} ${CFLAGS} -o mycc ${OBJS} 
14
+
15
+lex.yy.c: C.flex
16
+	flex C.flex
17
+
18
+C.tab.c:	C.y
19
+	bison -d -t C.y
20
+
21
+.c.o:
22
+	${CC} ${CFLAGS} -c $*.c
23
+
24
+depend:	
25
+	${CC} ${CFLAGS} -M $(SRCS) > .deps
26
+	cat Makefile .deps > makefile
27
+
28
+dist:	symbol_table.c nodes.c main.c Makefile C.flex C.y nodes.h token.h
29
+	tar cvfz mycc.tgz symbol_table.c nodes.c main.c Makefile C.flex C.y \
30
+		nodes.h token.h

+ 3 - 0
tac/README.md

@@ -0,0 +1,3 @@
1
+# mips-c-compiler
2
+
3
+A MIPS compiler for a subset of C that includes closures, for 3rd year compilers coursework

文件差異過大導致無法顯示
+ 2086 - 0
tac/lex.yy.c


+ 142 - 0
tac/list.c

@@ -0,0 +1,142 @@
1
+#include "list.h"
2
+#include <stdio.h>
3
+#include <stdlib.h>
4
+#include <string.h>
5
+
6
+typedef void* any_t;
7
+
8
+typedef struct list_t {
9
+  any_t elem;
10
+  struct list_t *next;
11
+} LIST_T;
12
+
13
+LIST_T* new_list(any_t element) {
14
+
15
+  LIST_T *head = (LIST_T *) malloc(sizeof(LIST_T));
16
+  if (head == NULL) {
17
+    perror("failed to create list: ");
18
+    exit(1);
19
+  }
20
+  head->elem = element;
21
+  head->next = NULL;
22
+  return head;
23
+}
24
+
25
+void push_list(LIST_T **head, any_t element) {
26
+  LIST_T* n_head = (LIST_T *) malloc(sizeof(LIST_T));
27
+  if (n_head == NULL) perror("failed to allocate new element: ");
28
+  n_head->elem = element;
29
+  n_head->next = *head;
30
+  *head = n_head;
31
+}
32
+
33
+void append_to_list(LIST_T *head, any_t element) {
34
+  LIST_T* ptr = head;
35
+  LIST_T* tail = (LIST_T *) malloc(sizeof(LIST_T));
36
+  if (tail == NULL) perror("failed to allocate new element: ");
37
+  while (ptr->next != NULL) ptr = ptr->next;
38
+  tail->elem = element;
39
+  tail->next = NULL;
40
+  ptr->next = tail;
41
+}
42
+
43
+BLIST* create_list(BIND *binding, BLIST *second) {
44
+  BLIST *head = (BLIST*) malloc(sizeof(BLIST));
45
+  if (head == NULL) {
46
+    perror("Failed to create list: ");
47
+    exit(1);
48
+  }
49
+  head->binding = binding;
50
+  head->next = second;
51
+  return head;
52
+}
53
+
54
+ENV* create_new_function_env(ENV* env) {
55
+  ENV* n_env = (ENV*) malloc(sizeof(ENV));
56
+  if (n_env == NULL) {
57
+    perror("Failed to create environment");
58
+    exit(1);
59
+  }
60
+  n_env->bindings = NULL;
61
+  n_env->parent = env;
62
+  return n_env;
63
+}
64
+
65
+BIND* create_binding(char* name, NODE* tree, ENV* env_ptr) {
66
+  BIND* n_bind = (BIND*) malloc(sizeof(BIND));
67
+  if (n_bind == NULL) {
68
+    perror("Failed to create binding: ");
69
+    exit(1);
70
+  }
71
+  n_bind->name = name;
72
+  n_bind->tree = tree;
73
+  n_bind->env  = env_ptr;
74
+
75
+  return n_bind;
76
+}
77
+
78
+void append_list(BLIST *head, BIND *binding) {
79
+  BLIST *ptr = head;
80
+  while (ptr->next != NULL) {
81
+    ptr = ptr->next;
82
+  }
83
+  ptr->next = create_list(binding, NULL);
84
+}
85
+
86
+BIND* find_name_in_list(char* name, BLIST *head) {
87
+  BLIST *ptr = head;
88
+  while (ptr != NULL) {
89
+    if (strcmp(ptr->binding->name, name) == 0) {
90
+      return ptr->binding;
91
+    }
92
+    ptr = ptr->next;
93
+  }
94
+  return NULL;
95
+}
96
+
97
+  BIND* find_name_in_env(char* name, ENV* env) {
98
+    BIND* ptr = NULL;
99
+    ENV* env_ptr = env;
100
+    while (env_ptr != NULL && 
101
+        (ptr = find_name_in_list(name, env_ptr->bindings)) == NULL) env_ptr = env_ptr->parent;
102
+  return ptr;
103
+}
104
+
105
+TLIST* new_tac_list(TAC_T* elem, TLIST* second) {
106
+  TLIST *head = (TLIST*) malloc(sizeof(TLIST));
107
+  if (head == NULL) {
108
+    perror("Failed to create list: ");
109
+    exit(1);
110
+  }
111
+  head->elem = elem;
112
+  head->next = second;
113
+  return head;
114
+}
115
+
116
+TAC_T* create_tac(int op, TOKEN* src, TOKEN* tgt, TOKEN* dst) {
117
+  TAC_T* new_t = (TAC_T*) malloc(sizeof(TAC_T));
118
+  if (new_t == NULL) {
119
+    perror("Failed to create tac: ");
120
+    exit(1);
121
+  }
122
+  new_t->op  = op;
123
+  new_t->src = src;
124
+  new_t->tgt = tgt;
125
+  new_t->dst = dst;
126
+  return new_t;
127
+}
128
+
129
+void add_tac(TLIST *head, int op, TOKEN* src, TOKEN* tgt, TOKEN* dst) {
130
+  TLIST *ptr = head;
131
+  while (ptr->next != NULL) {
132
+    ptr = ptr->next;
133
+  }
134
+  ptr->next = (TLIST*) malloc(sizeof(TLIST));
135
+  if (ptr->next == NULL) {
136
+    perror("Failed to create new tac_element: ");
137
+    exit(1);
138
+  }
139
+  ptr->next->elem = create_tac(op, src, tgt, dst);
140
+  ptr->next->next = NULL;
141
+}
142
+

+ 15 - 0
tac/list.h

@@ -0,0 +1,15 @@
1
+#ifndef LIST_H
2
+#define LIST_H
3
+#include "types.h"
4
+
5
+BLIST* create_list(BIND*, BLIST*);
6
+BIND* create_binding(char*, NODE*, ENV*);
7
+void append_list(BLIST*, BIND*);
8
+BIND* find_name_in_list(char*, BLIST*);
9
+BIND* find_name_in_env(char*, ENV*);
10
+ENV* create_new_function_env(ENV*);
11
+void add_tac(TLIST*, int, TOKEN*, TOKEN*, TOKEN*);
12
+TAC_T* create_tac(int, TOKEN*, TOKEN*, TOKEN*);
13
+TLIST* new_tac_list(TAC_T*, TLIST*);
14
+#endif
15
+

+ 375 - 0
tac/main.c

@@ -0,0 +1,375 @@
1
+#include <stdio.h>
2
+#include <stdlib.h>
3
+#include <ctype.h>
4
+#include <string.h>
5
+#include "nodes.h"
6
+#include "C.tab.h"
7
+#include "types.h"
8
+#include "list.h"
9
+
10
+int asprintf(char **strp, const char *fmt, ...);
11
+extern TOKEN* lookup_token(char*);
12
+
13
+/*
14
+ * Existing problems/todo:
15
+ * return from control block, need a "return address" to jump to -- call levels
16
+ * --multiple assignments `int x,y,z = 1`--
17
+ * new block scope for if statements?
18
+ * arguments for functions
19
+ * difference between tilde and semicolon
20
+ * while loops
21
+ * control flow `continue` and `break` linked to return address sort of? call levels
22
+ */
23
+
24
+TOKEN* gen_tmp(void) {
25
+  char* tmp;
26
+  static char letter = 'a';
27
+  static char num = 0;
28
+  if (num == 100) {
29
+    num = 0;
30
+    if (++letter == 'r') letter++;
31
+  }
32
+  if (letter == '{') exit(1);
33
+  asprintf(&tmp, "\\%c%d", letter, num);
34
+  num++;
35
+  return lookup_token(tmp);
36
+}
37
+
38
+char *named(int t)
39
+{
40
+    static char b[100];
41
+    if (isgraph(t) || t==' ') {
42
+      sprintf(b, "%c", t);
43
+      return b;
44
+    }
45
+    switch (t) {
46
+      default: return "???";
47
+    case IDENTIFIER:
48
+      return "id";
49
+    case CONSTANT:
50
+      return "constant";
51
+    case STRING_LITERAL:
52
+      return "string";
53
+    case LE_OP:
54
+      return "<=";
55
+    case GE_OP:
56
+      return ">=";
57
+    case EQ_OP:
58
+      return "==";
59
+    case NE_OP:
60
+      return "!=";
61
+    case EXTERN:
62
+      return "extern";
63
+    case AUTO:
64
+      return "auto";
65
+    case INT:
66
+      return "int";
67
+    case VOID:
68
+      return "void";
69
+    case APPLY:
70
+      return "apply";
71
+    case LEAF:
72
+      return "leaf";
73
+    case IF:
74
+      return "if";
75
+    case ELSE:
76
+      return "else";
77
+    case WHILE:
78
+      return "while";
79
+    case CONTINUE:
80
+      return "continue";
81
+    case BREAK:
82
+      return "break";
83
+    case RETURN:
84
+      return "return";
85
+    }
86
+}
87
+
88
+
89
+
90
+void print_leaf(NODE *tree, int level)
91
+{
92
+    TOKEN *t = (TOKEN *)tree;
93
+    int i;
94
+    for (i=0; i<level; i++) putchar(' ');
95
+    if (t->type == CONSTANT) printf("%d\n", t->value);
96
+    else if (t->type == STRING_LITERAL) printf("\"%s\"\n", t->lexeme);
97
+    else if (t) puts(t->lexeme);
98
+}
99
+
100
+void print_tree0(NODE *tree, int level)
101
+{
102
+    int i;
103
+    if (tree==NULL) return;
104
+    if (tree->type==LEAF) {
105
+      print_leaf(tree->left, level);
106
+    }
107
+    else {
108
+      for(i=0; i<level; i++) putchar(' ');
109
+      printf("%s\n", named(tree->type));
110
+
111
+/*       if (tree->type=='~') { */
112
+/*         for(i=0; i<level+2; i++) putchar(' '); */
113
+/*         printf("%p\n", tree->left); */
114
+/*       } */
115
+/*       else */
116
+        print_tree0(tree->left, level+2);
117
+      print_tree0(tree->right, level+2);
118
+    }
119
+}
120
+
121
+void print_tree(NODE *tree)
122
+{
123
+    print_tree0(tree, 0);
124
+}
125
+
126
+// void add_function_to_env(NODE *tree, ENV *env_ptr) {
127
+//   BIND* existing;
128
+//   NODE* func_name = tree->left->right->left->left;
129
+//   TOKEN* name_token = (TOKEN*) func_name;
130
+//   if ((existing = find_name_in_env(name_token->lexeme, env_ptr)) == NULL) {
131
+//     printf("Added function name %s to environment with value: \n", name_token->lexeme);
132
+//     print_tree(tree);
133
+//     if (env_ptr->bindings == NULL) {
134
+//       env_ptr->bindings = create_list(create_binding(name_token->lexeme, tree, env_ptr), NULL);
135
+//     } else {
136
+//       append_list(env_ptr->bindings, create_binding(name_token->lexeme, tree, env_ptr));
137
+//     }
138
+//   } else {
139
+//     printf("Updating function name %s with value: \n", name_token->lexeme);
140
+//     print_tree(tree);
141
+//     existing->tree = tree;
142
+//     existing->env = env_ptr;
143
+//   }
144
+// }
145
+
146
+
147
+// void add_var_to_env(NODE *tree, ENV *env_ptr) {
148
+//   BIND* existing;
149
+//   NODE* var_name = tree->left->left;
150
+//   TOKEN* name_token = (TOKEN*) var_name;
151
+//   TOKEN* tok = new_token(INT);
152
+//   tok->value = recursive_interpret(tree->right, env_ptr);
153
+//   asprintf(&tok->lexeme, "%d", tok->value);
154
+//   if ((existing = find_name_in_env(name_token->lexeme, env_ptr)) == NULL) {
155
+//     printf("Added variable name %s to environment with value: %s\n", name_token->lexeme, tok->lexeme);
156
+//     if (env_ptr->bindings == NULL) {
157
+//       env_ptr->bindings = create_list(create_binding(name_token->lexeme, (NODE*) tok, NULL), NULL);
158
+//     } else {
159
+//       append_list(env_ptr->bindings, create_binding(name_token->lexeme, (NODE*) tok, NULL));
160
+//     }
161
+//   } else {
162
+//     printf("Updating variable name %s with value: %s\n", name_token->lexeme, tok->lexeme);
163
+//     existing->tree = (NODE *) tok;
164
+//   } 
165
+// }
166
+
167
+void new_tac(TACS* tacs, TOKEN* dst, TOKEN* src, TOKEN* tgt, int op) {
168
+  if (tacs->list == NULL) {
169
+    TAC_T* tac;
170
+    tac = create_tac(op, src, tgt, dst);
171
+    tacs->list = new_tac_list(tac, NULL);
172
+  } else {
173
+    add_tac(tacs->list, op, src, tgt, dst);
174
+  }
175
+}
176
+
177
+char* stok(TOKEN* tok) {
178
+  return tok->lexeme;
179
+}
180
+
181
+void print_tac(TLIST* tac_list) {
182
+  TLIST *ptr = tac_list;
183
+
184
+  while (ptr != NULL) {
185
+    int op = ptr->elem->op;
186
+    if (op == '=') printf("%s := %s\n", stok(ptr->elem->dst), stok(ptr->elem->src));
187
+    if (op == '+') printf("%s := %s + %s\n", stok(ptr->elem->dst), stok(ptr->elem->src), stok(ptr->elem->tgt));
188
+    if (op == '-') printf("%s := %s - %s\n", stok(ptr->elem->dst), stok(ptr->elem->src), stok(ptr->elem->tgt));
189
+    if (op == '/') printf("%s := %s / %s\n", stok(ptr->elem->dst), stok(ptr->elem->src), stok(ptr->elem->tgt));
190
+    if (op == '*') printf("%s := %s * %s\n", stok(ptr->elem->dst), stok(ptr->elem->src), stok(ptr->elem->tgt));
191
+    if (op == '%') printf("%s := %s %% %s\n", stok(ptr->elem->dst), stok(ptr->elem->src), stok(ptr->elem->tgt));
192
+    if (op == RETURN) printf("ret %s\n", stok(ptr->elem->src));
193
+    ptr = ptr->next;
194
+  }
195
+}
196
+
197
+TOKEN* build_tac(NODE *tree, TACS* tac) {
198
+  if (tree == NULL) return NULL;
199
+  int type = tree->type;
200
+  if (type == LEAF) {
201
+    return (TOKEN *) tree->left;
202
+  } else if (type == '=') {
203
+    TOKEN* dst = (TOKEN*) tree->left->left;
204
+    TOKEN* result = build_tac(tree->right, tac);
205
+    new_tac(tac, dst, result, NULL, tree->type);
206
+  } else if (type=='+' || type=='-' || type=='*' || type=='/' || type =='%') {
207
+    TOKEN* dst = gen_tmp();
208
+    TOKEN* src = build_tac(tree->left, tac);
209
+    TOKEN* tgt = build_tac(tree->right, tac);
210
+    new_tac(tac, dst, src, tgt, tree->type);
211
+    return dst;
212
+  } else if (type == RETURN) {
213
+    TOKEN* src = build_tac(tree->left, tac);
214
+    new_tac(tac, NULL, src, NULL, RETURN);
215
+  } else {
216
+    build_tac(tree->left, tac);
217
+    build_tac(tree->right, tac);
218
+  }
219
+}
220
+
221
+
222
+int tmp_regs[10] = {8, 9, 10, 11, 12, 13, 14, 15, 24, 25};
223
+int svd_regs[8]  = {16, 17, 18, 19, 20, 21, 22, 23};
224
+int tmp_cntr = 0;
225
+VARLOC** vartab;
226
+
227
+int is_imm(TOKEN *t) {
228
+  if (t->type==CONSTANT) return 1;
229
+  else return 0;
230
+}
231
+
232
+int find_var_idx(TOKEN* var) {
233
+  int i;
234
+  for (i = 0; i < 8; i++) { 
235
+    if (vartab[i]->var == var) {
236
+      return vartab[i]->loc_idx;
237
+    }
238
+  }
239
+  return -1;
240
+}
241
+
242
+int store_var(TOKEN* name) {
243
+  int i;
244
+  for (i = 0; i < 8; i++) {
245
+    if (vartab[i]->var == NULL) {
246
+      vartab[i]->var = name;
247
+      vartab[i]->loc_idx = svd_regs[i];
248
+      return vartab[i]->loc_idx;
249
+    } else if (name == vartab[i]->var) {
250
+      vartab[i]->loc_idx = svd_regs[i];
251
+      return svd_regs[i];
252
+    }
253
+  }
254
+  printf("bugger\n");
255
+  exit(1);
256
+}
257
+
258
+void init_reg() {
259
+  int i;
260
+  vartab = (VARLOC**) malloc(8 * sizeof(VARLOC*));
261
+  for (i = 0; i < 8; i++) {
262
+    vartab[i] = (VARLOC*) malloc(sizeof(VARLOC));
263
+    vartab[i]->var = NULL;
264
+    vartab[i]->loc_idx = -1;
265
+  }
266
+}
267
+
268
+int alloc_register(TOKEN* val) {
269
+  int idx;
270
+  int imm = is_imm(val);
271
+  if (imm) {
272
+    if (val->value <= 32767 && val->value >= -32767) {
273
+      printf("ori $%d, $0, %d\n", tmp_regs[tmp_cntr], val->value);
274
+      idx = tmp_regs[tmp_cntr++];
275
+    } else {
276
+      printf("li $%d, %d\n", tmp_regs[tmp_cntr], val->value);
277
+      idx = tmp_regs[tmp_cntr++];
278
+    }
279
+  } else {
280
+    idx = find_var_idx(val);
281
+  }
282
+  if (tmp_cntr == 10) tmp_cntr = 0;
283
+  return idx;
284
+}
285
+
286
+void compile_tac(TLIST* tacs) {
287
+  printf("=====\n");
288
+  printf("main:\n");
289
+  init_reg();
290
+  while(tacs != NULL) {
291
+    TAC_T* t = tacs->elem;
292
+    if (t->op == '=') {
293
+      int src_idx = alloc_register(t->src);
294
+      printf("or $%d, $0, $%d\n", store_var(t->dst), src_idx);
295
+    }
296
+    if (t->op == '+') {
297
+      int tgt_idx = alloc_register(t->tgt);
298
+      int src_idx = alloc_register(t->src);
299
+      printf("add $%d, $%d, $%d\n", store_var(t->dst), src_idx, tgt_idx);
300
+    }
301
+    if (t->op == '-') {
302
+      int tgt_idx = alloc_register(t->tgt);
303
+      int src_idx = alloc_register(t->src);
304
+      printf("sub $%d, $%d, $%d\n", store_var(t->dst), src_idx, tgt_idx);
305
+    }
306
+    if (t->op == '*') {
307
+      int tgt_idx = alloc_register(t->tgt);
308
+      int src_idx = alloc_register(t->src);
309
+      printf("mult $%d, $%d\n", src_idx, tgt_idx);
310
+      printf("mflo $%d\n", store_var(t->dst));
311
+    }
312
+    if (t->op == '/') {
313
+      int tgt_idx = alloc_register(t->tgt);
314
+      int src_idx = alloc_register(t->src);
315
+      printf("div $%d, $%d\n", src_idx, tgt_idx);
316
+      printf("mflo $%d\n", store_var(t->dst));
317
+    }
318
+    if (t->op == '%') {
319
+      int tgt_idx = alloc_register(t->tgt);
320
+      int src_idx = alloc_register(t->src);
321
+      printf("div $%d, $%d\n", src_idx, tgt_idx);
322
+      printf("mfhi $%d\n", store_var(t->dst));
323
+    }
324
+    if (t->op == RETURN) {
325
+      int src_idx = alloc_register(t->src);
326
+      printf("or $k0, $0, $%d\n", src_idx);
327
+    }
328
+    tacs = tacs->next;
329
+  }
330
+  printf("ori $v0, 10\n");
331
+  printf("syscall\n");
332
+}
333
+
334
+// ENV* cons_global_env(NODE *tree) {
335
+//   ENV* global = create_new_function_env(NULL);
336
+//   recursive_interpret(tree, global);
337
+//   return global;
338
+// }
339
+
340
+void interpret_tree(NODE *tree) {
341
+  // ENV* global_env = cons_global_env(tree);
342
+  // BIND* ref_main = find_name_in_env("main", global_env);
343
+  // if (ref_main == NULL) {
344
+  //   printf("Could not find main, cannot run!\n");
345
+  //   exit(1);
346
+  // }
347
+  // print ref_main to make sure we really got it
348
+  // printf("Located %s, ready to run!\n", ref_main->name);
349
+  // printf("%d\n", recursive_interpret(ref_main->tree->right, ref_main->env));
350
+  TACS* gen_tac = (TACS*) malloc(sizeof(TACS));
351
+  build_tac(tree, gen_tac);
352
+  print_tac(gen_tac->list);
353
+  compile_tac(gen_tac->list);
354
+}
355
+
356
+extern int yydebug;
357
+/* extern NODE* yyparse(void); */
358
+extern NODE* ans;
359
+extern void init_symbtable(void);
360
+
361
+int main(int argc, char** argv)
362
+{
363
+    NODE* tree;
364
+    if (argc>1 && strcmp(argv[1],"-d")==0) yydebug = 1;
365
+    init_symbtable();
366
+    printf("--C COMPILER\n");
367
+    yyparse();
368
+    tree = ans;
369
+    printf("parse finished\n");
370
+    print_tree(tree);
371
+    interpret_tree(tree);
372
+    // int i;
373
+    // for (i = 0; i < 2600; i++) printf("%s\n", gen_tmp());
374
+    return 0;
375
+}

+ 31 - 0
tac/nodes.c

@@ -0,0 +1,31 @@
1
+#include <stdio.h>
2
+#include <stdlib.h>
3
+#include "nodes.h"
4
+#include "C.tab.h"
5
+
6
+NODE* make_node(int t, NODE* left, NODE* right)
7
+{
8
+    NODE *a = (NODE*)malloc(sizeof(NODE));
9
+    if (a==NULL) {
10
+      perror("Cannot make node");
11
+      exit(1);
12
+    }
13
+    a->type = t;
14
+    a->left = left;
15
+    a->right = right;
16
+    return a;
17
+}
18
+
19
+NODE* make_leaf(TOKEN* l)
20
+{
21
+    NODE *a = (NODE*)malloc(sizeof(NODE));
22
+/*     printf("make_leaf: %p -> %p\n", l, a); */
23
+    if (a==NULL) {
24
+      perror("Cannot make leaf");
25
+      exit(1);
26
+    }
27
+    a->type = LEAF;
28
+    a->left = (NODE*)l;
29
+    a->right = NULL;
30
+    return a;
31
+}

+ 13 - 0
tac/nodes.h

@@ -0,0 +1,13 @@
1
+#ifndef NODES_H
2
+#define NODES_H
3
+#include "token.h"
4
+
5
+typedef struct node {
6
+  int          type;
7
+  struct node *left;
8
+  struct node *right;
9
+} NODE;
10
+
11
+NODE* make_leaf(TOKEN*);
12
+NODE* make_node(int, NODE*, NODE*);
13
+#endif

+ 11 - 0
tac/prog.c

@@ -0,0 +1,11 @@
1
+int main() {
2
+  int a = 1;
3
+  int d = 1;
4
+
5
+  return 1;
6
+}
7
+
8
+int other_f() {
9
+  int b = 2;
10
+  return 2;
11
+}

+ 6 - 0
tac/simple.c

@@ -0,0 +1,6 @@
1
+int main() {
2
+  int z = 5;
3
+  int y = 5 + 2;
4
+  int x = 5 + y * z;
5
+  return x;
6
+}

+ 58 - 0
tac/symbol_table.c

@@ -0,0 +1,58 @@
1
+/*
2
+ * Adapted from 
3
+ * CM20029 Coursework Assignment 1
4
+ * Tom Crick
5
+ * cs1tc@bath.ac.uk
6
+ * 30 Apr 2003
7
+ *
8
+ * symbol_table.c
9
+ */
10
+
11
+#include <stdio.h>
12
+#include <stdlib.h>
13
+#include <string.h>
14
+#include "token.h"
15
+#include "C.tab.h"
16
+
17
+static TOKEN** symbtable;
18
+#define HASH_SIZE (1000)
19
+TOKEN *int_token, *void_token, *function_token;
20
+
21
+void init_symbtable(void)
22
+{
23
+    symbtable = (TOKEN**)calloc(HASH_SIZE, sizeof(TOKEN*));
24
+    int_token = new_token(INT);
25
+    int_token->lexeme = "int";
26
+    function_token = new_token(FUNCTION);
27
+    function_token->lexeme = "function";
28
+    void_token = new_token(VOID);
29
+    void_token->lexeme = "void";
30
+}
31
+
32
+int hash(char *s)
33
+{
34
+    int h = 0;
35
+    while (*s != '\0') {
36
+      h = (h<<4) ^ *s++;
37
+    }
38
+    return (0x7fffffff&h) % HASH_SIZE;
39
+}
40
+
41
+TOKEN* lookup_token(char *s)
42
+{
43
+    int	h = hash(s);
44
+    TOKEN *a = symbtable[h];
45
+    TOKEN *ans;
46
+/*     printf("\nLookup: %s\n", s); */
47
+    while (a!=NULL) {
48
+      if (strcmp(a->lexeme, s)==0) return a;
49
+      a = a->next;
50
+    }
51
+    ans = new_token(IDENTIFIER);
52
+    ans->lexeme = (char*)malloc(1+strlen(s));
53
+    strcpy(ans->lexeme, s);
54
+    ans->next = symbtable[h];
55
+    symbtable[h] = ans;
56
+/*     printf(" stored at %p\n", ans); */
57
+    return ans;
58
+}

+ 18 - 0
tac/test.asm

@@ -0,0 +1,18 @@
1
+main:
2
+ori $8, $0, 2
3
+li $9, 48282
4
+add $19, $9, $8
5
+ori $10, $0, 2
6
+mult $19, $10
7
+mflo $20
8
+ori $11, $0, 2
9
+ori $12, $0, 4
10
+div $12, $11
11
+mflo $21
12
+ori $13, $0, 5
13
+div $13, $21
14
+mfhi $22
15
+sub $23, $20, $22
16
+or $k0, $0, $23
17
+ori $v0, 10
18
+syscall

+ 18 - 0
tac/token.h

@@ -0,0 +1,18 @@
1
+#ifndef __TOKEN_H
2
+#define __TOKEN_H
3
+
4
+#define TRUE 1
5
+#define FALSE 0
6
+#define TEST_MODE 0
7
+
8
+typedef struct TOKEN
9
+{
10
+  int           type;
11
+  char          *lexeme;
12
+  int           value;
13
+  struct TOKEN  *next;
14
+} TOKEN;
15
+
16
+extern TOKEN* new_token(int);
17
+
18
+#endif

+ 47 - 0
tac/types.h

@@ -0,0 +1,47 @@
1
+#ifndef TYPES_H
2
+#define TYPES_H
3
+#include "nodes.h"
4
+
5
+typedef struct binding {
6
+  char* name;
7
+  NODE* tree;
8
+  struct environ *env;
9
+} BIND;
10
+
11
+typedef struct blist {
12
+  BIND* binding;
13
+  struct blist *next;
14
+} BLIST;
15
+
16
+typedef struct environ {
17
+  BLIST *bindings;
18
+  struct environ *parent;
19
+} ENV;
20
+
21
+typedef struct tac_elem {
22
+  TOKEN* src;
23
+  TOKEN* dst;
24
+  TOKEN* tgt;
25
+  int op;
26
+} TAC_T;
27
+
28
+typedef struct tac_list {
29
+  TAC_T* elem;
30
+  struct tac_list* next;
31
+} TLIST;
32
+
33
+typedef struct tacs {
34
+  TLIST* list;
35
+} TACS;
36
+
37
+typedef struct reg {
38
+  int num;
39
+  int stored;
40
+} REG;
41
+
42
+typedef struct varloc {
43
+  TOKEN* var;
44
+  int loc_idx;
45
+} VARLOC;
46
+
47
+#endif