├── .gitignore ├── lab1 ├── Makefile ├── hello_world.c ├── hello_world.h ├── linked_list.c ├── linked_list.h ├── ll_test.py └── main.c ├── lab2 ├── calc │ ├── Makefile │ ├── lex.l │ └── quiz.txt ├── ipaddr │ ├── Makefile │ ├── data.pickle │ ├── ip_test.py │ ├── lex.l │ └── readme.txt └── wc │ ├── Makefile │ ├── inferno3.txt │ └── lex.l ├── lab3 ├── Makefile ├── calc_test.py ├── lex.l └── syntax.y ├── lab5 ├── Makefile ├── lex.l ├── quiz.txt └── syntax.y ├── lab7 ├── Makefile ├── symtab_bt.c ├── symtab_ht.c ├── symtab_ll.c └── test.py ├── lab9 ├── Makefile ├── expr_test.py ├── lex.l ├── stack.c └── syntax.y ├── project1 ├── Makefile └── test │ ├── test_1_o01.out │ ├── test_1_o01.spl │ ├── test_1_o02.spl │ ├── test_1_o03.spl │ ├── test_1_r01.out │ ├── test_1_r01.spl │ ├── test_1_r02.out │ ├── test_1_r02.spl │ ├── test_1_r03.out │ ├── test_1_r03.spl │ ├── test_1_r04.out │ ├── test_1_r04.spl │ ├── test_1_r05.spl │ ├── test_1_r06.spl │ ├── test_1_r07.spl │ ├── test_1_r08.spl │ ├── test_1_r09.spl │ └── test_1_r10.spl ├── project2 ├── Makefile └── test │ ├── test_2_o01.spl │ ├── test_2_o02.spl │ ├── test_2_r01.spl │ ├── test_2_r02.spl │ ├── test_2_r03.spl │ ├── test_2_r04.spl │ ├── test_2_r05.spl │ ├── test_2_r06.spl │ ├── test_2_r07.spl │ ├── test_2_r08.spl │ ├── test_2_r09.spl │ ├── test_2_r10.spl │ ├── test_2_r11.spl │ ├── test_2_r12.spl │ ├── test_2_r13.spl │ ├── test_2_r14.spl │ └── test_2_r15.spl ├── project3 ├── Makefile ├── sample │ ├── test01.ir │ ├── test01.spl │ ├── test02.ir │ ├── test02.spl │ ├── test03.ir │ ├── test03.spl │ ├── test04.ir │ └── test04.spl └── test │ ├── test_3_b01.spl │ ├── test_3_b02.spl │ ├── test_3_b03.spl │ ├── test_3_b04.spl │ ├── test_3_b05.spl │ ├── test_3_r01.spl │ ├── test_3_r02.spl │ ├── test_3_r03.spl │ ├── test_3_r04.spl │ ├── test_3_r05.spl │ ├── test_3_r06.spl │ ├── test_3_r07.spl │ ├── test_3_r08.spl │ ├── test_3_r09.spl │ └── test_3_r10.spl ├── project4 ├── Makefile ├── main.c ├── mips32.c ├── mips32.h ├── sample │ ├── test_4_fact.ir │ ├── test_4_fact.s │ └── test_4_fact.spl ├── tac.c ├── tac.h └── test │ ├── test_4_r01.ir │ ├── test_4_r01.spl │ ├── test_4_r02.ir │ ├── test_4_r02.spl │ ├── test_4_r03.ir │ └── test_4_r03.spl ├── semantic.txt ├── syntax.txt └── token.txt /.gitignore: -------------------------------------------------------------------------------- 1 | *.out 2 | *.swp 3 | *.so 4 | *.bak 5 | peda-session-* 6 | .gdb_history 7 | lex.yy.c 8 | syntax.tab.[hc] 9 | bin 10 | !*/test/*.out 11 | -------------------------------------------------------------------------------- /lab1/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=-I. 3 | 4 | hello: 5 | $(CC) hello_world.c -o hello.out 6 | main: 7 | $(CC) linked_list.c main.c -o ll_main.out 8 | libll: 9 | $(CC) linked_list.c --shared -fPIC -o libll.so 10 | clean: 11 | @rm -f a.out hello.out ll_main.out 12 | .PHONY: hello main 13 | 14 | -------------------------------------------------------------------------------- /lab1/hello_world.c: -------------------------------------------------------------------------------- 1 | #include "hello_world.h" 2 | 3 | void say_hello_world(){ 4 | printf("hello wolrd!\n"); 5 | } 6 | 7 | int main(void){ 8 | say_hello_world(); 9 | return 0; 10 | } 11 | 12 | -------------------------------------------------------------------------------- /lab1/hello_world.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void say_hello_world(); 4 | 5 | -------------------------------------------------------------------------------- /lab1/linked_list.c: -------------------------------------------------------------------------------- 1 | #include "linked_list.h" 2 | 3 | node *linked_list_init(){ 4 | node *head = (node*)malloc(sizeof(node)); 5 | head->count = 0; 6 | head->next = NULL; 7 | return head; 8 | } 9 | 10 | void linked_list_free(node *head){ 11 | node *cur = head; 12 | node *last; 13 | while(cur != NULL){ 14 | last = cur; 15 | cur = cur->next; 16 | free(last); 17 | } 18 | } 19 | 20 | char linked_list_string[0x10000]; 21 | 22 | char *linked_list_tostring(node *head){ 23 | node *cur = head->next; 24 | char *position; 25 | int length = 0; 26 | while(cur != NULL){ 27 | position = linked_list_string + length; 28 | length += sprintf(position, "%d", cur->value); 29 | cur = cur->next; 30 | if(cur != NULL){ 31 | position = linked_list_string + length; 32 | length += sprintf(position, "->"); 33 | } 34 | } 35 | position = linked_list_string + length; 36 | length += sprintf(position, "%c", '\0'); 37 | return linked_list_string; 38 | } 39 | 40 | int linked_list_size(node *head){ 41 | return head->count; 42 | } 43 | 44 | void linked_list_append(node *head, int val){ 45 | node *cur = head; 46 | node *new_node; 47 | while(cur->next != NULL){ 48 | cur = cur->next; 49 | } 50 | new_node = (node*)malloc(sizeof(node)); 51 | new_node->value = val; 52 | new_node->next = NULL; 53 | cur->next = new_node; 54 | head->count++; 55 | } 56 | 57 | /* your implementation goes here */ 58 | 59 | -------------------------------------------------------------------------------- /lab1/linked_list.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | typedef struct node { 5 | union { 6 | int count; 7 | int value; 8 | }; 9 | struct node *next; 10 | } node; 11 | 12 | /* initialize a linked list, head node is special */ 13 | node *linked_list_init(); 14 | 15 | /* destroy a linked list, free spaces */ 16 | void linked_list_free(node *head); 17 | 18 | /* display elements in the linked list */ 19 | char *linked_list_tostring(node *head); 20 | 21 | /* get the length of the linked list */ 22 | int linked_list_size(node *head); 23 | 24 | /* insert val at the last of the linked list */ 25 | void linked_list_append(node *head, int val); 26 | 27 | /* 28 | * You should implement functions according to the follow function 29 | * declarations. One thing to note that, the parameter *index* 30 | * refers to the position of value node, i.e., index 0 corresponds 31 | * to the next node of the header node. 32 | * 33 | * In case of out-of-bound index, your code should do nothing in all 34 | * functions. As for remove, if the value doesn't exist, do nothing. 35 | * 36 | * For get, if index out of bound, return INT_MIN. 37 | * For search, if value not exists. return -1. 38 | * For search_all, if value not exists, return empty list. 39 | */ 40 | 41 | /* insert val at position index */ 42 | void linked_list_insert(node *head, int val, int index); 43 | 44 | /* delete node at position index */ 45 | void linked_list_delete(node *head, int index); 46 | 47 | /* remove the first occurence node of val */ 48 | void linked_list_remove(node *head, int val); 49 | 50 | /* remove all occurences of val */ 51 | void linked_list_remove_all(node *head, int val); 52 | 53 | /* get value at position index */ 54 | int linked_list_get(node *head, int index); 55 | 56 | /* search the first index of val */ 57 | int linked_list_search(node *head, int val); 58 | 59 | /* search all indexes of val */ 60 | node *linked_list_search_all(node *head, int val); 61 | 62 | -------------------------------------------------------------------------------- /lab1/ll_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # encoding: utf-8 3 | 4 | import ctypes 5 | import os 6 | import unittest 7 | 8 | class LinkedList(ctypes.Structure): 9 | cwd = os.getcwd() 10 | lib_path = os.path.join(cwd, 'libll.so') 11 | lib = ctypes.CDLL(lib_path) 12 | def __init__(self, head=0): 13 | self.lib.linked_list_tostring.restype = ctypes.c_char_p 14 | self.lib.linked_list_init.restype = ctypes.POINTER(LinkedList) 15 | self.lib.linked_list_search_all.restype = ctypes.POINTER(LinkedList) 16 | if head == 0: 17 | self.head = self.lib.linked_list_init() 18 | else: 19 | self.head = head 20 | 21 | def __del__(self): 22 | self.lib.linked_list_free(self.head) 23 | 24 | def __str__(self): 25 | addr = self.lib.linked_list_tostring(self.head) 26 | raw = ctypes.cast(addr, ctypes.c_char_p).value 27 | return raw.decode() 28 | 29 | def size(self): 30 | return self.lib.linked_list_size(self.head) 31 | 32 | def append(self, val): 33 | self.lib.linked_list_append(self.head, val) 34 | 35 | def insert(self, val, index): 36 | self.lib.linked_list_insert(self.head, val, index) 37 | 38 | def delete(self, index): 39 | self.lib.linked_list_delete(self.head, index) 40 | 41 | def remove(self, val): 42 | self.lib.linked_list_remove(self.head, val) 43 | 44 | def remove_all(self, val): 45 | self.lib.linked_list_remove_all(self.head, val) 46 | 47 | def get(self, index): 48 | return self.lib.linked_list_get(self.head, index) 49 | 50 | def search(self, val): 51 | return self.lib.linked_list_search(self.head, val) 52 | 53 | def search_all(self, val): 54 | ptr = self.lib.linked_list_search_all(self.head, val) 55 | return LinkedList(ptr) 56 | 57 | 58 | class LinkedListTest(unittest.TestCase): 59 | def test_basic(self): 60 | ll = LinkedList() 61 | ll.append(10) 62 | ll.append(20) 63 | self.assertEqual(str(ll), '10->20') 64 | self.assertEqual(ll.size(), 2) 65 | 66 | def test_insert(self): 67 | ll = LinkedList() 68 | ll.append(1) 69 | ll.append(2) 70 | ll.append(3) 71 | ll.insert(5, 2) 72 | ll.insert(6, 2) 73 | self.assertEqual(str(ll), '1->2->6->5->3') 74 | ll.insert(999, 999) 75 | self.assertEqual(ll.size(), 5) 76 | self.assertEqual(str(ll), '1->2->6->5->3') 77 | 78 | def test_delete(self): 79 | ll = LinkedList() 80 | ll.append(9) 81 | ll.append(6) 82 | ll.append(3) 83 | ll.append(0) 84 | ll.delete(2) 85 | self.assertEqual(str(ll), '9->6->0') 86 | ll.delete(-1) 87 | self.assertEqual(str(ll), '9->6->0') 88 | ll.delete(3) 89 | self.assertEqual(ll.size(), 3) 90 | 91 | def test_remove(self): 92 | ll = LinkedList() 93 | ll.append(1) 94 | ll.append(1) 95 | ll.append(1) 96 | ll.append(2) 97 | ll.append(3) 98 | ll.append(3) 99 | ll.append(2) 100 | self.assertEqual(str(ll), '1->1->1->2->3->3->2') 101 | ll.remove(2) 102 | self.assertEqual(str(ll), '1->1->1->3->3->2') 103 | ll.remove(2) 104 | self.assertEqual(str(ll), '1->1->1->3->3') 105 | ll.remove(-1) 106 | self.assertEqual(str(ll), '1->1->1->3->3') 107 | 108 | def test_remove_all(self): 109 | ll = LinkedList() 110 | ll.append(1) 111 | ll.append(2) 112 | for _ in range(100): 113 | ll.append(3) 114 | self.assertEqual(ll.size(), 102) 115 | ll.append(5) 116 | ll.remove_all(3) 117 | self.assertEqual(str(ll), '1->2->5') 118 | 119 | def test_get(self): 120 | ll = LinkedList() 121 | for i in range(100): 122 | ll.append(i) 123 | for i in range(200): 124 | val = ll.get(i) 125 | if i < 100: 126 | self.assertTrue(val == i) 127 | else: 128 | self.assertEqual(val, -0x80000000) 129 | 130 | def test_search(self): 131 | ll = LinkedList() 132 | for i in range(10): 133 | ll.append(i) 134 | for i in range(10): 135 | ll.append(i) 136 | for i in range(10): 137 | idx = ll.search(i) 138 | self.assertTrue(idx == i) 139 | self.assertEqual(ll.search(10), -1) 140 | 141 | def test_search_all(self): 142 | ll = LinkedList() 143 | for i in range(10): 144 | ll.append(i) 145 | for i in range(10): 146 | ll.append(9-i) 147 | ret = ll.search_all(7) 148 | self.assertEqual(str(ret), '7->12') 149 | ret = ll.search_all(101) 150 | self.assertEqual(ret.size(), 0) 151 | 152 | 153 | 154 | unittest.main() 155 | 156 | -------------------------------------------------------------------------------- /lab1/main.c: -------------------------------------------------------------------------------- 1 | #include "linked_list.h" 2 | 3 | int main(void){ 4 | node *head = linked_list_init(); 5 | char *string; 6 | printf("%d\n", linked_list_size(head)); 7 | linked_list_append(head, 1); 8 | linked_list_append(head, 3); 9 | linked_list_append(head, 7); 10 | string = linked_list_tostring(head); 11 | puts(string); 12 | linked_list_append(head, 101); 13 | string = linked_list_tostring(head); 14 | puts(string); 15 | printf("%d\n", linked_list_size(head)); 16 | linked_list_free(head); 17 | return 0; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /lab2/calc/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | FLEX=flex 3 | calc: 4 | $(FLEX) lex.l 5 | $(CC) lex.yy.c -lfl -o calc.out 6 | clean: 7 | @rm -f lex.yy.c *.out 8 | .PHONY: calc 9 | -------------------------------------------------------------------------------- /lab2/calc/lex.l: -------------------------------------------------------------------------------- 1 | %{ 2 | %} 3 | %% 4 | . { putchar(yytext[0]); } 5 | %% 6 | int main(int argc, char **argv){ 7 | int i; 8 | char *file_path; 9 | if(argc < 2){ 10 | fprintf(stderr, "Usage: %s ...\n", argv[0]); 11 | return EXIT_FAILURE; 12 | } 13 | else{ 14 | for(i = 1; i < argc; i++){ 15 | file_path = argv[i]; 16 | FILE *fd = fopen(file_path, "r"); 17 | if(!fd){ 18 | perror(file_path); 19 | return EXIT_FAILURE; 20 | } 21 | yyrestart(fd); 22 | yylex(); 23 | fclose(fd); 24 | } 25 | return EXIT_SUCCESS; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /lab2/calc/quiz.txt: -------------------------------------------------------------------------------- 1 | 11 + 13 2 | 33 - 22 3 | 0 + 881 4 | 47 * 6 - 12 5 | 5 + 6 / 3 6 | 4 * 12 - 80 / 5 * 3 7 | 3 - 4 + 1 * 2 8 | 33*3 - 102 9 | -------------------------------------------------------------------------------- /lab2/ipaddr/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | FLEX=flex 3 | ipaddr: 4 | $(FLEX) lex.l 5 | $(CC) lex.yy.c --shared -fPIC -o libip.so 6 | clean: 7 | @rm -f lex.yy.c *.out *.so 8 | .PHONY: ipaddr 9 | -------------------------------------------------------------------------------- /lab2/ipaddr/data.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CirQ/CS323-Compilers-2019fall/702fad8f1e04aad3517587133519a6d587f2b3d7/lab2/ipaddr/data.pickle -------------------------------------------------------------------------------- /lab2/ipaddr/ip_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # encoding: utf-8 3 | 4 | import ctypes 5 | import os 6 | import pickle 7 | 8 | 9 | cwd = os.getcwd() 10 | lib_path = os.path.join(cwd, 'libip.so') 11 | lib = ctypes.cdll.LoadLibrary(lib_path) 12 | 13 | def valid_ip_address(ip): 14 | func = lib.validIPAddress 15 | func.restype = ctypes.c_char_p 16 | ip_b = ip.encode('ascii') 17 | ip_buf = ctypes.c_char_p(ip_b) 18 | return func(ip_buf).decode() 19 | 20 | 21 | test_cases = pickle.load(open('data.pickle', 'rb')) 22 | 23 | for input_, output in test_cases.items(): 24 | ans = valid_ip_address(input_+'\n') 25 | if ans != output: 26 | print('Wrong!') 27 | print('Input: %s' % input_) 28 | print('Excepted: %s' % output) 29 | print('Your answer: %s' % ans) 30 | break 31 | else: 32 | print('All tests passed!') 33 | -------------------------------------------------------------------------------- /lab2/ipaddr/lex.l: -------------------------------------------------------------------------------- 1 | %{ 2 | int indicator = 0; 3 | char *addr_type = NULL; 4 | %} 5 | %option noyywrap 6 | 7 | v4 "WRITE YOUR REGULAR EXPRESSIONS HERE" 8 | v6 "ADD ANY SUB-PATTERNS AS YOU WANT" 9 | 10 | %% 11 | {v4} { indicator = 4; } 12 | {v6} { indicator = 6; } 13 | <> { 14 | if(indicator == 4) 15 | addr_type = "IPv4"; 16 | else if(indicator == 6) 17 | addr_type = "IPv6"; 18 | else 19 | addr_type = "Neither"; 20 | indicator = 0; 21 | return 0; 22 | } 23 | \n {} 24 | . {} 25 | %% 26 | char *validIPAddress(char *IP){ 27 | YY_BUFFER_STATE buf; 28 | buf = yy_scan_string(IP); 29 | yylex(); 30 | yy_delete_buffer(buf); 31 | return addr_type; 32 | } 33 | -------------------------------------------------------------------------------- /lab2/ipaddr/readme.txt: -------------------------------------------------------------------------------- 1 | LeetCode 468. Validate IP Address 2 | https://leetcode.com/problems/validate-ip-address/ 3 | -------------------------------------------------------------------------------- /lab2/wc/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | FLEX=flex 3 | wc: 4 | $(FLEX) lex.l 5 | $(CC) lex.yy.c -lfl -o wc.out 6 | clean: 7 | @rm -f lex.yy.c *.out 8 | .PHONY: wc 9 | -------------------------------------------------------------------------------- /lab2/wc/inferno3.txt: -------------------------------------------------------------------------------- 1 | The Gate and Vestibule of Hell 2 | 3 | Cowards and Neutrals. Acheron 4 | 5 | Through me one goes into the town of woe, 6 | through me one goes into eternal pain, 7 | through me among the people that are lost. 8 | 9 | Justice inspired my high exalted Maker; 10 | I was created by the Might divine, 11 | the highest Wisdom and the primal Love. 12 | 13 | Before me there was naught created, save 14 | eternal things, and I eternal last; 15 | all hope abandon, ye that enter here! 16 | 17 | These words of gloomy color I beheld 18 | inscribed upon the summit of a gate; 19 | whence I: “Their meaning, Teacher, troubles me.” 20 | 21 | And he to me, like one aware, replied: 22 | “All fearfulness must here be left behind; 23 | all forms of cowardice must here be dead. 24 | We’ve reached the place where, as I said to thee, 25 | thou’lt see the sad folk who have lost the Good 26 | which is the object of the intellect.” 27 | Then, after he had placed his hand in mine 28 | with cheerful face, whence I was comforted, 29 | he led me in among the hidden things. 30 | 31 | There sighs and wails and piercing cries of woe 32 | reverberated through the starless air; 33 | hence I, at first, shed tears of sympathy. 34 | Strange languages, and frightful forms of speech, 35 | words caused by pain, accents of anger, voices 36 | both loud and faint, and smiting hands withal, 37 | a mighty tumult made, which sweeps around 38 | forever in that timelessly dark air, 39 | as sand is wont, whene’er a whirlwind blows. 40 | 41 | And I, whose head was girt about with horror, 42 | said: “Teacher, what is this I hear? What folk 43 | is this, that seems so overwhelmed with woe?” 44 | 45 | And he to me: “This wretched kind of life 46 | the miserable spirits lead of those 47 | who lived with neither infamy nor praise. 48 | Commingled are they with that worthless choir 49 | of Angels who did not rebel, nor yet 50 | were true to God, but sided with themselves. 51 | The heavens, in order not to be less fair, 52 | expelled them; nor doth nether Hell receive them, 53 | because the bad would get some glory thence.” 54 | 55 | And I: “What is it, Teacher, grieves them so, 56 | it causes them so loudly to lament?” 57 | 58 | “I’ll tell thee very briefly,” he replied. 59 | “These have no hope of death, and so low down 60 | is this unseeing life of theirs, that envious 61 | they are of every other destiny. 62 | 63 | The world allows no fame of them to live; 64 | Mercy and Justice hold them in contempt. 65 | Let us not talk of them; but look, and pass!” 66 | 67 | And I, who gazed intently, saw a flag, 68 | which, whirling, moved so swiftly that to me 69 | contemptuous it appeared of all repose; 70 | and after it there came so long a line 71 | of people, that I never would have thought 72 | that death so great a number had undone. 73 | 74 | When some I’d recognized, I saw and knew 75 | the shade of him who through his cowardice 76 | the great Refusal made. I understood 77 | immediately, and was assured that this 78 | the band of cowards was, who both to God 79 | displeasing are, and to His enemies. 80 | These wretched souls, who never were alive, 81 | were naked, and were sorely spurred to action 82 | by means of wasps and hornets that were there. 83 | The latter streaked their faces with their blood, 84 | which, after it had mingled with their tears, 85 | was at their feet sucked up by loathsome worms. 86 | 87 | When I had given myself to peering further, 88 | people I saw upon a great stream’s bank; 89 | I therefore said: “Now, Teacher, grant to me 90 | that I may know who these are, and what law 91 | makes them appear so eager to cross over, 92 | as in this dim light I perceive they are.” 93 | 94 | And he to me: “These things will be made clear 95 | to thee, as soon as on the dismal strand 96 | of Acheron we shall have stayed our steps.” 97 | Thereat, with shame-suffused and downcast eyes, 98 | and fearing lest my talking might annoy him, 99 | up to the river I abstained from speech. 100 | 101 | Behold then, coming toward us in a boat, 102 | an agèd man, all white with ancient hair, 103 | who shouted: “Woe to you, ye souls depraved! 104 | Give up all hope of ever seeing Heaven! 105 | I come to take you to the other shore, 106 | into eternal darkness, heat and cold. 107 | And thou that yonder art, a living soul, 108 | withdraw thee from those fellows that are dead.” 109 | But when he saw that I did not withdraw, 110 | he said: “By other roads and other ferries 111 | shalt thou attain a shore to pass across, 112 | not here; a lighter boat must carry thee.” 113 | 114 | To him my Leader: “Charon, be not vexed; 115 | thus is it yonder willed, where there is power 116 | to do whate’er is willed; so ask no more!” 117 | 118 | Thereat were quieted the woolly cheeks 119 | of that old boatman of the murky swamp, 120 | who round about his eyes had wheels of flame. 121 | Those spirits, though, who nude and weary were, 122 | their color changed, and gnashed their teeth together, 123 | as soon as they had heard the cruel words. 124 | 125 | They kept blaspheming God, and their own parents, 126 | the human species, and the place, and time, 127 | and seed of their conception and their birth. 128 | Then each and all of them drew on together, 129 | weeping aloud, to that accursèd shore 130 | which waits for every man that fears not God. 131 | 132 | Charon, the demon, with his ember eyes 133 | makes beckoning signs to them, collects them all, 134 | and with his oar beats whoso takes his ease. 135 | 136 | Even as in autumn leaves detach themselves, 137 | now one and now another, till their branch 138 | sees all its stripped off clothing on the ground; 139 | so, one by one, the evil seed of Adam 140 | cast themselves down that river-bank at signals, 141 | as doth a bird to its recalling lure. 142 | Thus o’er the dusky waves they wend their way; 143 | and ere they land upon the other side, 144 | another crowd collects again on this. 145 | 146 | “My son,” the courteous Teacher said to me, 147 | “all those that perish in the wrath of God 148 | from every country come together here; 149 | and eager are to pass across the stream, 150 | because Justice Divine so spurs them on, 151 | that what was fear is turned into desire. 152 | A good soul never goes across from hence; 153 | if Charon, therefore, findeth fault with thee, 154 | well canst thou now know what his words imply.” 155 | 156 | The darkling plain, when this was ended, quaked 157 | so greatly, that the memory of my terror 158 | bathes me even now with sweat. 159 | The tear-stained ground 160 | gave forth a wind, whence flashed vermilion light 161 | which in me overcame all consciousness; 162 | and down I fell like one whom sleep o’ertakes. 163 | 164 | -------------------------------------------------------------------------------- /lab2/wc/lex.l: -------------------------------------------------------------------------------- 1 | %{ 2 | // just let you know you have macros! 3 | #define EXIT_OK 0 4 | #define EXIT_FAIL 1 5 | 6 | // and global variables 7 | int chars = 0; 8 | int words = 0; 9 | int lines = 0; 10 | %} 11 | letter [a-zA-Z] 12 | %% 13 | {letter}+ { words++; chars+=strlen(yytext); } 14 | \n { chars++; lines++; } 15 | . { chars++; } 16 | %% 17 | int main(int argc, char **argv){ 18 | char *file_path; 19 | if(argc < 2){ 20 | fprintf(stderr, "Usage: %s \n", argv[0]); 21 | return EXIT_FAIL; 22 | } 23 | else if(argc == 2){ 24 | file_path = argv[1]; 25 | if(!(yyin = fopen(file_path, "r"))){ 26 | perror(argv[1]); 27 | return EXIT_FAIL; 28 | } 29 | yylex(); 30 | printf("%-8d%-8d%-8d%s\n", lines, words, chars, file_path); 31 | return EXIT_OK; 32 | } 33 | else{ 34 | fputs("Too much arguments!\n", stderr); 35 | return EXIT_FAIL; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /lab3/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | FLEX=flex 3 | BISON=bison 4 | 5 | 6 | .lex: lex.l 7 | $(FLEX) lex.l 8 | .syntax: syntax.y 9 | $(BISON) -t -d syntax.y 10 | calc: .lex .syntax 11 | $(CC) syntax.tab.c -lfl -ly -D CALC_MAIN -o calc.out 12 | libcalc: .lex .syntax 13 | $(CC) syntax.tab.c -lfl -ly -fPIC --shared -o libcalc.so 14 | clean: 15 | @rm -f lex.yy.c syntax.tab.* *.out *.so 16 | -------------------------------------------------------------------------------- /lab3/calc_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # encoding: utf-8 3 | 4 | import ctypes 5 | import os 6 | 7 | 8 | cwd = os.getcwd() 9 | lib_path = os.path.join(cwd, 'libcalc.so') 10 | lib = ctypes.cdll.LoadLibrary(lib_path) 11 | 12 | def evaluate(expr): 13 | func = lib.evaluate 14 | func.restype = ctypes.c_int 15 | expr += ' = ' 16 | expr_b = expr.encode('ascii') 17 | expr_buf = ctypes.c_char_p(expr_b) 18 | return func(expr_buf) 19 | 20 | testcases = [ 21 | ('1+1', 2), 22 | ('4-1', 3), 23 | ('3-2*4', -5), 24 | ('10-4/2', 8), 25 | ('10-10%', 9), 26 | ('10+10%', 11), 27 | ('10+3*10-10%+5', 41), # iphone 28 | ('10+3*10-10%+5', 42), # google 29 | ('10+3*10-10%+5', 44.9), # bing 30 | ] 31 | 32 | for q, a in testcases: 33 | r = evaluate(q) 34 | assert r == a, '%s: expect %d; got %d' % (q,a,r) 35 | else: 36 | print('pass all test cases') 37 | 38 | -------------------------------------------------------------------------------- /lab3/lex.l: -------------------------------------------------------------------------------- 1 | %{ 2 | #include"syntax.tab.h" 3 | %} 4 | %% 5 | [0-9]+ { yylval = atoi(yytext); return INT; } 6 | "+" { return ADD; } 7 | "-" { return SUB; } 8 | "*" { return MUL; } 9 | "/" { return DIV; } 10 | "%" { return PERC; } 11 | "=" { return EQ; } 12 | [ \n\r\t] {} 13 | . { fprintf(stderr, "unknown symbol: %s\n", yytext); } 14 | -------------------------------------------------------------------------------- /lab3/syntax.y: -------------------------------------------------------------------------------- 1 | %{ 2 | #include"lex.yy.c" 3 | void yyerror(const char*); 4 | int result; 5 | %} 6 | %error-verbose 7 | %token INT 8 | %token ADD SUB MUL DIV PERC EQ 9 | %% 10 | Quiz: Exp EQ { result = $1; } 11 | ; 12 | Exp: Factor 13 | | Factor ADD Exp { $$ = $1 + $3; } 14 | | Factor SUB Exp { $$ = $1 - $3; } 15 | ; 16 | Factor: INT 17 | | INT MUL Factor { $$ = $1 * $3; } 18 | | INT DIV Factor { $$ = $1 / $3; } 19 | ; 20 | %% 21 | void yyerror(const char *s){ 22 | fprintf(stderr, "%s\n", s); 23 | } 24 | #ifndef CALC_MAIN 25 | #else 26 | int main(){ 27 | yyparse(); 28 | printf(" = %d\n", result); 29 | } 30 | #endif 31 | 32 | 33 | int evaluate(char *expr){ 34 | YY_BUFFER_STATE buf; 35 | buf = yy_scan_string(expr); 36 | yyparse(); 37 | yy_delete_buffer(buf); 38 | return result; 39 | } 40 | 41 | -------------------------------------------------------------------------------- /lab5/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | FLEX=flex 3 | BISON=bison 4 | calc: 5 | $(BISON) -d syntax.y 6 | $(FLEX) lex.l 7 | $(CC) syntax.tab.c -lfl -ly -o calc.out 8 | clean: 9 | @rm -f lex.yy.c syntax.tab.* *.out 10 | -------------------------------------------------------------------------------- /lab5/lex.l: -------------------------------------------------------------------------------- 1 | %{ 2 | #include"syntax.tab.h" 3 | %} 4 | %% 5 | [0-9]+ { yylval = atoi(yytext); return INT; } 6 | "+" { return ADD; } 7 | "-" { return SUB; } 8 | "*" { return MUL; } 9 | "/" { return DIV; } 10 | "%" { return PERC; } 11 | "\n" { return EQ; } 12 | [ \r\t] {} 13 | . { fprintf(stderr, "unknown symbol: %s\n", yytext); } 14 | -------------------------------------------------------------------------------- /lab5/quiz.txt: -------------------------------------------------------------------------------- 1 | 11 + 13 2 | 33 - 22 3 | 0 + 881 4 | 47 * 6 - 12 5 | 5 + 6 / 3 6 | 4 * 12 - 80 / 5 * 3 7 | 3 - 4 + 1 * 2 8 | 33*3 - 102 9 | 42 + 10 | 10 + 3*10 - 10% + 5 11 | -------------------------------------------------------------------------------- /lab5/syntax.y: -------------------------------------------------------------------------------- 1 | %{ 2 | #include"lex.yy.c" 3 | extern FILE *yyin; 4 | void yyerror(const char*); 5 | 6 | // what if (assume no syntax error) 7 | // Quiz QuizList { printf(" = %.2f\n", $1); } 8 | %} 9 | %error-verbose 10 | %define api.value.type { float } 11 | %token INT PERC EQ 12 | %left ADD SUB 13 | %left MUL DIV 14 | %% 15 | QuizList: %empty 16 | | QuizList Quiz { printf(" = %.2f\n", $2); } 17 | | QuizList ErrExp EQ {} 18 | ; 19 | Quiz: Exp EQ { $$ = $1; } 20 | ; 21 | Exp: INT 22 | | Exp ADD Exp { $$ = $1 + $3; } 23 | | Exp SUB Exp { $$ = $1 - $3; } 24 | | Exp MUL Exp { $$ = $1 * $3; } 25 | | Exp DIV Exp { $$ = $1 / $3; } 26 | | Exp ADD Disc { $$ = $1 * (1 + $3); } 27 | | Exp SUB Disc { $$ = $1 * (1 - $3); } 28 | ; 29 | ErrExp: 30 | Exp ADD error 31 | | Exp SUB error 32 | | Exp MUL error 33 | | Exp DIV error 34 | ; 35 | Disc: INT PERC { $$ = 0.01 * $1; } 36 | ; 37 | %% 38 | void yyerror(const char *s){ 39 | fprintf(stderr, "%s\n", s); 40 | } 41 | int main(int argc, char **argv){ 42 | yyin = fopen(argv[1], "r"); 43 | yyparse(); 44 | fclose(yyin); 45 | } 46 | -------------------------------------------------------------------------------- /lab7/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=-I. 3 | 4 | lltest: clean 5 | $(CC) symtab_ll.c --shared -fPIC -o libsymtab.so 6 | @echo "\e[92mRunning test for \e[4mlinked list\e[24m implementation...\e[0m" 7 | @python3 test.py ||: 8 | httest: clean 9 | $(CC) symtab_ht.c --shared -fPIC -o libsymtab.so 10 | @echo "\e[92mRunning test for \e[4mhash table\e[24m implementation...\e[0m" 11 | @python3 test.py ||: 12 | bttest: clean 13 | $(CC) symtab_bt.c --shared -fPIC -o libsymtab.so 14 | @echo "\e[92mRunning test for \e[4mbinary tree\e[24m implementation...\e[0m" 15 | @python3 test.py ||: 16 | clean: 17 | @rm -f *.out *.so 18 | .PHONY: lltest httest bttest 19 | 20 | -------------------------------------------------------------------------------- /lab7/symtab_bt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define KEY_LEN 32 6 | #define VAL_T int 7 | 8 | /* 9 | * struct definition for table entry, 10 | * should only be used internally 11 | */ 12 | struct _entry { 13 | char key[KEY_LEN+1]; 14 | VAL_T value; 15 | }; 16 | 17 | // init a table entry, to be inserted 18 | void _entry_init(struct _entry *self, char *key, VAL_T value){ 19 | sprintf(self->key, "%s", key); 20 | self->value = value; 21 | } 22 | 23 | /* 24 | * symbol table type, binary tree impl 25 | */ 26 | typedef struct symtab { 27 | struct _entry entry; 28 | struct symtab *left, *right; 29 | } symtab; 30 | 31 | // init a single symbol table 32 | symtab *symtab_init(); 33 | 34 | // insert a key-value pair to the table 35 | // if insert success, return 1, otherwise 0 36 | int symtab_insert(symtab*, char*, VAL_T); 37 | 38 | // lookup the value to a specific key 39 | // return -1 if not found (for ptr VAL_T, return NULL) 40 | VAL_T symtab_lookup(symtab*, char*); 41 | 42 | // delete a key-value pair from the table 43 | // if delete success, return 1, otherwise 0 44 | int symtab_delete(symtab*, char*); 45 | 46 | // ************************************************************ 47 | // Your implementation goes here 48 | // ************************************************************ 49 | 50 | symtab *symtab_init(){ 51 | 52 | } 53 | 54 | int symtab_insert(symtab *self, char *key, VAL_T value){ 55 | 56 | } 57 | 58 | VAL_T symtab_lookup(symtab *self, char *key){ 59 | 60 | } 61 | 62 | int symtab_delete(symtab *self, char *key){ 63 | 64 | } 65 | 66 | -------------------------------------------------------------------------------- /lab7/symtab_ht.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define KEY_LEN 32 6 | #define VAL_T int 7 | 8 | /* 9 | * struct definition for table entry, 10 | * should only be used internally 11 | */ 12 | struct _entry { 13 | char key[KEY_LEN+1]; 14 | VAL_T value; 15 | }; 16 | 17 | // init a table entry, to be inserted 18 | void _entry_init(struct _entry *self, char *key, VAL_T value){ 19 | sprintf(self->key, "%s", key); 20 | self->value = value; 21 | } 22 | 23 | /* 24 | * symbol table type, hash table (close addressing) impl 25 | */ 26 | #define TABLE_SIZE 0x1003 27 | struct _node { 28 | struct _entry entry; 29 | struct _node *next; 30 | }; 31 | typedef struct _node *symtab[TABLE_SIZE]; 32 | 33 | // init a single symbol table 34 | symtab *symtab_init(); 35 | 36 | // insert a key-value pair to the table 37 | // if insert success, return 1, otherwise 0 38 | int symtab_insert(symtab*, char*, VAL_T); 39 | 40 | // lookup the value to a specific key 41 | // return -1 if not found (for ptr VAL_T, return NULL) 42 | VAL_T symtab_lookup(symtab*, char*); 43 | 44 | // delete a key-value pair from the table 45 | // if delete success, return 1, otherwise 0 46 | int symtab_delete(symtab*, char*); 47 | 48 | // ************************************************************ 49 | // Your implementation goes here 50 | // ************************************************************ 51 | 52 | symtab *symtab_init(){ 53 | 54 | } 55 | 56 | int symtab_insert(symtab *self, char *key, VAL_T value){ 57 | 58 | } 59 | 60 | VAL_T symtab_lookup(symtab *self, char *key){ 61 | 62 | } 63 | 64 | int symtab_delete(symtab *self, char *key){ 65 | 66 | } 67 | 68 | -------------------------------------------------------------------------------- /lab7/symtab_ll.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define KEY_LEN 32 6 | #define VAL_T int 7 | 8 | /* 9 | * struct definition for table entry, 10 | * should only be used internally 11 | */ 12 | struct _entry { 13 | char key[KEY_LEN+1]; 14 | VAL_T value; 15 | }; 16 | 17 | // init a table entry, to be inserted 18 | void _entry_init(struct _entry *self, char *key, VAL_T value){ 19 | sprintf(self->key, "%s", key); 20 | self->value = value; 21 | } 22 | 23 | /* 24 | * symbol table type, linked list impl 25 | */ 26 | typedef struct symtab { 27 | struct _entry entry; 28 | struct symtab *next; 29 | } symtab; 30 | 31 | // init a single symbol table 32 | symtab *symtab_init(); 33 | 34 | // insert a key-value pair to the table 35 | // if insert success, return 1, otherwise 0 36 | int symtab_insert(symtab*, char*, VAL_T); 37 | 38 | // lookup the value to a specific key 39 | // return -1 if not found (for ptr VAL_T, return NULL) 40 | VAL_T symtab_lookup(symtab*, char*); 41 | 42 | // delete a key-value pair from the table 43 | // if delete success, return 1, otherwise 0 44 | int symtab_delete(symtab*, char*); 45 | 46 | // ************************************************************ 47 | // Your implementation goes here 48 | // ************************************************************ 49 | 50 | symtab *symtab_init(){ 51 | 52 | } 53 | 54 | int symtab_insert(symtab *self, char *key, VAL_T value){ 55 | 56 | } 57 | 58 | VAL_T symtab_lookup(symtab *self, char *key){ 59 | 60 | } 61 | 62 | int symtab_delete(symtab *self, char *key){ 63 | 64 | } 65 | 66 | -------------------------------------------------------------------------------- /lab7/test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # encoding: utf-8 3 | 4 | import ctypes 5 | import os 6 | import random 7 | import string 8 | import unittest 9 | 10 | class SymbolTable(ctypes.Structure): 11 | cwd = os.getcwd() 12 | lib_path = os.path.join(cwd, 'libsymtab.so') 13 | lib = ctypes.CDLL(lib_path) 14 | def __init__(self): 15 | self.lib.symtab_init.restype = ctypes.POINTER(SymbolTable) 16 | self.lib.symtab_insert.restype = ctypes.c_int32 17 | self.lib.symtab_lookup.restype = ctypes.c_int32 18 | self.lib.symtab_delete.restype = ctypes.c_int32 19 | self.this = self.lib.symtab_init() 20 | 21 | @staticmethod 22 | def safe_key(key): 23 | assert len(key) <= 32 24 | key_b = key.encode('ascii') 25 | key_buf = ctypes.c_char_p(key_b) 26 | return key_buf 27 | 28 | def insert(self, key, value): 29 | key = self.safe_key(key) 30 | r = self.lib.symtab_insert(self.this, key, value) 31 | return int(r) 32 | 33 | def lookup(self, key): 34 | key = self.safe_key(key) 35 | r = self.lib.symtab_lookup(self.this, key) 36 | return int(r) 37 | 38 | def delete(self, key): 39 | key = self.safe_key(key) 40 | r = self.lib.symtab_delete(self.this, key) 41 | return int(r) 42 | 43 | 44 | class SymbolTableTest(unittest.TestCase): 45 | def test_suite_01(self): 46 | st = SymbolTable() 47 | st.insert('10', 10) 48 | st.insert('20', 20) 49 | self.assertEqual(st.lookup('10'), 10) 50 | self.assertEqual(st.lookup('20'), 20) 51 | self.assertEqual(st.insert('30', 30), 1) 52 | self.assertEqual(st.insert('10', 100), 0) 53 | st.delete('10') 54 | self.assertEqual(st.insert('10', 100), 1) 55 | self.assertEqual(st.lookup('10'), 100) 56 | self.assertEqual(st.delete('10'), 1) 57 | self.assertEqual(st.delete('10'), 0) 58 | 59 | def test_suite_02(self): 60 | st = SymbolTable() 61 | size = 10000 62 | data = list(range(size)) 63 | random.shuffle(data) 64 | for i in data: 65 | st.insert(str(i), i) 66 | for i in data: 67 | s = st.lookup(str(i)) 68 | self.assertEqual(s, i) 69 | self.assertEqual(st.lookup(str(size)), -1) 70 | 71 | def test_suite_03(self): 72 | letters = string.ascii_lowercase + string.ascii_uppercase 73 | st = SymbolTable() 74 | tab = dict() 75 | size = random.randint(500, 1000) 76 | while len(tab) < size: 77 | k = ''.join(random.choice(letters) for _ in range(8)) 78 | v = random.randint(0, 10000) 79 | tab[k] = v 80 | st.insert(k, v) 81 | ks = list(tab) 82 | 83 | trial = random.randint(500, 800) 84 | for _ in range(trial): 85 | k = random.choice(ks) 86 | v = tab[k] 87 | self.assertEqual(st.lookup(k), v) 88 | 89 | trial = random.randint(200, 400) 90 | for k in random.sample(ks, trial): 91 | del tab[k] 92 | self.assertEqual(st.delete(k), 1) 93 | 94 | trial = random.randint(400, 700) 95 | for _ in range(trial): 96 | k = random.choice(ks) 97 | if k in tab: 98 | self.assertEqual(st.lookup(k), tab[k]) 99 | else: 100 | self.assertEqual(st.lookup(k), -1) 101 | 102 | 103 | if __name__ == '__main__': 104 | unittest.main() 105 | 106 | -------------------------------------------------------------------------------- /lab9/Makefile: -------------------------------------------------------------------------------- 1 | expr_bison: 2 | flex lex.l && bison -t -d syntax.y 3 | gcc syntax.tab.c -lfl -ly -shared -fPIC -o libexpr.so 4 | @echo "\e[92mTesting BISON implementation...\e[0m" 5 | @python3 expr_test.py ||: 6 | expr_stack: 7 | gcc stack.c -shared -fPIC -o libexpr.so 8 | @echo "\e[92mTesting STACK implementation...\e[0m" 9 | @python3 expr_test.py ||: 10 | clean: 11 | @rm -f lex.yy.c syntax.tab.* *.out *.so 12 | -------------------------------------------------------------------------------- /lab9/expr_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # encoding: utf-8 3 | 4 | import ctypes 5 | import os 6 | 7 | 8 | cwd = os.getcwd() 9 | lib_path = os.path.join(cwd, 'libexpr.so') 10 | lib = ctypes.cdll.LoadLibrary(lib_path) 11 | 12 | def convert(expr): 13 | func = lib.convert 14 | func.restype = ctypes.c_char_p 15 | expr_b = expr.encode() 16 | expr_buf = ctypes.c_char_p(expr_b) 17 | return func(expr_buf).decode() 18 | 19 | 20 | assert convert('5')=='5', convert('5') 21 | 22 | assert convert('9-5+2')=='95-2+', convert('9-5+2') 23 | 24 | print("Testing completed.") 25 | 26 | -------------------------------------------------------------------------------- /lab9/lex.l: -------------------------------------------------------------------------------- 1 | %{ 2 | #include"syntax.tab.h" 3 | %} 4 | %% 5 | [0-9] { 6 | yylval = (char*)malloc(2); 7 | memcpy(yylval, yytext, 2); 8 | return TERM; 9 | } 10 | "+" { yylval = "+"; return ADD; } 11 | "-" { yylval = "-"; return SUB; } 12 | . { /* do nothing */ } 13 | -------------------------------------------------------------------------------- /lab9/stack.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #define STACK_LEN 32 5 | 6 | char *convert(char *expr){ 7 | char opstack[STACK_LEN]; 8 | char stack[STACK_LEN]; 9 | int optop, top; 10 | char *c, *ret; 11 | 12 | memset(opstack, '\0', STACK_LEN); 13 | memset(stack, '\0', STACK_LEN); 14 | optop = top = 0; 15 | c = expr; 16 | 17 | while(*c != '\0'){ 18 | if((*c >= '0') && (*c <= '9')){ 19 | 20 | } 21 | else if((*c == '+') || (*c == '-')){ 22 | 23 | } 24 | else{ 25 | // lexical errors 26 | } 27 | c++; 28 | } 29 | 30 | ret = (char*)malloc(strlen(stack)+1); 31 | sprintf(ret, "%s", stack); 32 | return ret; 33 | } 34 | 35 | int main(){ 36 | puts( convert("3-7+4-5") ); 37 | return 0; 38 | } 39 | 40 | -------------------------------------------------------------------------------- /lab9/syntax.y: -------------------------------------------------------------------------------- 1 | %{ 2 | #include"lex.yy.c" 3 | void yyerror(char*s){} 4 | 5 | /* 6 | * We make assumptions on the input: 7 | * there are no syntax errors, and 8 | * only consist two operators, plus 9 | * and minus, and all numbers contain 10 | * exactly one digit, no spaces. 11 | */ 12 | 13 | // where reverse Polish notation goes 14 | char *result; 15 | %} 16 | %define api.value.type { char* } 17 | %token TERM ADD SUB 18 | 19 | %% 20 | Eval: Expr { result = $1; } 21 | Expr: TERM /* write the */ 22 | | Expr ADD TERM /* SDT actions */ 23 | | Expr SUB TERM /* at HERE */ 24 | %% 25 | 26 | char *convert(char *expr){ 27 | YY_BUFFER_STATE buf; 28 | buf = yy_scan_string(expr); 29 | yyparse(); 30 | yy_delete_buffer(buf); 31 | return result; 32 | } 33 | -------------------------------------------------------------------------------- /project1/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | splc: 3 | @mkdir bin 4 | touch bin/splc 5 | @chmod +x bin/splc 6 | clean: 7 | @rm -rf bin/ 8 | .PHONY: splc -------------------------------------------------------------------------------- /project1/test/test_1_o01.out: -------------------------------------------------------------------------------- 1 | Error type A at Line 3: unknown lexeme 0x77G 2 | Error type A at Line 4: unknown lexeme 0xCS 3 | Error type A at Line 7: unknown lexeme '\x6u' 4 | Error type A at Line 8: unknown lexeme '\x910' 5 | -------------------------------------------------------------------------------- /project1/test/test_1_o01.spl: -------------------------------------------------------------------------------- 1 | int test_1_o01() 2 | { 3 | int _wrong_hex_int_1 = 0x77G; 4 | int _wrong_hex_int_2 = 0xCS; 5 | int _right_hex_int = 0xdeadbeef; 6 | char _right_hex_char = '\xa0'; 7 | char _wrong_hex_char_1 = '\x6u'; 8 | char _wrong_hex_char_2 = '\x910'; 9 | } 10 | -------------------------------------------------------------------------------- /project1/test/test_1_o02.spl: -------------------------------------------------------------------------------- 1 | int test_1_o02() 2 | { 3 | int dec_int = 323; 4 | int hex_int = 0xFFF; 5 | char ch = '\xC0'; 6 | return hex_int - dec_int; 7 | } 8 | -------------------------------------------------------------------------------- /project1/test/test_1_o03.spl: -------------------------------------------------------------------------------- 1 | /* 2 | multiline 3 | \/\///\\/ 4 | comment 5 | **/ 6 | int /*func*/test_1_o03(int m,//) 7 | int n) 8 | { 9 | int max; 10 | if (m > /*inline comment*/n) 11 | { 12 | max = m; 13 | // max = 2*m + 1; 14 | } 15 | else 16 | { 17 | max = n; 18 | } 19 | return max; 20 | } 21 | -------------------------------------------------------------------------------- /project1/test/test_1_r01.out: -------------------------------------------------------------------------------- 1 | Program (1) 2 | ExtDefList (1) 3 | ExtDef (1) 4 | Specifier (1) 5 | TYPE: int 6 | FunDec (1) 7 | ID: test_1_r01 8 | LP 9 | VarList (1) 10 | ParamDec (1) 11 | Specifier (1) 12 | TYPE: int 13 | VarDec (1) 14 | ID: a 15 | COMMA 16 | VarList (1) 17 | ParamDec (1) 18 | Specifier (1) 19 | TYPE: int 20 | VarDec (1) 21 | ID: b 22 | RP 23 | CompSt (2) 24 | LC 25 | StmtList (3) 26 | Stmt (3) 27 | Exp (3) 28 | Exp (3) 29 | ID: c 30 | ASSIGN 31 | Exp (3) 32 | CHAR: 'c' 33 | SEMI 34 | StmtList (4) 35 | Stmt (4) 36 | IF 37 | LP 38 | Exp (4) 39 | Exp (4) 40 | ID: a 41 | GT 42 | Exp (4) 43 | ID: b 44 | RP 45 | Stmt (5) 46 | CompSt (5) 47 | LC 48 | StmtList (6) 49 | Stmt (6) 50 | RETURN 51 | Exp (6) 52 | ID: a 53 | SEMI 54 | RC 55 | ELSE 56 | Stmt (9) 57 | CompSt (9) 58 | LC 59 | StmtList (10) 60 | Stmt (10) 61 | RETURN 62 | Exp (10) 63 | ID: b 64 | SEMI 65 | RC 66 | RC 67 | -------------------------------------------------------------------------------- /project1/test/test_1_r01.spl: -------------------------------------------------------------------------------- 1 | int test_1_r01(int a, int b) 2 | { 3 | c = 'c'; 4 | if (a > b) 5 | { 6 | return a; 7 | } 8 | else 9 | { 10 | return b; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /project1/test/test_1_r02.out: -------------------------------------------------------------------------------- 1 | Program (1) 2 | ExtDefList (1) 3 | ExtDef (1) 4 | Specifier (1) 5 | TYPE: int 6 | ExtDecList (1) 7 | VarDec (1) 8 | ID: global 9 | SEMI 10 | ExtDefList (2) 11 | ExtDef (2) 12 | Specifier (2) 13 | StructSpecifier (2) 14 | STRUCT 15 | ID: my_struct 16 | LC 17 | DefList (4) 18 | Def (4) 19 | Specifier (4) 20 | TYPE: int 21 | DecList (4) 22 | Dec (4) 23 | VarDec (4) 24 | ID: code 25 | SEMI 26 | DefList (5) 27 | Def (5) 28 | Specifier (5) 29 | TYPE: char 30 | DecList (5) 31 | Dec (5) 32 | VarDec (5) 33 | ID: data 34 | SEMI 35 | RC 36 | SEMI 37 | ExtDefList (7) 38 | ExtDef (7) 39 | Specifier (7) 40 | TYPE: int 41 | FunDec (7) 42 | ID: test_1_r02 43 | LP 44 | RP 45 | CompSt (8) 46 | LC 47 | DefList (9) 48 | Def (9) 49 | Specifier (9) 50 | StructSpecifier (9) 51 | STRUCT 52 | ID: my_struct 53 | DecList (9) 54 | Dec (9) 55 | VarDec (9) 56 | ID: obj 57 | SEMI 58 | StmtList (10) 59 | Stmt (10) 60 | Exp (10) 61 | Exp (10) 62 | Exp (10) 63 | ID: obj 64 | DOT 65 | ID: code 66 | ASSIGN 67 | Exp (10) 68 | ID: global 69 | SEMI 70 | StmtList (11) 71 | Stmt (11) 72 | Exp (11) 73 | Exp (11) 74 | ID: global 75 | ASSIGN 76 | Exp (11) 77 | Exp (11) 78 | ID: global 79 | PLUS 80 | Exp (11) 81 | INT: 1 82 | SEMI 83 | RC 84 | -------------------------------------------------------------------------------- /project1/test/test_1_r02.spl: -------------------------------------------------------------------------------- 1 | int global; 2 | struct my_struct 3 | { 4 | int code; 5 | char data; 6 | }; 7 | int test_1_r02() 8 | { 9 | struct my_struct obj; 10 | obj.code = global; 11 | global = global + 1; 12 | } 13 | -------------------------------------------------------------------------------- /project1/test/test_1_r03.out: -------------------------------------------------------------------------------- 1 | Error type A at Line 4: unknown lexeme $ 2 | Error type B at Line 6: Missing semicolon ';' 3 | Error type A at Line 8: unknown lexeme @ 4 | -------------------------------------------------------------------------------- /project1/test/test_1_r03.spl: -------------------------------------------------------------------------------- 1 | int test_1_r03() 2 | { 3 | int i = 0, j = 1; 4 | float i = $; 5 | if(i < 9.0){ 6 | return 1 7 | } 8 | return @; 9 | } 10 | -------------------------------------------------------------------------------- /project1/test/test_1_r04.out: -------------------------------------------------------------------------------- 1 | Error type B at Line 9: Missing closing parenthesis ')' 2 | Error type B at Line 12: Missing closing parenthesis ')' 3 | -------------------------------------------------------------------------------- /project1/test/test_1_r04.spl: -------------------------------------------------------------------------------- 1 | int func_1(int a) 2 | { 3 | return 3 * a; 4 | } 5 | int func_2(int x, int y) 6 | { 7 | return x + y; 8 | } 9 | int test_1_r04( 10 | { 11 | int a, b, c; 12 | c = func_2(func_1(func_1(a+b*func_1(b)), 1.7); 13 | return c; 14 | } 15 | -------------------------------------------------------------------------------- /project1/test/test_1_r05.spl: -------------------------------------------------------------------------------- 1 | int test_1_r05(int n) 2 | { 3 | int res = 1; 4 | while (n > 0) 5 | { 6 | res = res * n; 7 | n = n - 1; 8 | } 9 | return res; 10 | } 11 | -------------------------------------------------------------------------------- /project1/test/test_1_r06.spl: -------------------------------------------------------------------------------- 1 | int test_1_r06() 2 | { 3 | int right_id_1, _right_id_2; 4 | float 3_wrong_id; 5 | } 6 | -------------------------------------------------------------------------------- /project1/test/test_1_r07.spl: -------------------------------------------------------------------------------- 1 | int test_1_r07() 2 | { 3 | int a, b, c; 4 | a = 1; 5 | b = a && 2; 6 | c = b || 3; 7 | a = c | 4; 8 | b = a & 5; 9 | } 10 | -------------------------------------------------------------------------------- /project1/test/test_1_r08.spl: -------------------------------------------------------------------------------- 1 | int test_1_r08() 2 | { 3 | int a, bb 4 | if (a > 4) 5 | return bb; 6 | } 7 | -------------------------------------------------------------------------------- /project1/test/test_1_r09.spl: -------------------------------------------------------------------------------- 1 | int test_1_r09() 2 | { 3 | int m = 1; 4 | float n = 2.2; 5 | int x[5], y[10]; 6 | x[m] = 7; 7 | y[n] = 8; 8 | return x[y]; 9 | } 10 | -------------------------------------------------------------------------------- /project1/test/test_1_r10.spl: -------------------------------------------------------------------------------- 1 | int test_1_r10() 2 | { 3 | int a, b = 1; 4 | a = 10; 5 | int i = 0; 6 | while (i < a) 7 | { 8 | b = b + i; 9 | i = i + 1; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /project2/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | splc: 3 | @mkdir bin 4 | touch bin/splc 5 | @chmod +x bin/splc 6 | clean: 7 | @rm -rf bin/ 8 | .PHONY: splc -------------------------------------------------------------------------------- /project2/test/test_2_o01.spl: -------------------------------------------------------------------------------- 1 | int foo() 2 | { 3 | int a = 10; 4 | return a; 5 | } 6 | int test_2_o01(int a, int b) 7 | { 8 | int c; 9 | c = foo(); 10 | if (b > 0) 11 | { 12 | int a = c + 3; 13 | b = b - a; 14 | } 15 | a = a + b; 16 | return a; 17 | } 18 | -------------------------------------------------------------------------------- /project2/test/test_2_o02.spl: -------------------------------------------------------------------------------- 1 | struct Student 2 | { 3 | int age; 4 | float height; 5 | }; 6 | struct Person 7 | { 8 | int code; 9 | float weight; 10 | }; 11 | int test_2_o02() 12 | { 13 | struct Student s; 14 | struct Person p; 15 | s = p; 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /project2/test/test_2_r01.spl: -------------------------------------------------------------------------------- 1 | int test_2_r01() 2 | { 3 | int x1 = 5; 4 | int x2 = 3; 5 | int x4 = x1 + x3; 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /project2/test/test_2_r02.spl: -------------------------------------------------------------------------------- 1 | int add1(int n) 2 | { 3 | return n + 1; 4 | } 5 | int test_2_r02() 6 | { 7 | int k = 4; 8 | int r = add(k); 9 | return r; 10 | } 11 | -------------------------------------------------------------------------------- /project2/test/test_2_r03.spl: -------------------------------------------------------------------------------- 1 | int test_2_r03() 2 | { 3 | int ttt = 3; 4 | float iii = 0.3; 5 | float kkk = 1.2; 6 | float ttt = iii * kkk; 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /project2/test/test_2_r04.spl: -------------------------------------------------------------------------------- 1 | int compare(int x, int y) 2 | { 3 | if (x > y) {return 1;} 4 | else if (y > x) {return -1;} 5 | else {return 0;} 6 | } 7 | float compare(int a, int b) 8 | { 9 | if (b > a) {return -1.0;} 10 | if (b == a) {return 0.0;} 11 | return 1.0; 12 | } 13 | int test_2_r04() 14 | { 15 | return compare(7, 8); 16 | } 17 | -------------------------------------------------------------------------------- /project2/test/test_2_r05.spl: -------------------------------------------------------------------------------- 1 | int test_2_r05() 2 | { 3 | float iii = 5.0; 4 | float kkk = 1.2; 5 | int ttt; 6 | ttt = iii * kkk; 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /project2/test/test_2_r06.spl: -------------------------------------------------------------------------------- 1 | int test_2_r06(int i, int n) 2 | { 3 | int res = 0; 4 | if (i == 0) 5 | { 6 | 1 = res; 7 | } 8 | else 9 | { 10 | res = -n; 11 | } 12 | return res; 13 | } 14 | -------------------------------------------------------------------------------- /project2/test/test_2_r07.spl: -------------------------------------------------------------------------------- 1 | struct Apple 2 | { 3 | int weight; 4 | float round; 5 | }; 6 | int test_2_r07() 7 | { 8 | struct Apple aa; 9 | float weight_test = 1.0; 10 | aa.weight = aa + 2; 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /project2/test/test_2_r08.spl: -------------------------------------------------------------------------------- 1 | int compare1(int x, int y) 2 | { 3 | if (x > y) {return 1;} 4 | else if (y > x) {return -1;} 5 | else {return 0;} 6 | } 7 | float compare2(int a, int b) 8 | { 9 | if (b > a) {return -1.0;} 10 | if (b == a) {return 0.0;} 11 | return 1.0; 12 | } 13 | int test_2_r08(int i, int m, int n) 14 | { 15 | if (i == 0) 16 | { 17 | return compare1(m, n); 18 | } 19 | else 20 | { 21 | return compare2(m, n); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /project2/test/test_2_r09.spl: -------------------------------------------------------------------------------- 1 | int compare(int x, int y) 2 | { 3 | if (x > y) {return 1;} 4 | else if (y > x) {return -1;} 5 | else {return 0;} 6 | } 7 | int test_2_r09() 8 | { 9 | float a = 5.8; 10 | float b = 9.2; 11 | float c = 7.0; 12 | return compare(a, b, c); 13 | } 14 | -------------------------------------------------------------------------------- /project2/test/test_2_r10.spl: -------------------------------------------------------------------------------- 1 | struct Person 2 | { 3 | int name; 4 | int friends[10]; 5 | }; 6 | int test_2_r10() 7 | { 8 | struct Person tom; 9 | struct Person people[10]; 10 | int i = 0; 11 | while (i < 10) 12 | { 13 | people[i].name = i; 14 | tom.friends[i] = i; 15 | i = i + 1; 16 | } 17 | return tom.name[i-1]; 18 | } 19 | -------------------------------------------------------------------------------- /project2/test/test_2_r11.spl: -------------------------------------------------------------------------------- 1 | int compare1(int x, int y) 2 | { 3 | if (x > y) {return 1;} 4 | else if (y > x) {return -1;} 5 | else {return 0;} 6 | } 7 | int test_2_r11(int i, int m, int n) 8 | { 9 | int compare2 = 10; 10 | if (i == 0) 11 | { 12 | return compare1(m, n); 13 | } 14 | else 15 | { 16 | return compare2(m, n); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /project2/test/test_2_r12.spl: -------------------------------------------------------------------------------- 1 | int test_2_r12() 2 | { 3 | float arr1[10]; 4 | float arr2[10]; 5 | float a = 1.1; 6 | int i = 0; 7 | while (i < 10) 8 | { 9 | arr1[i] = a; 10 | a = a * a; 11 | } 12 | i = 0; 13 | while (i < 10) 14 | { 15 | arr2[arr1[i]] = a; 16 | } 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /project2/test/test_2_r13.spl: -------------------------------------------------------------------------------- 1 | struct Child 2 | { 3 | int name; 4 | int age; 5 | }; 6 | struct Parent 7 | { 8 | struct Child c; 9 | int cc; 10 | }; 11 | int test_2_r13() 12 | { 13 | struct Parent father; 14 | struct Parent mother; 15 | father.c.name = 1; 16 | father.c.age = 1; 17 | father.cc = 30; 18 | mother.c.name = father.c.name; 19 | mother.cc.age = father.cc.age; 20 | mother.cc = father.cc; 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /project2/test/test_2_r14.spl: -------------------------------------------------------------------------------- 1 | struct Girl 2 | { 3 | int name; 4 | int height; 5 | }; 6 | int test_2_r14() 7 | { 8 | struct Girl gg; 9 | gg.name = 1; 10 | gg.age = 20; 11 | gg.height = 165; 12 | gg.weight = 95; 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /project2/test/test_2_r15.spl: -------------------------------------------------------------------------------- 1 | struct Child 2 | { 3 | int name; 4 | int friends[10]; 5 | }; 6 | struct Child 7 | { 8 | int id; 9 | int age; 10 | }; 11 | int test_2_r15() 12 | { 13 | struct Child Amy; 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /project3/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | splc: 3 | @mkdir bin 4 | touch bin/splc 5 | @chmod +x bin/splc 6 | clean: 7 | @rm -rf bin/ 8 | .PHONY: splc -------------------------------------------------------------------------------- /project3/sample/test01.ir: -------------------------------------------------------------------------------- 1 | FUNCTION main : 2 | READ t1 3 | v1 := t1 4 | t2 := #0 5 | IF v1 > t2 GOTO label1 6 | GOTO label2 7 | LABEL label1 : 8 | t3 := #1 9 | WRITE t3 10 | GOTO label3 11 | LABEL label2 : 12 | t4 := #0 13 | IF v1 < t4 GOTO label4 14 | GOTO label5 15 | LABEL label4 : 16 | t5 := #1 17 | t6 := #0 - t5 18 | WRITE t6 19 | GOTO label6 20 | LABEL label5 : 21 | t7 := #0 22 | WRITE t7 23 | LABEL label6 : 24 | LABEL label3 : 25 | t8 := #0 26 | RETURN t8 -------------------------------------------------------------------------------- /project3/sample/test01.spl: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | int n; 4 | n = read(); 5 | if (n > 0) write(1); 6 | else if (n < 0) write (-1); 7 | else write(0); 8 | return 0; 9 | } -------------------------------------------------------------------------------- /project3/sample/test02.ir: -------------------------------------------------------------------------------- 1 | FUNCTION fact : 2 | PARAM v1 3 | IF v1 == #1 GOTO label1 4 | GOTO label2 5 | LABEL label1 : 6 | RETURN v1 7 | LABEL label2 : 8 | t1 := v1 - #1 9 | ARG t1 10 | t2 := CALL fact 11 | t3 := v1 * t2 12 | RETURN t3 13 | 14 | FUNCTION main : 15 | READ t4 16 | v2 := t4 17 | IF v2 > #1 GOTO label3 18 | GOTO label4 19 | LABEL label3 : 20 | ARG v2 21 | t5 := CALL fact 22 | v3 := t5 23 | GOTO label5 24 | LABEL label4 : 25 | v3 := #1 26 | LABEL label5 : 27 | WRITE v3 28 | RETURN #0 -------------------------------------------------------------------------------- /project3/sample/test02.spl: -------------------------------------------------------------------------------- 1 | int fact(int n) 2 | { 3 | if (n == 1) 4 | return n; 5 | else 6 | return (n * fact(n - 1)); 7 | } 8 | int main() 9 | { 10 | int m, result; 11 | m = read(); 12 | if (m > 1) 13 | result = fact(m); 14 | else 15 | result = 1; 16 | write(result); 17 | return 0; 18 | } -------------------------------------------------------------------------------- /project3/sample/test03.ir: -------------------------------------------------------------------------------- 1 | FUNCTION add : 2 | PARAM v1 3 | t2 := *v1 4 | t7 := v1 + #4 5 | t3 := *t7 6 | t1 := t2 + t3 7 | RETURN t1 8 | FUNCTION main : 9 | DEC v3 8 10 | t9 := &v3 11 | *t9 := #1 12 | t12 := &v3 + #4 13 | *t12 := #2 14 | ARG &v3 15 | t14 := CALL add 16 | v2 := t14 17 | WRITE v2 18 | RETURN #0 -------------------------------------------------------------------------------- /project3/sample/test03.spl: -------------------------------------------------------------------------------- 1 | struct Operands 2 | { 3 | int o1; 4 | int o2; 5 | }; 6 | 7 | int add(struct Operands temp) 8 | { 9 | return (temp.o1 + temp.o2); 10 | } 11 | 12 | int main() 13 | { 14 | int n; 15 | struct Operands op; 16 | op.o1 = 1; 17 | op.o2 = 2; 18 | n = add(op); 19 | write(n); 20 | return 0; 21 | } -------------------------------------------------------------------------------- /project3/sample/test04.ir: -------------------------------------------------------------------------------- 1 | FUNCTION add : 2 | PARAM v1 3 | t2 := *v1 4 | t11 := v1 + #4 5 | t3 := *t11 6 | t1 := t2 + t3 7 | RETURN t1 8 | FUNCTION main : 9 | DEC v2 8 10 | DEC v3 8 11 | v4 := #0 12 | v5 := #0 13 | LABEL label1 : 14 | IF v4 < #2 GOTO label2 15 | GOTO label3 16 | LABEL label2 : 17 | LABEL label4 : 18 | IF v5 < #2 GOTO label5 19 | GOTO label6 20 | LABEL label5 : 21 | t18 := v5 * #4 22 | t19 := &v2 + t18 23 | t20 := v4 + v5 24 | *t19 := t20 25 | v5 := v5 + #1 26 | GOTO label4 27 | LABEL label6 : 28 | t31 := v4 * #4 29 | t32 := &v3 + t31 30 | ARG &v2 31 | t33 := CALL add 32 | *t32 := t33 33 | t41 := v4 * #4 34 | t42 := &v3 + t41 35 | t35 := *t42 36 | WRITE t35 37 | v4 := v4 + #1 38 | v5 := #0 39 | GOTO label1 40 | LABEL label3 : 41 | RETURN #0 -------------------------------------------------------------------------------- /project3/sample/test04.spl: -------------------------------------------------------------------------------- 1 | int add(int temp[2]) 2 | { 3 | return (temp[0] + temp[1]); 4 | } 5 | 6 | int main() 7 | { 8 | int op[2]; 9 | int r[1][2]; 10 | int i = 0, j = 0; 11 | while (i < 2) 12 | { 13 | while (j < 2) 14 | { 15 | op[j] = i + j; 16 | j = j + 1; 17 | } 18 | r[0][i] = add(op); 19 | write(r[0][i]); 20 | i = i + 1; 21 | j = 0; 22 | } 23 | return 0; 24 | } -------------------------------------------------------------------------------- /project3/test/test_3_b01.spl: -------------------------------------------------------------------------------- 1 | struct Operands 2 | { 3 | int o1; 4 | int o2; 5 | }; 6 | 7 | int add(struct Operands temp) 8 | { 9 | return (temp.o1 + temp.o2); 10 | } 11 | 12 | int main() 13 | { 14 | int n; 15 | struct Operands op; 16 | op.o1 = 1; 17 | op.o2 = 2; 18 | n = add(op); 19 | write(n); 20 | return 0; 21 | } -------------------------------------------------------------------------------- /project3/test/test_3_b02.spl: -------------------------------------------------------------------------------- 1 | int add(int temp[2]) 2 | { 3 | return (temp[0] + temp[1]); 4 | } 5 | 6 | int main() 7 | { 8 | int op[2]; 9 | int r[1][2]; 10 | int i = 0, j = 0; 11 | while (i < 2) 12 | { 13 | while (j < 2) 14 | { 15 | op[j] = i + j; 16 | j = j + 1; 17 | } 18 | r[0][i] = add(op); 19 | write(r[0][i]); 20 | i = i + 1; 21 | j = 0; 22 | } 23 | return 0; 24 | } -------------------------------------------------------------------------------- /project3/test/test_3_b03.spl: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int x[5], max, temp; 3 | int i = 0, N = 5, j = 0; 4 | while(i < 5){ 5 | x[i] = read(); 6 | i = i + 1; 7 | } 8 | i = N; 9 | while(i > 0){ 10 | while(j < i - 1){ 11 | if(x[j] > x[j + 1]){ 12 | temp = x[j]; 13 | x[j] = x[j + 1]; 14 | x[j + 1] = temp; 15 | } 16 | j = j + 1; 17 | } 18 | j = 0; 19 | i = i- 1; 20 | } 21 | i = 0; 22 | while(i < 5){ 23 | write(x[i]); 24 | i = i + 1; 25 | } 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /project3/test/test_3_b04.spl: -------------------------------------------------------------------------------- 1 | int Josepy(int n,int m){ 2 | int people[100], i = 1; 3 | int j = 0, k = 0, num = 0; 4 | while(i <= n){ 5 | people[i] = 1; 6 | i = i + 1; 7 | } 8 | i = 1; 9 | while(i <= n){ 10 | if(people[i] == 1){ 11 | j = j + people[i]; 12 | if(j == m){ 13 | write(i); 14 | j = 0; 15 | people[i] = 0; 16 | k = k + 1; 17 | } 18 | if(k == n){ 19 | num=i; 20 | return 0; 21 | } 22 | } 23 | if(i == n) 24 | i = 0; 25 | i = i + 1; 26 | } 27 | return 0; 28 | } 29 | int main(){ 30 | int a, b; 31 | a = read(); 32 | b = read(); 33 | Josepy(a, b); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /project3/test/test_3_b05.spl: -------------------------------------------------------------------------------- 1 | int squaRever(int num) 2 | { 3 | int flag = 0; 4 | int array[3]; 5 | int j=0; 6 | array[0] = num / 100; 7 | array[1] = num / 10 - 10 * array[0]; 8 | array[2] = num - 100 * array[0] - 10 * array[1]; 9 | if (array[0] != array[2]) { 10 | flag = 0; 11 | } 12 | else { 13 | while (j < 12){ 14 | if ((j * j - num) == 0 ) 15 | flag = 1; 16 | j = j + 1; 17 | } 18 | } 19 | if (flag == 1) 20 | return 1; 21 | else 22 | return 0; 23 | } 24 | 25 | int main() 26 | { 27 | int i=100; 28 | while (i < 150){ 29 | if (squaRever(i) == 1) 30 | write(i); 31 | i = i + 1; 32 | } 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /project3/test/test_3_r01.spl: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | int a, b, c; 4 | int final = 0; 5 | a = 5; 6 | b = a * a * (a + 2); 7 | write(b); 8 | c = b / a + 1; 9 | write(c); 10 | final = a + b - c * 3 + (b / a - 4); 11 | write(final); 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /project3/test/test_3_r02.spl: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | int month, year; 4 | year = read(); 5 | month = read(); 6 | if(year == (year / 100 * 100)){ 7 | if(year == (year / 400 * 400)){ 8 | if(month == 2){ 9 | write(29); 10 | } 11 | else if(month == (month / 2 * 2)){ 12 | write(30); 13 | } 14 | else 15 | write(31); 16 | }else { 17 | if(month == 2){ 18 | write(28); 19 | } 20 | else if(month == (month / 2 * 2)){ 21 | write(30); 22 | } 23 | else { 24 | write(31); 25 | } 26 | } 27 | } 28 | else if(year == (year/4 * 4)){ 29 | if(month == 2){ 30 | write(29); 31 | } 32 | else if(month == (month / 2 * 2)){ 33 | write(30); 34 | } 35 | else { 36 | write(31); 37 | } 38 | } 39 | else{ 40 | if(month == 2){ 41 | write(28); 42 | } 43 | else if(month == (month / 2 * 2)){ 44 | write(30); 45 | } 46 | else { 47 | write(31); 48 | } 49 | } 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /project3/test/test_3_r03.spl: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int N = 30; 3 | int num = 0, i = 1, k = 1; 4 | while(k <= N){ 5 | while(i <= k){ 6 | if(k == (k / i * i)) 7 | num = num + 1; 8 | i = i + 1; 9 | } 10 | if(num == 2) 11 | write(k); 12 | i = 1; 13 | num = 0; 14 | k = k +1; 15 | } 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /project3/test/test_3_r04.spl: -------------------------------------------------------------------------------- 1 | int sqr(int i1){ 2 | return i1*i1; 3 | } 4 | int cbc(int i2){ 5 | return i2*i2*i2; 6 | } 7 | 8 | int main(){ 9 | int a, r; 10 | a = read(); 11 | write(a); 12 | r = sqr(a); 13 | write(r); 14 | r = cbc(a); 15 | write(r); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /project3/test/test_3_r05.spl: -------------------------------------------------------------------------------- 1 | int foo(int i, int j, int k){ 2 | return i - j + k*2; 3 | } 4 | 5 | int main(){ 6 | int a = 110; 7 | int b = 97; 8 | int c = 3; 9 | c = foo(a,b,c); 10 | write(c); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /project3/test/test_3_r06.spl: -------------------------------------------------------------------------------- 1 | int hanoi(int n, int p1, int p2, int p3){ 2 | if(n == 1){ 3 | write(p1*1000000+p3); 4 | } 5 | else{ 6 | hanoi(n-1,p1,p3,p2); 7 | write(p1*1000000+p3); 8 | hanoi(n-1,p2,p1,p3); 9 | } 10 | return 0; 11 | } 12 | int main(){ 13 | int sum = 3; 14 | hanoi(sum, 1, 2, 3); 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /project3/test/test_3_r07.spl: -------------------------------------------------------------------------------- 1 | int gcd1(int a, int b) 2 | { 3 | int result; 4 | int temp; 5 | temp = a - a/ b * b; 6 | while (temp != 0) { 7 | a = b; 8 | b = temp; 9 | temp = a - a / b * b; 10 | } 11 | result = b; 12 | return result; 13 | } 14 | int gcd2(int x, int y) 15 | { 16 | int remainder = 0; 17 | if(x > y){ 18 | remainder = x - x / y * y; 19 | if(remainder == 0) 20 | return y; 21 | else 22 | return gcd2(y, remainder); 23 | } 24 | else { 25 | remainder = y - y / x * x; 26 | if(remainder == 0) 27 | return x; 28 | else 29 | return gcd2(x, remainder); 30 | } 31 | } 32 | 33 | int main() 34 | { 35 | int m = read(); 36 | int n = read(); 37 | write(gcd1(m,n)); 38 | write(gcd2(m,n)); 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /project3/test/test_3_r08.spl: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | int n; 4 | n = read(); 5 | if (n > 0) write(1); 6 | else if (n < 0) write (-1); 7 | else write(0); 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /project3/test/test_3_r09.spl: -------------------------------------------------------------------------------- 1 | int mod(int number2, int m2) 2 | { 3 | int result = number2 - number2 / m2 * m2; 4 | int result2 = result; 5 | return result; 6 | } 7 | 8 | int power(int base1, int p1) { 9 | int ret1 = 1 + p1 - p1; 10 | while(p1 > (ret1 - ret1 + 90 - 89 + 1 - 2)) 11 | { 12 | ret1 = ret1 * base1; 13 | p1 = 2 * 1 * p1 - 1 * p1 - 1; 14 | } 15 | return ret1; 16 | } 17 | 18 | int getNumDigits(int number3) 19 | { 20 | int ret3 = 0; 21 | if(number3 < 0) 22 | return -1; 23 | while(number3 > 0) { 24 | number3 = number3 / 10; 25 | ret3 = ret3 + 2; 26 | ret3 = ret3 + 2; 27 | ret3 = ret3 - 3; 28 | } 29 | return ret3; 30 | } 31 | 32 | int isNarcissistic(int number4) 33 | { 34 | int numDigits4 = getNumDigits(1 + number4 - 1); 35 | int sum4 = 0; 36 | int n4 = number4; 37 | int s4; 38 | while(n4>0) { 39 | s4 = mod(n4, 10); 40 | n4 = (n4 - s4) / 10; 41 | sum4 = sum4 + power(s4, numDigits4); 42 | } 43 | 44 | if(sum4 == number4) 45 | return 1; 46 | else 47 | return 0; 48 | } 49 | 50 | int main() { 51 | int count = 0; 52 | int i = 300; 53 | while(i < 500) 54 | { 55 | if(isNarcissistic(i) == 1) 56 | { 57 | write(i); 58 | count = count + 1; 59 | } 60 | i = i + 1; 61 | } 62 | write(count); 63 | return count; 64 | } 65 | -------------------------------------------------------------------------------- /project3/test/test_3_r10.spl: -------------------------------------------------------------------------------- 1 | int fact(int n) 2 | { 3 | if (n == 1) 4 | return n; 5 | else 6 | return (n * fact(n-1)); 7 | } 8 | int main() 9 | { 10 | int m, result; 11 | m = read(); 12 | if (m > 1) 13 | result = fact(m); 14 | else 15 | result = 1; 16 | write(result); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /project4/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | BIN=bin 3 | SRC=main.c tac.c mips32.c 4 | 5 | splc: clean 6 | @mkdir -p $(BIN) 7 | $(CC) $(SRC) -o $(BIN)/$@ 8 | clean: 9 | @rm -rf $(BIN) 10 | .PHONY: clean 11 | -------------------------------------------------------------------------------- /project4/main.c: -------------------------------------------------------------------------------- 1 | #include "tac.h" 2 | #include "mips32.h" 3 | 4 | #define BUF_SIZE 0x10000 5 | 6 | char buf[BUF_SIZE]; 7 | 8 | int main(int argc, char *argv[]){ 9 | FILE *fp; 10 | tac *head; 11 | char c, *file; 12 | int size, len; 13 | 14 | if(argc != 2){ 15 | fprintf(stderr, "Usage:\n"); 16 | fprintf(stderr, " %s \n", argv[0]); 17 | return 1; 18 | } 19 | file = argv[1]; 20 | 21 | // read the IR code 22 | size = 0; 23 | fp = fopen(file, "r"); 24 | while ((c = getc(fp)) != EOF) 25 | buf[size++] = c; 26 | buf[size] = '\x7f'; 27 | fclose(fp); 28 | 29 | // write the target code 30 | len = strlen(file); 31 | file[len-2] = 's'; 32 | file[len-1] = '\0'; 33 | fp = stdout; // fopen(file, "w"); 34 | head = tac_from_buffer(buf); 35 | mips32_gen(head, fp); 36 | // fclose(fp); 37 | 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /project4/mips32.c: -------------------------------------------------------------------------------- 1 | #include "mips32.h" 2 | 3 | /* the output file descriptor, may not be explicitly used */ 4 | FILE *fd; 5 | 6 | #define _tac_kind(tac) (((tac)->code).kind) 7 | #define _tac_quadruple(tac) (((tac)->code).tac) 8 | #define _reg_name(reg) regs[reg].name 9 | 10 | 11 | Register get_register(tac_opd *opd){ 12 | assert(opd->kind == OP_VARIABLE); 13 | char *var = opd->char_val; 14 | /* COMPLETE the register allocation */ 15 | return t0; 16 | } 17 | 18 | Register get_register_w(tac_opd *opd){ 19 | assert(opd->kind == OP_VARIABLE); 20 | char *var = opd->char_val; 21 | /* COMPLETE the register allocation (for write) */ 22 | return s0; 23 | } 24 | 25 | void spill_register(Register reg){ 26 | /* COMPLETE the register spilling */ 27 | } 28 | 29 | 30 | void _mips_printf(const char *fmt, ...){ 31 | va_list args; 32 | va_start(args, fmt); 33 | vfprintf(fd, fmt, args); 34 | va_end(args); 35 | fputs("\n", fd); 36 | } 37 | 38 | void _mips_iprintf(const char *fmt, ...){ 39 | va_list args; 40 | fputs(" ", fd); // `iprintf` stands for indented printf 41 | va_start(args, fmt); 42 | vfprintf(fd, fmt, args); 43 | va_end(args); 44 | fputs("\n", fd); 45 | } 46 | 47 | 48 | /* PARAM: a pointer to `struct tac_node` instance 49 | RETURN: the next instruction to be translated */ 50 | tac *emit_label(tac *label){ 51 | assert(_tac_kind(label) == LABEL); 52 | _mips_printf("label%d:", _tac_quadruple(label).labelno->int_val); 53 | return label->next; 54 | } 55 | 56 | tac *emit_function(tac *function){ 57 | _mips_printf("%s:", _tac_quadruple(function).funcname); 58 | return function->next; 59 | } 60 | 61 | tac *emit_assign(tac *assign){ 62 | Register x, y; 63 | 64 | x = get_register_w(_tac_quadruple(assign).left); 65 | if(_tac_quadruple(assign).right->kind == OP_CONSTANT){ 66 | _mips_iprintf("li %s, %d", _reg_name(x), 67 | _tac_quadruple(assign).right->int_val); 68 | } 69 | else{ 70 | y = get_register(_tac_quadruple(assign).right); 71 | _mips_iprintf("move %s, %s", _reg_name(x), _reg_name(y)); 72 | } 73 | return assign->next; 74 | } 75 | 76 | tac *emit_add(tac *add){ 77 | Register x, y, z; 78 | 79 | x = get_register_w(_tac_quadruple(add).left); 80 | if(_tac_quadruple(add).r1->kind == OP_CONSTANT){ 81 | y = get_register(_tac_quadruple(add).r2); 82 | _mips_iprintf("addi %s, %s, %d", _reg_name(x), 83 | _reg_name(y), 84 | _tac_quadruple(add).r1->int_val); 85 | } 86 | else if(_tac_quadruple(add).r2->kind == OP_CONSTANT){ 87 | y = get_register(_tac_quadruple(add).r1); 88 | _mips_iprintf("addi %s, %s, %d", _reg_name(x), 89 | _reg_name(y), 90 | _tac_quadruple(add).r2->int_val); 91 | } 92 | else{ 93 | y = get_register(_tac_quadruple(add).r1); 94 | z = get_register(_tac_quadruple(add).r2); 95 | _mips_iprintf("add %s, %s, %s", _reg_name(x), 96 | _reg_name(y), 97 | _reg_name(z)); 98 | } 99 | return add->next; 100 | } 101 | 102 | tac *emit_sub(tac *sub){ 103 | Register x, y, z; 104 | 105 | x = get_register_w(_tac_quadruple(sub).left); 106 | if(_tac_quadruple(sub).r1->kind == OP_CONSTANT){ 107 | y = get_register(_tac_quadruple(sub).r2); 108 | _mips_iprintf("neg %s, %s", _reg_name(y), _reg_name(y)); 109 | _mips_iprintf("addi %s, %s, %d", _reg_name(x), 110 | _reg_name(y), 111 | _tac_quadruple(sub).r1->int_val); 112 | } 113 | else if(_tac_quadruple(sub).r2->kind == OP_CONSTANT){ 114 | y = get_register(_tac_quadruple(sub).r1); 115 | _mips_iprintf("addi %s, %s, -%d", _reg_name(x), 116 | _reg_name(y), 117 | _tac_quadruple(sub).r2->int_val); 118 | } 119 | else{ 120 | y = get_register(_tac_quadruple(sub).r1); 121 | z = get_register(_tac_quadruple(sub).r2); 122 | _mips_iprintf("sub %s, %s, %s", _reg_name(x), 123 | _reg_name(y), 124 | _reg_name(z)); 125 | } 126 | return sub->next; 127 | } 128 | 129 | tac *emit_mul(tac *mul){ 130 | Register x, y, z; 131 | 132 | x = get_register_w(_tac_quadruple(mul).left); 133 | if(_tac_quadruple(mul).r1->kind == OP_CONSTANT){ 134 | y = get_register_w(_tac_quadruple(mul).r1); 135 | z = get_register(_tac_quadruple(mul).r2); 136 | _mips_iprintf("lw %s, %d", _reg_name(y), 137 | _tac_quadruple(mul).r1->int_val); 138 | } 139 | else if(_tac_quadruple(mul).r2->kind == OP_CONSTANT){ 140 | y = get_register(_tac_quadruple(mul).r1); 141 | z = get_register_w(_tac_quadruple(mul).r2); 142 | _mips_iprintf("lw %s, %d", _reg_name(z), 143 | _tac_quadruple(mul).r2->int_val); 144 | } 145 | else{ 146 | y = get_register(_tac_quadruple(mul).r1); 147 | z = get_register(_tac_quadruple(mul).r2); 148 | } 149 | _mips_iprintf("mul %s, %s, %s", _reg_name(x), 150 | _reg_name(y), 151 | _reg_name(z)); 152 | return mul->next; 153 | } 154 | 155 | tac *emit_div(tac *div){ 156 | Register x, y, z; 157 | 158 | x = get_register_w(_tac_quadruple(div).left); 159 | if(_tac_quadruple(div).r1->kind == OP_CONSTANT){ 160 | y = get_register_w(_tac_quadruple(div).r1); 161 | z = get_register(_tac_quadruple(div).r2); 162 | _mips_iprintf("lw %s, %d", _reg_name(y), 163 | _tac_quadruple(div).r1->int_val); 164 | } 165 | else if(_tac_quadruple(div).r2->kind == OP_CONSTANT){ 166 | y = get_register(_tac_quadruple(div).r1); 167 | z = get_register_w(_tac_quadruple(div).r2); 168 | _mips_iprintf("lw %s, %d", _reg_name(z), 169 | _tac_quadruple(div).r2->int_val); 170 | } 171 | else{ 172 | y = get_register(_tac_quadruple(div).r1); 173 | z = get_register(_tac_quadruple(div).r2); 174 | } 175 | _mips_iprintf("div %s, %s", _reg_name(y), _reg_name(z)); 176 | _mips_iprintf("mflo %s", _reg_name(x)); 177 | return div->next; 178 | } 179 | 180 | tac *emit_addr(tac *addr){ 181 | Register x, y; 182 | 183 | x = get_register_w(_tac_quadruple(addr).left); 184 | y = get_register(_tac_quadruple(addr).right); 185 | _mips_iprintf("move %s, %s", _reg_name(x), _reg_name(y)); 186 | return addr->next; 187 | } 188 | 189 | tac *emit_fetch(tac *fetch){ 190 | Register x, y; 191 | 192 | x = get_register_w(_tac_quadruple(fetch).left); 193 | y = get_register(_tac_quadruple(fetch).raddr); 194 | _mips_iprintf("lw %s, 0(%s)", _reg_name(x), _reg_name(y)); 195 | return fetch->next; 196 | } 197 | 198 | tac *emit_deref(tac *deref){ 199 | Register x, y; 200 | 201 | x = get_register(_tac_quadruple(deref).laddr); 202 | y = get_register(_tac_quadruple(deref).right); 203 | _mips_iprintf("sw %s, 0(%s)", _reg_name(y), _reg_name(x)); 204 | return deref->next; 205 | } 206 | 207 | tac *emit_goto(tac *goto_){ 208 | _mips_iprintf("j label%d", _tac_quadruple(goto_).labelno->int_val); 209 | return goto_->next; 210 | } 211 | 212 | tac *emit_iflt(tac *iflt){ 213 | /* COMPLETE emit function */ 214 | return iflt->next; 215 | } 216 | 217 | tac *emit_ifle(tac *ifle){ 218 | /* COMPLETE emit function */ 219 | return ifle->next; 220 | } 221 | 222 | tac *emit_ifgt(tac *ifgt){ 223 | /* COMPLETE emit function */ 224 | return ifgt->next; 225 | } 226 | 227 | tac *emit_ifge(tac *ifge){ 228 | /* COMPLETE emit function */ 229 | return ifge->next; 230 | } 231 | 232 | tac *emit_ifne(tac *ifne){ 233 | /* COMPLETE emit function */ 234 | return ifne->next; 235 | } 236 | 237 | tac *emit_ifeq(tac *ifeq){ 238 | /* COMPLETE emit function */ 239 | return ifeq->next; 240 | } 241 | 242 | tac *emit_return(tac *return_){ 243 | /* COMPLETE emit function */ 244 | return return_->next; 245 | } 246 | 247 | tac *emit_dec(tac *dec){ 248 | /* NO NEED TO IMPLEMENT */ 249 | return dec->next; 250 | } 251 | 252 | tac *emit_arg(tac *arg){ 253 | /* COMPLETE emit function */ 254 | return arg->next; 255 | } 256 | 257 | tac *emit_call(tac *call){ 258 | /* COMPLETE emit function */ 259 | return call->next; 260 | } 261 | 262 | tac *emit_param(tac *param){ 263 | /* COMPLETE emit function */ 264 | return param->next; 265 | } 266 | 267 | tac *emit_read(tac *read){ 268 | Register x = get_register(_tac_quadruple(read).p); 269 | 270 | _mips_iprintf("addi $sp, $sp, -4"); 271 | _mips_iprintf("sw $ra, 0($sp)"); 272 | _mips_iprintf("jal read"); 273 | _mips_iprintf("lw $ra, 0($sp)"); 274 | _mips_iprintf("addi $sp, $sp, 4"); 275 | _mips_iprintf("move %s, $v0", _reg_name(x)); 276 | return read->next; 277 | } 278 | 279 | tac *emit_write(tac *write){ 280 | Register x = get_register_w(_tac_quadruple(write).p); 281 | 282 | _mips_iprintf("move $a0, %s", _reg_name(x)); 283 | _mips_iprintf("addi $sp, $sp, -4"); 284 | _mips_iprintf("sw $ra, 0($sp)"); 285 | _mips_iprintf("jal write"); 286 | _mips_iprintf("lw $ra, 0($sp)"); 287 | _mips_iprintf("addi $sp, $sp, 4"); 288 | return write->next; 289 | } 290 | 291 | void emit_preamble(){ 292 | _mips_printf("# SPL compiler generated assembly"); 293 | _mips_printf(".data"); 294 | _mips_printf("_prmpt: .asciiz \"Enter an integer: \""); 295 | _mips_printf("_eol: .asciiz \"\\n\""); 296 | _mips_printf(".globl main"); 297 | _mips_printf(".text"); 298 | } 299 | 300 | void emit_read_function(){ 301 | _mips_printf("read:"); 302 | _mips_iprintf("li $v0, 4"); 303 | _mips_iprintf("la $a0, _prmpt"); 304 | _mips_iprintf("syscall"); 305 | _mips_iprintf("li $v0, 5"); 306 | _mips_iprintf("syscall"); 307 | _mips_iprintf("jr $ra"); 308 | } 309 | 310 | void emit_write_function(){ 311 | _mips_printf("write:"); 312 | _mips_iprintf("li $v0, 1"); 313 | _mips_iprintf("syscall"); 314 | _mips_iprintf("li $v0, 4"); 315 | _mips_iprintf("la $a0, _eol"); 316 | _mips_iprintf("syscall"); 317 | _mips_iprintf("move $v0, $0"); 318 | _mips_iprintf("jr $ra"); 319 | } 320 | 321 | static tac* (*emitter[])(tac*) = { 322 | emit_label, emit_function, emit_assign, 323 | emit_add, emit_sub, emit_mul, emit_div, 324 | emit_addr, emit_fetch, emit_deref, emit_goto, 325 | emit_iflt, emit_ifle, emit_ifgt, emit_ifge, emit_ifne, emit_ifeq, 326 | emit_return, emit_dec, emit_arg, emit_call, emit_param, 327 | emit_read, emit_write 328 | }; 329 | 330 | tac *emit_code(tac *head){ 331 | tac *(*tac_emitter)(tac*); 332 | tac *tac_code = head; 333 | emit_preamble(); 334 | emit_read_function(); 335 | emit_write_function(); 336 | while(tac_code != NULL){ 337 | if(_tac_kind(tac_code) != NONE){ 338 | tac_emitter = emitter[_tac_kind(tac_code)]; 339 | tac_code = tac_emitter(tac_code); 340 | } 341 | else{ 342 | tac_code = tac_code->next; 343 | } 344 | } 345 | } 346 | 347 | /* translate a TAC list into mips32 assembly 348 | output the textual assembly code to _fd */ 349 | void mips32_gen(tac *head, FILE *_fd){ 350 | regs[zero].name = "$zero"; 351 | regs[at].name = "$at"; 352 | regs[v0].name = "$v0"; regs[v1].name = "$v1"; 353 | regs[a0].name = "$a0"; regs[a1].name = "$a1"; 354 | regs[a2].name = "$a2"; regs[a3].name = "$a3"; 355 | regs[t0].name = "$t0"; regs[t1].name = "$t1"; 356 | regs[t2].name = "$t2"; regs[t3].name = "$t3"; 357 | regs[t4].name = "$t4"; regs[t5].name = "$t5"; 358 | regs[t6].name = "$t6"; regs[t7].name = "$t7"; 359 | regs[s0].name = "$s0"; regs[s1].name = "$s1"; 360 | regs[s2].name = "$s2"; regs[s3].name = "$s3"; 361 | regs[s4].name = "$s4"; regs[s5].name = "$s5"; 362 | regs[s6].name = "$s6"; regs[s7].name = "$s7"; 363 | regs[t8].name = "$t8"; regs[t9].name = "$t9"; 364 | regs[k0].name = "$k0"; regs[k1].name = "$k1"; 365 | regs[gp].name = "$gp"; 366 | regs[sp].name = "$sp"; regs[fp].name = "$fp"; 367 | regs[ra].name = "$ra"; 368 | vars = (struct VarDesc*)malloc(sizeof(struct VarDesc)); 369 | vars->next = NULL; 370 | fd = _fd; 371 | emit_code(head); 372 | } 373 | -------------------------------------------------------------------------------- /project4/mips32.h: -------------------------------------------------------------------------------- 1 | #ifndef MIPS_H 2 | #define MIPS_H 3 | 4 | #include "tac.h" 5 | #define FALSE 0 6 | #define TRUE 1 7 | typedef unsigned char bool; 8 | 9 | typedef enum { 10 | zero, at, v0, v1, a0, a1, a2, a3, 11 | t0, t1, t2, t3, t4, t5, t6, t7, 12 | s0, s1, s2, s3, s4, s5, s6, s7, 13 | t8, t9, k0, k1, gp, sp, fp, ra, NUM_REGS 14 | } Register; 15 | 16 | 17 | struct RegDesc { // the register descriptor 18 | const char *name; 19 | char var[8]; 20 | bool dirty; // value updated but not stored 21 | /* add other fields as you need */ 22 | } regs[NUM_REGS]; 23 | 24 | 25 | struct VarDesc { // the variable descriptor 26 | char var[8]; 27 | Register reg; 28 | int offset; // the offset from stack 29 | /* add other fields as you need */ 30 | struct VarDesc *next; 31 | } *vars; 32 | 33 | 34 | void mips32_gen(tac *head, FILE *_fd); 35 | 36 | #endif // MIPS_H 37 | -------------------------------------------------------------------------------- /project4/sample/test_4_fact.ir: -------------------------------------------------------------------------------- 1 | FUNCTION fact : 2 | PARAM v1 3 | IF v1 == #1 GOTO label1 4 | GOTO label2 5 | LABEL label1 : 6 | RETURN v1 7 | LABEL label2 : 8 | t1 := v1 - #1 9 | ARG t1 10 | t2 := CALL fact 11 | t3 := v1 * t2 12 | RETURN t3 13 | 14 | FUNCTION main : 15 | READ t4 16 | v2 := t4 17 | IF v2 > #1 GOTO label3 18 | GOTO label4 19 | LABEL label3 : 20 | ARG v2 21 | t5 := CALL fact 22 | v3 := t5 23 | GOTO label5 24 | LABEL label4 : 25 | v3 := #1 26 | LABEL label5 : 27 | WRITE v3 28 | RETURN #0 29 | -------------------------------------------------------------------------------- /project4/sample/test_4_fact.s: -------------------------------------------------------------------------------- 1 | .data 2 | _prompt: .asciiz "Enter an integer:" 3 | _ret: .asciiz "\n" 4 | .globl main 5 | .text 6 | read: 7 | li $v0, 4 8 | la $a0, _prompt 9 | syscall 10 | li $v0, 5 11 | syscall 12 | jr $ra 13 | write: 14 | li $v0, 1 15 | syscall 16 | li $v0, 4 17 | la $a0, _ret 18 | syscall 19 | move $v0, $0 20 | jr $ra 21 | 22 | fact: 23 | li $t4, 1 24 | beq $a0, $t4, label1 25 | j label2 26 | label1: 27 | move $v0, $a0 28 | jr $ra 29 | label2: 30 | addi $sp, $sp, -8 31 | sw $a0, ($sp) 32 | sw $ra, 4($sp) 33 | sub $a0, $a0, 1 34 | jal fact 35 | lw $a0, ($sp) 36 | lw $ra, 4($sp) 37 | addi $sp, $sp, 8 38 | mul $v0, $v0, $a0 39 | jr $ra 40 | 41 | main: 42 | addi $sp, $sp, -4 43 | sw $ra, 0($sp) 44 | jal read 45 | lw $ra, 0($sp) 46 | addi $sp, $sp, 4 47 | move $t1, $v0 48 | li $t3, 1 49 | bgt $t1, $t3, label6 50 | j label7 51 | label6: 52 | move $a0, $t1 53 | addi $sp, $sp, -4 54 | sw $ra, 0($sp) 55 | jal fact 56 | lw $ra, 0($sp) 57 | addi $sp, $sp, 4 58 | move $t2, $v0 59 | j label8 60 | label7: 61 | li $t2, 1 62 | label8: 63 | move $a0, $t2 64 | addi $sp, $sp, -4 65 | sw $ra, 0($sp) 66 | jal write 67 | lw $ra, 0($sp) 68 | addi $sp, $sp, 4 69 | move $v0, $0 70 | jr $ra 71 | -------------------------------------------------------------------------------- /project4/sample/test_4_fact.spl: -------------------------------------------------------------------------------- 1 | int fact(int n) 2 | { 3 | if (n == 1) 4 | return n; 5 | else 6 | return (n * fact(n-1)); 7 | } 8 | 9 | int main() 10 | { 11 | int m, result; 12 | m = read(); 13 | if (m > 1) 14 | result = fact(m); 15 | else 16 | result = 1; 17 | write(result); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /project4/tac.c: -------------------------------------------------------------------------------- 1 | #include "tac.h" 2 | 3 | /***************************************************************** 4 | ####################### STOP HERE ######################### 5 | The code below is related to the intermediate code 6 | generation, they are not helpful to you in project 4. 7 | ####################### STOP HERE ######################### 8 | *****************************************************************/ 9 | 10 | char *_str_trim(char *str) { 11 | // from: https://stackoverflow.com/questions/122616/ 12 | char *end; 13 | 14 | // Trim leading space 15 | while(isspace((unsigned char)*str)) 16 | str++; 17 | 18 | if(*str == 0) // All spaces? 19 | return str; 20 | 21 | // Trim trailing space 22 | end = str + strlen(str) - 1; 23 | while(end > str && isspace((unsigned char)*end)) 24 | end--; 25 | 26 | // Write new null terminator character 27 | end[1] = '\0'; 28 | return str; 29 | } 30 | 31 | char** _str_split(char* str, const char delim, int *n) { 32 | // from: https://stackoverflow.com/questions/9210528/ 33 | char** result = 0; 34 | size_t count = 0; 35 | char* tmp = str; 36 | char* last_comma = 0; 37 | char delims[2]; 38 | delims[0] = delim; 39 | delims[1] = 0; 40 | 41 | /* Count how many elements will be extracted. */ 42 | while (*tmp) { 43 | if (delim == *tmp) { 44 | count++; 45 | last_comma = tmp; 46 | } 47 | tmp++; 48 | } 49 | /* Add space for trailing token. */ 50 | count += last_comma < (str + strlen(str) - 1); 51 | *n = count; 52 | 53 | result = malloc(sizeof(char*) * count); 54 | if (result) { 55 | size_t idx = 0; 56 | char* token = strtok(str, delims); 57 | 58 | while (token) { 59 | assert(idx < count); 60 | *(result + idx++) = strdup(token); 61 | token = strtok(0, delims); 62 | } 63 | assert(idx == count); 64 | *(result + idx) = 0; 65 | } 66 | return result; 67 | } 68 | 69 | tac_opd *_tac_opd_from_str(char *tk){ 70 | int i; 71 | 72 | if(tk[0] == '#'){ 73 | i = atoi(tk+1); 74 | return tac_opd_constant(i); 75 | } 76 | else if(tk[0] == '&'){ 77 | return tac_opd_pointer(tk+1); 78 | } 79 | else if(memcmp(tk, "label", 5) == 0){ 80 | i = atoi(tk+5); 81 | return tac_opd_label(i); 82 | } 83 | else{ 84 | return tac_opd_variable(tk); 85 | } 86 | } 87 | 88 | tac *_tac_from_line(char *ln){ 89 | tac_opd *t1, *t2, *t3; 90 | tac *code; 91 | char **tokens; 92 | int i, count; 93 | 94 | ln = _str_trim(ln); 95 | tokens = _str_split(ln, ' ', &count); 96 | 97 | if(count == 2){ 98 | code = tac_init_none(); 99 | t1 = _tac_opd_from_str(tokens[1]); 100 | if(strcmp(tokens[0], "GOTO") == 0) 101 | code = tac_init_goto(t1); 102 | else if(strcmp(tokens[0], "RETURN") == 0) 103 | code = tac_init_return(t1); 104 | else if(strcmp(tokens[0], "ARG") == 0) 105 | code = tac_init_arg(t1); 106 | else if(strcmp(tokens[0], "PARAM") == 0) 107 | code = tac_init_param(t1); 108 | else if(strcmp(tokens[0], "READ") == 0) 109 | code = tac_init_read(t1); 110 | else if(strcmp(tokens[0], "WRITE") == 0) 111 | code = tac_init_write(t1); 112 | else 113 | assert(0); 114 | } 115 | else if(count == 3){ 116 | if(strcmp(tokens[0], "LABEL") == 0){ 117 | t1 = _tac_opd_from_str(tokens[1]); 118 | code = tac_init_label(t1); 119 | } 120 | else if(strcmp(tokens[0], "FUNCTION") == 0){ 121 | code = tac_init_function(tokens[1]); 122 | } 123 | else if(strcmp(tokens[0], "DEC") == 0){ 124 | t1 = tac_opd_pointer(tokens[1]); 125 | i = atoi(tokens[2]); 126 | code = tac_init_dec(t1, i); 127 | } 128 | else{ 129 | if(tokens[0][0] == '*'){ 130 | t1 = _tac_opd_from_str(tokens[0]+1); 131 | t2 = _tac_opd_from_str(tokens[2]); 132 | code = tac_init_deref(t1, t2); 133 | } 134 | else if(tokens[2][0] == '*'){ 135 | t1 = _tac_opd_from_str(tokens[0]); 136 | t2 = _tac_opd_from_str(tokens[2]+1); 137 | code = tac_init_fetch(t1, t2); 138 | } 139 | else if(tokens[2][0] == '&'){ 140 | t1 = _tac_opd_from_str(tokens[0]); 141 | t2 = _tac_opd_from_str(tokens[2]); 142 | code = tac_init_addr(t1, t2); 143 | } 144 | else{ 145 | t1 = _tac_opd_from_str(tokens[0]); 146 | t2 = _tac_opd_from_str(tokens[2]); 147 | code = tac_init_assign(t1, t2); 148 | } 149 | } 150 | } 151 | else if(count == 4){ 152 | t1 = _tac_opd_from_str(tokens[0]); 153 | code = tac_init_call(t1, tokens[3]); 154 | } 155 | else if(count == 5){ 156 | t1 = _tac_opd_from_str(tokens[0]); 157 | t2 = _tac_opd_from_str(tokens[2]); 158 | t3 = _tac_opd_from_str(tokens[4]); 159 | switch(tokens[3][0]){ 160 | case '+': 161 | code = tac_init_add(t1, t2, t3); 162 | break; 163 | case '-': 164 | code = tac_init_sub(t1, t2, t3); 165 | break; 166 | case '*': 167 | code = tac_init_mul(t1, t2, t3); 168 | break; 169 | case '/': 170 | code = tac_init_div(t1, t2, t3); 171 | break; 172 | } 173 | } 174 | else{ // count == 6 175 | t1 = _tac_opd_from_str(tokens[1]); 176 | t2 = _tac_opd_from_str(tokens[3]); 177 | t3 = _tac_opd_from_str(tokens[5]); 178 | if(strlen(tokens[2]) == 1){ 179 | if(tokens[2][0] == '<') 180 | code = tac_init_iflt(t1, t2, t3); 181 | else // > 182 | code = tac_init_ifgt(t1, t2, t3); 183 | } 184 | else{ // == 2 185 | if(tokens[2][0] == '<') 186 | code = tac_init_ifle(t1, t2, t3); 187 | else if(tokens[2][0] == '>') 188 | code = tac_init_ifge(t1, t2, t3); 189 | else if(tokens[2][0] == '!') 190 | code = tac_init_ifne(t1, t2, t3); 191 | else // == 192 | code = tac_init_ifeq(t1, t2, t3); 193 | } 194 | } 195 | 196 | free(tokens); 197 | return code; 198 | } 199 | 200 | tac *tac_from_buffer(char *buf){ 201 | tac *self, *inst; 202 | char lnbuf[64]; 203 | int buf_i, i; 204 | 205 | self = tac_init_none(); 206 | for(buf_i = i = 0; buf[buf_i] != '\x7f'; buf_i++){ 207 | if(buf[buf_i] != '\n'){ 208 | lnbuf[i++] = buf[buf_i]; 209 | } 210 | else{ 211 | lnbuf[i] = '\0'; 212 | inst = _tac_from_line(lnbuf); 213 | tac_append(self, inst); 214 | i = 0; 215 | } 216 | } 217 | return self; 218 | } 219 | 220 | void tac_opd_print(tac_opd *self, FILE *fd){ 221 | switch(self->kind){ 222 | case OP_LABEL: 223 | fprintf(fd, "label%d", self->int_val); 224 | break; 225 | case OP_VARIABLE: 226 | fprintf(fd, "%s", self->char_val); 227 | break; 228 | case OP_CONSTANT: 229 | fprintf(fd, "#%d", self->int_val); 230 | break; 231 | case OP_POINTER: 232 | fprintf(fd, "&%s", self->char_val); 233 | break; 234 | } 235 | } 236 | 237 | tac_opd *tac_opd_label(int lval){ 238 | tac_opd *self = (tac_opd*)malloc(sizeof(tac_opd)); 239 | self->kind = OP_LABEL; 240 | self->int_val = lval; 241 | return self; 242 | } 243 | 244 | tac_opd *tac_opd_variable(char *vname){ 245 | tac_opd *self = (tac_opd*)malloc(sizeof(tac_opd)); 246 | self->kind = OP_VARIABLE; 247 | sprintf(self->char_val, "%s", vname); 248 | return self; 249 | } 250 | 251 | tac_opd *tac_opd_constant(int cval){ 252 | tac_opd *self = (tac_opd*)malloc(sizeof(tac_opd)); 253 | self->kind = OP_CONSTANT; 254 | self->int_val = cval; 255 | return self; 256 | } 257 | 258 | tac_opd *tac_opd_pointer(char *pname){ 259 | tac_opd *self = (tac_opd*)malloc(sizeof(tac_opd)); 260 | self->kind = OP_POINTER; 261 | sprintf(self->char_val, "%s", pname); 262 | return self; 263 | } 264 | 265 | void tac_print(tac *head, FILE *fd){ 266 | tac *p = head; 267 | while(p != NULL){ 268 | switch(p->code.kind){ 269 | case LABEL: 270 | fprintf(fd, "LABEL "); 271 | tac_opd_print(p->code.label.labelno, fd); 272 | fprintf(fd, " :\n"); 273 | break; 274 | case FUNCTION: 275 | fprintf(fd, "FUNCTION %s :\n", p->code.function.funcname); 276 | break; 277 | case ASSIGN: 278 | tac_opd_print(p->code.assign.left, fd); 279 | fprintf(fd, " := "); 280 | tac_opd_print(p->code.assign.right, fd); 281 | fprintf(fd, "\n"); 282 | break; 283 | case ADD: 284 | tac_opd_print(p->code.add.left, fd); 285 | fprintf(fd, " := "); 286 | tac_opd_print(p->code.add.r1, fd); 287 | fprintf(fd, " + "); 288 | tac_opd_print(p->code.add.r2, fd); 289 | fprintf(fd, "\n"); 290 | break; 291 | case SUB: 292 | tac_opd_print(p->code.sub.left, fd); 293 | fprintf(fd, " := "); 294 | tac_opd_print(p->code.sub.r1, fd); 295 | fprintf(fd, " - "); 296 | tac_opd_print(p->code.sub.r2, fd); 297 | fprintf(fd, "\n"); 298 | break; 299 | case MUL: 300 | tac_opd_print(p->code.mul.left, fd); 301 | fprintf(fd, " := "); 302 | tac_opd_print(p->code.mul.r1, fd); 303 | fprintf(fd, " * "); 304 | tac_opd_print(p->code.mul.r2, fd); 305 | fprintf(fd, "\n"); 306 | break; 307 | case DIV: 308 | tac_opd_print(p->code.div.left, fd); 309 | fprintf(fd, " := "); 310 | tac_opd_print(p->code.div.r1, fd); 311 | fprintf(fd, " / "); 312 | tac_opd_print(p->code.div.r2, fd); 313 | fprintf(fd, "\n"); 314 | break; 315 | case ADDR: 316 | fprintf(fd, "%s := &%s\n", p->code.addr.left->char_val, p->code.addr.right->char_val); 317 | break; 318 | case FETCH: 319 | fprintf(fd, "%s := *%s\n", p->code.fetch.left->char_val, p->code.fetch.raddr->char_val); 320 | break; 321 | case DEREF: 322 | fprintf(fd, "*%s := ", p->code.deref.laddr->char_val); 323 | tac_opd_print(p->code.deref.right, fd); 324 | fprintf(fd, "\n"); 325 | break; 326 | case GOTO: 327 | fprintf(fd, "GOTO "); 328 | tac_opd_print(p->code.goto_.labelno, fd); 329 | fprintf(fd, "\n"); 330 | break; 331 | case IFLT: 332 | fprintf(fd, "IF "); 333 | tac_opd_print(p->code.iflt.c1, fd); 334 | fprintf(fd, " < "); 335 | tac_opd_print(p->code.iflt.c2, fd); 336 | fprintf(fd, " GOTO "); 337 | tac_opd_print(p->code.iflt.labelno, fd); 338 | fprintf(fd, "\n"); 339 | break; 340 | case IFLE: 341 | fprintf(fd, "IF "); 342 | tac_opd_print(p->code.ifle.c1, fd); 343 | fprintf(fd, " <= "); 344 | tac_opd_print(p->code.ifle.c2, fd); 345 | fprintf(fd, " GOTO "); 346 | tac_opd_print(p->code.ifle.labelno, fd); 347 | fprintf(fd, "\n"); 348 | break; 349 | case IFGT: 350 | fprintf(fd, "IF "); 351 | tac_opd_print(p->code.ifgt.c1, fd); 352 | fprintf(fd, " > "); 353 | tac_opd_print(p->code.ifgt.c2, fd); 354 | fprintf(fd, " GOTO "); 355 | tac_opd_print(p->code.ifgt.labelno, fd); 356 | fprintf(fd, "\n"); 357 | break; 358 | case IFGE: 359 | fprintf(fd, "IF "); 360 | tac_opd_print(p->code.ifge.c1, fd); 361 | fprintf(fd, " >= "); 362 | tac_opd_print(p->code.ifge.c2, fd); 363 | fprintf(fd, " GOTO "); 364 | tac_opd_print(p->code.ifge.labelno, fd); 365 | fprintf(fd, "\n"); 366 | break; 367 | case IFNE: 368 | fprintf(fd, "IF "); 369 | tac_opd_print(p->code.ifne.c1, fd); 370 | fprintf(fd, " != "); 371 | tac_opd_print(p->code.ifne.c2, fd); 372 | fprintf(fd, " GOTO "); 373 | tac_opd_print(p->code.ifne.labelno, fd); 374 | fprintf(fd, "\n"); 375 | break; 376 | case IFEQ: 377 | fprintf(fd, "IF "); 378 | tac_opd_print(p->code.ifeq.c1, fd); 379 | fprintf(fd, " == "); 380 | tac_opd_print(p->code.ifeq.c2, fd); 381 | fprintf(fd, " GOTO "); 382 | tac_opd_print(p->code.ifeq.labelno, fd); 383 | fprintf(fd, "\n"); 384 | break; 385 | case RETURN: 386 | fprintf(fd, "RETURN "); 387 | tac_opd_print(p->code.return_.var, fd); 388 | fprintf(fd, "\n"); 389 | break; 390 | case DEC: 391 | assert(p->code.dec.var->kind == OP_POINTER); 392 | // DEC should not followed &v 393 | fprintf(fd, "DEC %s %d\n", p->code.dec.var->char_val, p->code.dec.size); 394 | break; 395 | case ARG: 396 | fprintf(fd, "ARG "); 397 | tac_opd_print(p->code.arg.var, fd); 398 | fprintf(fd, "\n"); 399 | break; 400 | case CALL: 401 | tac_opd_print(p->code.call.ret, fd); 402 | fprintf(fd, " := CALL %s\n", p->code.call.funcname); 403 | break; 404 | case PARAM: 405 | fprintf(fd, "PARAM "); 406 | tac_opd_print(p->code.param.p, fd); 407 | fprintf(fd, "\n"); 408 | break; 409 | case READ: 410 | fprintf(fd, "READ "); 411 | tac_opd_print(p->code.read.p, fd); 412 | fprintf(fd, "\n"); 413 | break; 414 | case WRITE: 415 | fprintf(fd, "WRITE "); 416 | tac_opd_print(p->code.write.p, fd); 417 | fprintf(fd, "\n"); 418 | break; 419 | case NONE: 420 | break; 421 | } 422 | p = p->next; 423 | } 424 | } 425 | 426 | void tac_insert(tac *head, tac *seg){ 427 | tac *p, *q; 428 | q = head->next; 429 | head->next = seg; 430 | seg->prev = head; 431 | p = seg; 432 | while(p->next != NULL) 433 | p = p->next; 434 | p->next = q; 435 | if(q != NULL) 436 | q->prev = p; 437 | } 438 | 439 | void tac_append(tac *head, tac *seg){ 440 | tac *p; 441 | p = head; 442 | while(p->next != NULL) 443 | p = p->next; 444 | tac_insert(p, seg); 445 | } 446 | 447 | tac *tac_init_label(tac_opd *labelno){ 448 | tac *self = (tac*)malloc(sizeof(tac)); 449 | self->code.kind = LABEL; 450 | self->code.label.labelno = labelno; 451 | self->prev = self->next = NULL; 452 | return self; 453 | } 454 | 455 | tac *tac_init_function(char *funcname){ 456 | tac *self = (tac*)malloc(sizeof(tac)); 457 | self->code.kind = FUNCTION; 458 | self->code.function.funcname = (char*)malloc(32); 459 | sprintf(self->code.function.funcname, "%s", funcname); 460 | self->prev = self->next = NULL; 461 | return self; 462 | } 463 | 464 | tac *tac_init_assign(tac_opd *left, tac_opd *right){ 465 | tac *self = (tac*)malloc(sizeof(tac)); 466 | self->code.kind = ASSIGN; 467 | self->code.assign.left = left; 468 | self->code.assign.right = right; 469 | self->prev = self->next = NULL; 470 | return self; 471 | } 472 | 473 | tac *tac_init_add(tac_opd *left, tac_opd *r1, tac_opd *r2){ 474 | tac *self = (tac*)malloc(sizeof(tac)); 475 | self->code.kind = ADD; 476 | self->code.add.left = left; 477 | self->code.add.r1 = r1; 478 | self->code.add.r2 = r2; 479 | self->prev = self->next = NULL; 480 | return self; 481 | } 482 | 483 | tac *tac_init_sub(tac_opd *left, tac_opd *r1, tac_opd *r2){ 484 | tac *self = (tac*)malloc(sizeof(tac)); 485 | self->code.kind = SUB; 486 | self->code.sub.left = left; 487 | self->code.sub.r1 = r1; 488 | self->code.sub.r2 = r2; 489 | self->prev = self->next = NULL; 490 | return self; 491 | } 492 | 493 | tac *tac_init_mul(tac_opd *left, tac_opd *r1, tac_opd *r2){ 494 | tac *self = (tac*)malloc(sizeof(tac)); 495 | self->code.kind = MUL; 496 | self->code.mul.left = left; 497 | self->code.mul.r1 = r1; 498 | self->code.mul.r2 = r2; 499 | self->prev = self->next = NULL; 500 | return self; 501 | } 502 | 503 | tac *tac_init_div(tac_opd *left, tac_opd *r1, tac_opd *r2){ 504 | tac *self = (tac*)malloc(sizeof(tac)); 505 | self->code.kind = DIV; 506 | self->code.div.left = left; 507 | self->code.div.r1 = r1; 508 | self->code.div.r2 = r2; 509 | self->prev = self->next = NULL; 510 | return self; 511 | } 512 | 513 | tac *tac_init_addr(tac_opd *left, tac_opd *right){ 514 | assert(right->kind == OP_POINTER); 515 | tac *self = (tac*)malloc(sizeof(tac)); 516 | self->code.kind = ADDR; 517 | self->code.addr.left = left; 518 | self->code.addr.right = right; 519 | self->prev = self->next = NULL; 520 | return self; 521 | } 522 | 523 | tac *tac_init_fetch(tac_opd *left, tac_opd *raddr){ 524 | tac *self = (tac*)malloc(sizeof(tac)); 525 | self->code.kind = FETCH; 526 | self->code.fetch.left = left; 527 | self->code.fetch.raddr = raddr; 528 | self->prev = self->next = NULL; 529 | return self; 530 | } 531 | 532 | tac *tac_init_deref(tac_opd *laddr, tac_opd *right){ 533 | tac *self = (tac*)malloc(sizeof(tac)); 534 | self->code.kind = DEREF ; 535 | self->code.deref.laddr = laddr; 536 | self->code.deref.right = right; 537 | self->prev = self->next = NULL; 538 | return self; 539 | } 540 | 541 | tac *tac_init_goto(tac_opd *labelno){ 542 | tac *self = (tac*)malloc(sizeof(tac)); 543 | self->code.kind = GOTO; 544 | self->code.goto_.labelno = labelno; 545 | self->prev = self->next = NULL; 546 | return self; 547 | } 548 | 549 | tac *tac_init_iflt(tac_opd *c1, tac_opd *c2, tac_opd *labelno){ 550 | tac *self = (tac*)malloc(sizeof(tac)); 551 | self->code.kind = IFLT; 552 | self->code.iflt.c1 = c1; 553 | self->code.iflt.c2 = c2; 554 | self->code.iflt.labelno = labelno; 555 | self->prev = self->next = NULL; 556 | return self; 557 | } 558 | 559 | tac *tac_init_ifle(tac_opd *c1, tac_opd *c2, tac_opd *labelno){ 560 | tac *self = (tac*)malloc(sizeof(tac)); 561 | self->code.kind = IFLE; 562 | self->code.ifle.c1 = c1; 563 | self->code.ifle.c2 = c2; 564 | self->code.ifle.labelno = labelno; 565 | self->prev = self->next = NULL; 566 | return self; 567 | } 568 | 569 | tac *tac_init_ifgt(tac_opd *c1, tac_opd *c2, tac_opd *labelno){ 570 | tac *self = (tac*)malloc(sizeof(tac)); 571 | self->code.kind = IFGT; 572 | self->code.ifgt.c1 = c1; 573 | self->code.ifgt.c2 = c2; 574 | self->code.ifgt.labelno = labelno; 575 | self->prev = self->next = NULL; 576 | return self; 577 | } 578 | 579 | tac *tac_init_ifge(tac_opd *c1, tac_opd *c2, tac_opd *labelno){ 580 | tac *self = (tac*)malloc(sizeof(tac)); 581 | self->code.kind = IFGE; 582 | self->code.ifge.c1 = c1; 583 | self->code.ifge.c2 = c2; 584 | self->code.ifge.labelno = labelno; 585 | self->prev = self->next = NULL; 586 | return self; 587 | } 588 | 589 | tac *tac_init_ifne(tac_opd *c1, tac_opd *c2, tac_opd *labelno){ 590 | tac *self = (tac*)malloc(sizeof(tac)); 591 | self->code.kind = IFNE; 592 | self->code.ifne.c1 = c1; 593 | self->code.ifne.c2 = c2; 594 | self->code.ifne.labelno = labelno; 595 | self->prev = self->next = NULL; 596 | return self; 597 | } 598 | 599 | tac *tac_init_ifeq(tac_opd *c1, tac_opd *c2, tac_opd *labelno){ 600 | tac *self = (tac*)malloc(sizeof(tac)); 601 | self->code.kind = IFEQ; 602 | self->code.ifeq.c1 = c1; 603 | self->code.ifeq.c2 = c2; 604 | self->code.ifeq.labelno = labelno; 605 | self->prev = self->next = NULL; 606 | return self; 607 | } 608 | 609 | tac *tac_init_return(tac_opd *var){ 610 | tac *self = (tac*)malloc(sizeof(tac)); 611 | self->code.kind = RETURN; 612 | self->code.return_.var = var; 613 | self->prev = self->next = NULL; 614 | return self; 615 | } 616 | 617 | tac *tac_init_dec(tac_opd *var, int size){ 618 | tac *self = (tac*)malloc(sizeof(tac)); 619 | self->code.kind = DEC; 620 | self->code.dec.var = var; 621 | self->code.dec.size = size; 622 | self->prev = self->next = NULL; 623 | return self; 624 | } 625 | 626 | tac *tac_init_arg(tac_opd *var){ 627 | tac *self = (tac*)malloc(sizeof(tac)); 628 | self->code.kind = ARG; 629 | self->code.arg.var = var; 630 | self->prev = self->next = NULL; 631 | return self; 632 | } 633 | 634 | tac *tac_init_call(tac_opd *ret, char *funcname){ 635 | tac *self = (tac*)malloc(sizeof(tac)); 636 | self->code.kind = CALL; 637 | self->code.call.ret = ret; 638 | self->code.call.funcname = (char*)malloc(32); 639 | sprintf(self->code.call.funcname, "%s", funcname); 640 | self->prev = self->next = NULL; 641 | return self; 642 | } 643 | 644 | tac *tac_init_param(tac_opd *p){ 645 | tac *self = (tac*)malloc(sizeof(tac)); 646 | self->code.kind = PARAM; 647 | self->code.param.p = p; 648 | self->prev = self->next = NULL; 649 | return self; 650 | } 651 | 652 | tac *tac_init_read(tac_opd *p){ 653 | tac *self = (tac*)malloc(sizeof(tac)); 654 | self->code.kind = READ; 655 | self->code.read.p = p; 656 | self->prev = self->next = NULL; 657 | return self; 658 | } 659 | 660 | tac *tac_init_write(tac_opd *p){ 661 | tac *self = (tac*)malloc(sizeof(tac)); 662 | self->code.kind = WRITE; 663 | self->code.write.p = p; 664 | self->prev = self->next = NULL; 665 | return self; 666 | } 667 | 668 | tac *tac_init_none(){ 669 | tac *self = (tac*)malloc(sizeof(tac)); 670 | self->code.kind = NONE; 671 | self->prev = self->next = NULL; 672 | return self; 673 | } 674 | -------------------------------------------------------------------------------- /project4/tac.h: -------------------------------------------------------------------------------- 1 | #ifndef TAC_H 2 | #define TAC_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | typedef struct tac_opd tac_opd; 12 | typedef struct tac_node tac; 13 | 14 | struct tac_opd { 15 | enum { OP_LABEL, OP_VARIABLE, OP_CONSTANT, OP_POINTER } kind; 16 | union { 17 | char char_val[8]; // stores variable name, pointer name 18 | int int_val; // stores label number, int constant 19 | }; 20 | }; 21 | 22 | struct _tac_inst { 23 | enum { LABEL, FUNCTION, ASSIGN, ADD, SUB, MUL, DIV, ADDR, FETCH, DEREF, 24 | GOTO, IFLT, IFLE, IFGT, IFGE, IFNE, IFEQ, RETURN, DEC, ARG, 25 | CALL, PARAM, READ, WRITE, NONE } kind; 26 | union { // all union variables are not pointer! 27 | // LABEL label[labelno] : 28 | struct { tac_opd *labelno; } label; 29 | // FUNCTION funcname : 30 | struct { char *funcname; } function; 31 | // left := right 32 | struct { tac_opd *left, *right; } assign; 33 | // left := r1 + r2 34 | struct { tac_opd *left, *r1, *r2; } add; 35 | // left := r1 - r2 36 | struct { tac_opd *left, *r1, *r2; } sub; 37 | // left := r1 * r2 38 | struct { tac_opd *left, *r1, *r2; } mul; 39 | // left := r1 / r2 40 | struct { tac_opd *left, *r1, *r2; } div; 41 | // left := &right 42 | struct { tac_opd *left, *right; } addr; 43 | // left := *raddr 44 | struct { tac_opd *left, *raddr; } fetch; 45 | // *laddr := right 46 | struct { tac_opd *laddr, *right; } deref; 47 | // GOTO label[labelno] 48 | struct { tac_opd *labelno; } goto_; 49 | // IF c1 < c2 GOTO label[labelno] 50 | struct { tac_opd *c1, *c2; tac_opd *labelno; } iflt; 51 | // IF c1 <= c2 GOTO label[labelno] 52 | struct { tac_opd *c1, *c2; tac_opd *labelno; } ifle; 53 | // IF c1 > c2 GOTO label[labelno] 54 | struct { tac_opd *c1, *c2; tac_opd *labelno; } ifgt; 55 | // IF c1 >= c2 GOTO label[labelno] 56 | struct { tac_opd *c1, *c2; tac_opd *labelno; } ifge; 57 | // IF c1 != c2 GOTO label[labelno] 58 | struct { tac_opd *c1, *c2; tac_opd *labelno; } ifne; 59 | // IF c1 == c2 GOTO label[labelno] 60 | struct { tac_opd *c1, *c2; tac_opd *labelno; } ifeq; 61 | // RETURN var 62 | struct { tac_opd *var; } return_; 63 | // DEC var size 64 | struct { tac_opd *var; int size; } dec; 65 | // ARG var 66 | struct { tac_opd *var; } arg; 67 | // ret := CALL funcname 68 | struct { tac_opd *ret; char *funcname; } call; 69 | // PARAM p 70 | struct { tac_opd *p; } param; 71 | // READ p 72 | struct { tac_opd *p; } read; 73 | // WRITE p 74 | struct { tac_opd *p; } write; 75 | }; 76 | }; 77 | 78 | struct tac_node { 79 | struct _tac_inst code; // code is not a pointer! 80 | struct tac_node *prev, *next; // doubly linked list impl 81 | }; 82 | 83 | /* 84 | * construct a tac list from the input buffer 85 | * put a '\n' after each instruction (also the last one) 86 | * ## you should put a '\x7f' at the end of the buffer ## 87 | */ 88 | tac *tac_from_buffer(char *buf); 89 | 90 | 91 | 92 | /***************************************************************** 93 | ####################### STOP HERE ######################### 94 | The declaration below is related to the intermediate code 95 | generation, they are not helpful to you in project 4. 96 | ####################### STOP HERE ######################### 97 | *****************************************************************/ 98 | 99 | void tac_opd_print(tac_opd*, FILE*); 100 | 101 | /* 102 | * related to intermediate code generation 103 | * returns a single TAC operand 104 | */ 105 | tac_opd *tac_opd_label(int); 106 | tac_opd *tac_opd_variable(char*); 107 | tac_opd *tac_opd_constant(int); 108 | tac_opd *tac_opd_pointer(char*); 109 | 110 | // insert a segment of TAC next to head 111 | void tac_insert(tac*, tac*); 112 | 113 | // insert a segment of TAC at the end of list 114 | void tac_append(tac*, tac*); 115 | 116 | void tac_print(tac*, FILE*); 117 | 118 | /* 119 | * related to intermediate code generation 120 | * returns a single TAC quadruple 121 | */ 122 | tac *tac_init_label(tac_opd*); 123 | tac *tac_init_function(char*); 124 | tac *tac_init_assign(tac_opd*, tac_opd*); 125 | tac *tac_init_add(tac_opd*, tac_opd*, tac_opd*); 126 | tac *tac_init_sub(tac_opd*, tac_opd*, tac_opd*); 127 | tac *tac_init_mul(tac_opd*, tac_opd*, tac_opd*); 128 | tac *tac_init_div(tac_opd*, tac_opd*, tac_opd*); 129 | tac *tac_init_addr(tac_opd*, tac_opd*); 130 | tac *tac_init_fetch(tac_opd*, tac_opd*); 131 | tac *tac_init_deref(tac_opd*, tac_opd*); 132 | tac *tac_init_goto(tac_opd*); 133 | tac *tac_init_iflt(tac_opd*, tac_opd*, tac_opd*); 134 | tac *tac_init_ifle(tac_opd*, tac_opd*, tac_opd*); 135 | tac *tac_init_ifgt(tac_opd*, tac_opd*, tac_opd*); 136 | tac *tac_init_ifge(tac_opd*, tac_opd*, tac_opd*); 137 | tac *tac_init_ifne(tac_opd*, tac_opd*, tac_opd*); 138 | tac *tac_init_ifeq(tac_opd*, tac_opd*, tac_opd*); 139 | tac *tac_init_return(tac_opd*); 140 | tac *tac_init_dec(tac_opd*, int); 141 | tac *tac_init_arg(tac_opd*); 142 | tac *tac_init_call(tac_opd*, char*); 143 | tac *tac_init_param(tac_opd*); 144 | tac *tac_init_read(tac_opd*); 145 | tac *tac_init_write(tac_opd*); 146 | tac *tac_init_none(); 147 | 148 | #endif // TAC_H 149 | -------------------------------------------------------------------------------- /project4/test/test_4_r01.ir: -------------------------------------------------------------------------------- 1 | FUNCTION hanoi : 2 | PARAM v0 3 | PARAM v1 4 | PARAM v2 5 | PARAM v3 6 | v4 := v0 7 | v5 := #1 8 | IF v4 == v5 GOTO label0 9 | GOTO label1 10 | LABEL label0 : 11 | v9 := v1 12 | v10 := #10000 13 | v8 := v9 * v10 14 | v11 := v3 15 | v7 := v8 + v11 16 | WRITE v7 17 | GOTO label2 18 | LABEL label1 : 19 | v14 := v0 20 | v15 := #1 21 | v13 := v14 - v15 22 | v16 := v1 23 | v17 := v3 24 | v18 := v2 25 | ARG v18 26 | ARG v17 27 | ARG v16 28 | ARG v13 29 | v12 := CALL hanoi 30 | v22 := v1 31 | v23 := #10000 32 | v21 := v22 * v23 33 | v24 := v3 34 | v20 := v21 + v24 35 | WRITE v20 36 | v27 := v0 37 | v28 := #1 38 | v26 := v27 - v28 39 | v29 := v2 40 | v30 := v1 41 | v31 := v3 42 | ARG v31 43 | ARG v30 44 | ARG v29 45 | ARG v26 46 | v25 := CALL hanoi 47 | LABEL label2 : 48 | v32 := #0 49 | RETURN v32 50 | FUNCTION main : 51 | v34 := #3 52 | v33 := v34 53 | v36 := v33 54 | v37 := #1 55 | v38 := #2 56 | v39 := #3 57 | ARG v39 58 | ARG v38 59 | ARG v37 60 | ARG v36 61 | v35 := CALL hanoi 62 | v40 := #0 63 | RETURN v40 64 | -------------------------------------------------------------------------------- /project4/test/test_4_r01.spl: -------------------------------------------------------------------------------- 1 | int hanoi(int n, int p1, int p2, int p3){ 2 | if(n == 1){ 3 | write(p1*10000+p3); 4 | } 5 | else{ 6 | hanoi(n-1,p1,p3,p2); 7 | write(p1*10000+p3); 8 | hanoi(n-1,p2,p1,p3); 9 | } 10 | return 0; 11 | } 12 | int main(){ 13 | int sum = 3; 14 | hanoi(sum, 1, 2, 3); 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /project4/test/test_4_r02.ir: -------------------------------------------------------------------------------- 1 | FUNCTION main : 2 | READ v2 3 | v0 := v2 4 | v3 := v0 5 | v4 := #0 6 | IF v3 > v4 GOTO label0 7 | GOTO label1 8 | LABEL label0 : 9 | v6 := #1 10 | WRITE v6 11 | GOTO label2 12 | LABEL label1 : 13 | v7 := v0 14 | v8 := #0 15 | IF v7 < v8 GOTO label3 16 | GOTO label4 17 | LABEL label3 : 18 | v11 := #1 19 | v10 := #0 - v11 20 | WRITE v10 21 | GOTO label5 22 | LABEL label4 : 23 | v13 := #0 24 | WRITE v13 25 | LABEL label5 : 26 | LABEL label2 : 27 | v14 := #0 28 | RETURN v14 29 | -------------------------------------------------------------------------------- /project4/test/test_4_r02.spl: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | int n; 4 | n = read(); 5 | if (n > 0) write(1); 6 | else if (n < 0) write (-1); 7 | else write(0); 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /project4/test/test_4_r03.ir: -------------------------------------------------------------------------------- 1 | FUNCTION main : 2 | v0 := #110 3 | v2 := #97 4 | v4 := #3 5 | v8 := v0 - v2 6 | v13 := #2 7 | v11 := v4 * v13 8 | v7 := v8 + v11 9 | v4 := v7 10 | v15 := v4 11 | WRITE v15 12 | v16 := #0 13 | RETURN v16 14 | -------------------------------------------------------------------------------- /project4/test/test_4_r03.spl: -------------------------------------------------------------------------------- 1 | int main(){ 2 | int a = 110; 3 | int b = 97; 4 | int c = 3; 5 | c = a - b + c*2; 6 | write(c); 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /semantic.txt: -------------------------------------------------------------------------------- 1 | /* 2 | * Assumptions means the test cases will not bring these violation 3 | * But assumption 7&8 will be revoked for optional rules 4 | * 5 | * two options: 6 | * 1. adopt scope checking (no assumption 7) 7 | * 2. structural equivalence for struct type (no assumption 8) 8 | */ 9 | 10 | Assumptions: 11 | 12 | 1. no assignment/operation between int and float variables 13 | 2. no unary/binary operation with char variables (they only occur as function parameters and arguments) 14 | 3. only int variables can do boolean operations, and branching/ looping conditions 15 | 4. only int and float variables can do arithmetic operations 16 | 5. no nested function de finitions 17 | 6. fi eld names in struct are unique (in any scope), so the names of struct fi elds, and variables never overlapped 18 | 7. (relaxed) there is only global scope, i.e., all variable names are unique 19 | 8. (relaxed) we adopt name equivalence to determine whether two struct types are equivalent 20 | 21 | Error types: 22 | 23 | 1. variable is used without defi nition 24 | 2. function is invoked without defi nition 25 | 3. variable is rede fined in the same scope 26 | 4. function is redefi ned (in the global scope, since we don't have nested function) 27 | 5. unmatching types on both sides of assignment operator (=) 28 | 6. rvalue on the left side of assignment operator 29 | 7. unmatching operands, such as adding an integer to a structure variable 30 | 8. the function's return value type mismatches the declared type 31 | 9. the function's arguments mismatch the declared parameters (either types or numbers, or both) 32 | 10. applying indexing operator ([...]) on non-array type variables 33 | 11. applying function invocation operator (foo(...)) on non-function names 34 | 12. array indexing with non-integer type expression 35 | 13. accessing member of non-structure variable (i.e., misuse the dot operator) 36 | 14. accessing an undefi ned structure member 37 | 15. redefi ne the same structure type 38 | -------------------------------------------------------------------------------- /syntax.txt: -------------------------------------------------------------------------------- 1 | /* 2 | * Error type: 3 | * 1. missing closing symbol, eg. parenthese, quotation, etc. 4 | * 2. missing comma or semicolon 5 | * 3. (optional) composite multiline comment 6 | * 7 | * (remark: '$' stands for empty terminal) 8 | */ 9 | 10 | /* high-level definition */ 11 | Program -> ExtDefList 12 | ExtDefList -> ExtDef ExtDefList 13 | | $ 14 | ExtDef -> Specifier ExtDecList SEMI 15 | | Specifier SEMI 16 | | Specifier FunDec CompSt 17 | ExtDecList -> VarDec 18 | | VarDec COMMA ExtDecList 19 | 20 | /* specifier */ 21 | Specifier -> TYPE 22 | | StructSpecifier 23 | StructSpecifier -> STRUCT ID LC DefList RC 24 | | STRUCT ID 25 | 26 | /* declarator */ 27 | VarDec -> ID 28 | | VarDec LB INT RB 29 | FunDec -> ID LP VarList RP 30 | | ID LP RP 31 | VarList -> ParamDec COMMA VarList 32 | | ParamDec 33 | ParamDec -> Specifier VarDec 34 | 35 | /* statement */ 36 | CompSt -> LC DefList StmtList RC 37 | StmtList -> Stmt StmtList 38 | | $ 39 | Stmt -> Exp SEMI 40 | | CompSt 41 | | RETURN Exp SEMI 42 | | IF LP Exp RP Stmt 43 | | IF LP Exp RP Stmt ELSE Stmt 44 | | WHILE LP Exp RP Stmt 45 | 46 | /* local definition */ 47 | DefList -> Def DefList 48 | | $ 49 | Def -> Specifier DecList SEMI 50 | DecList -> Dec 51 | | Dec COMMA DecList 52 | Dec -> VarDec 53 | | VarDec ASSIGN Exp 54 | 55 | /* Expression */ 56 | Exp -> Exp ASSIGN Exp 57 | | Exp AND Exp 58 | | Exp OR Exp 59 | | Exp LT Exp 60 | | Exp LE Exp 61 | | Exp GT Exp 62 | | Exp GE Exp 63 | | Exp NE Exp 64 | | Exp EQ Exp 65 | | Exp PLUS Exp 66 | | Exp MINUS Exp 67 | | Exp MUL Exp 68 | | Exp DIV Exp 69 | | LP Exp RP 70 | | MINUS Exp 71 | | NOT Exp 72 | | ID LP Args RP 73 | | ID LP RP 74 | | Exp LB Exp RB 75 | | Exp DOT ID 76 | | ID 77 | | INT 78 | | FLOAT 79 | | CHAR 80 | Args -> Exp COMMA Args 81 | | Exp -------------------------------------------------------------------------------- /token.txt: -------------------------------------------------------------------------------- 1 | /* 2 | * Optional implementation: 3 | * 1. hexadecimal representation of INT (eg. 0x12) 4 | * 2. hex-form CHAR, no int, no escape (eg. '\x90') 5 | * 3. comment (single line or multi-line) 6 | * 7 | * Error type: 8 | * 1. undefined tokens, eg., '@', '#' as non-literal token 9 | * 2. (optional) illegal hex int, eg., 0x5gg 10 | * 3. (optional) illegal hex char, eg., '\x9', '\xt0' 11 | */ 12 | 13 | INT -> /* integer in 32-bits (decimal or hexadecimal) */ 14 | FLOAT -> /* floating point number (only dot-form) */ 15 | CHAR -> /* single character (printable or hex-form) */ 16 | ID -> /* identifier */ 17 | TYPE -> int | float | char 18 | STRUCT -> struct 19 | IF -> if 20 | ELSE -> else 21 | WHILE -> while 22 | RETURN -> return 23 | DOT -> . 24 | SEMI -> ; 25 | COMMA -> , 26 | ASSIGN -> = 27 | LT -> < 28 | LE -> <= 29 | GT -> > 30 | GE -> >= 31 | NE -> != 32 | EQ -> == 33 | PLUS -> + 34 | MINUS -> - 35 | MUL -> * 36 | DIV -> / 37 | AND -> && 38 | OR -> || 39 | NOT -> ! 40 | LP -> ( 41 | RP -> ) 42 | LB -> [ 43 | RB -> ] 44 | LC -> { 45 | RC -> } --------------------------------------------------------------------------------