├── IR-simulator ├── irsim_linux-x86_64.zip └── irsim_macosx-x64.zip ├── README.md ├── irsim_linux-x86_64.zip ├── irsim_macosx-x64.zip ├── lab1 ├── Makefile ├── hello_world.c ├── linked_list.c ├── linked_list.h ├── ll_test.py └── main.c ├── lab2 ├── test_1_r02.spl ├── test_1_r03.spl ├── test_1_r06.spl ├── test_1_r07.spl ├── test_1_r09.spl └── test_1_r11.spl ├── lab3 ├── identifiers │ ├── Makefile │ ├── lex.l │ └── test.c └── wc │ ├── Makefile │ ├── inferno3.txt │ └── lex.l ├── lab4 ├── comment_sanitizer │ ├── Makefile │ ├── lex.l │ └── test.c └── nested_quotation_marks │ ├── Makefile │ ├── lex.l │ └── test.c ├── lab6 └── calc │ ├── Makefile │ ├── lex.l │ └── syntax.y ├── lab7 └── ipaddr │ ├── Makefile │ ├── lex.l │ └── syntax.y ├── lab8 ├── calc │ ├── Makefile │ ├── lex.l │ └── syntax.y └── jp │ ├── Makefile │ ├── data │ ├── .gitignore │ ├── canada.json │ ├── citm_catalog.json │ ├── jsonchecker │ │ ├── fail02.json │ │ ├── fail03.json │ │ ├── fail04.json │ │ ├── fail05.json │ │ ├── fail06.json │ │ ├── fail07.json │ │ ├── fail08.json │ │ ├── fail09.json │ │ ├── fail10.json │ │ ├── fail11.json │ │ ├── fail12.json │ │ ├── fail13.json │ │ ├── fail14.json │ │ ├── fail15.json │ │ ├── fail16.json │ │ ├── fail17.json │ │ ├── fail19.json │ │ ├── fail20.json │ │ ├── fail21.json │ │ ├── fail22.json │ │ ├── fail23.json │ │ ├── fail24.json │ │ ├── fail25.json │ │ ├── fail26.json │ │ ├── fail27.json │ │ ├── fail28.json │ │ ├── fail29.json │ │ ├── fail30.json │ │ ├── fail31.json │ │ ├── fail32.json │ │ ├── fail33.json │ │ ├── pass01.json │ │ ├── pass02.json │ │ ├── pass03.json │ │ └── readme.txt │ └── twitter.json │ ├── jsonparser_test.py │ ├── lex.l │ └── syntax.y ├── project ├── phase2 │ ├── test_2_r01.out │ ├── test_2_r01.spl │ ├── test_2_r02.out │ ├── test_2_r02.spl │ ├── test_2_r03.out │ ├── test_2_r03.spl │ ├── test_2_r04.out │ ├── test_2_r04.spl │ ├── test_2_r05.out │ ├── test_2_r05.spl │ ├── test_2_r06.out │ ├── test_2_r06.spl │ ├── test_2_r07.out │ ├── test_2_r07.spl │ ├── test_2_r08.out │ ├── test_2_r08.spl │ ├── test_2_r09.out │ ├── test_2_r09.spl │ ├── test_2_r10.out │ ├── test_2_r10.spl │ ├── test_2_r11.out │ ├── test_2_r11.spl │ ├── test_2_r12.out │ ├── test_2_r12.spl │ ├── test_2_r13.out │ ├── test_2_r13.spl │ ├── test_2_r14.out │ ├── test_2_r14.spl │ ├── test_2_r15.out │ └── test_2_r15.spl ├── phase3 │ ├── test_3_r01.spl │ ├── test_3_r02.spl │ ├── test_3_r03.spl │ ├── test_3_r04.spl │ ├── test_3_r05.spl │ └── test_3_r06.spl └── phase4 │ ├── 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 └── spl-spec ├── syntax.txt └── token.txt /IR-simulator/irsim_linux-x86_64.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqlab-sustech/CS323-2024F/7ddef7ba2e717db31d9cb17f1a463707e36d6d21/IR-simulator/irsim_linux-x86_64.zip -------------------------------------------------------------------------------- /IR-simulator/irsim_macosx-x64.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqlab-sustech/CS323-2024F/7ddef7ba2e717db31d9cb17f1a463707e36d6d21/IR-simulator/irsim_macosx-x64.zip -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SUSTech CS323-2024F Course Website 2 | 3 | If you see any potential errors in the course materials, please submit a issue report. 4 | -------------------------------------------------------------------------------- /irsim_linux-x86_64.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqlab-sustech/CS323-2024F/7ddef7ba2e717db31d9cb17f1a463707e36d6d21/irsim_linux-x86_64.zip -------------------------------------------------------------------------------- /irsim_macosx-x64.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sqlab-sustech/CS323-2024F/7ddef7ba2e717db31d9cb17f1a463707e36d6d21/irsim_macosx-x64.zip -------------------------------------------------------------------------------- /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 libll.so 12 | .PHONY: hello main 13 | -------------------------------------------------------------------------------- /lab1/hello_world.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void say_hello_world(){ 4 | printf("hello world!\n"); 5 | } 6 | 7 | int main(void){ 8 | say_hello_world(); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /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 | void linked_list_insert(node *head, int val, int index){ 60 | 61 | } 62 | 63 | void linked_list_delete(node *head, int index){ 64 | 65 | } 66 | 67 | void linked_list_remove(node *head, int val){ 68 | 69 | } 70 | 71 | void linked_list_remove_all(node *head, int val){ 72 | 73 | } 74 | 75 | int linked_list_get(node *head, int index){ 76 | return 0; 77 | } 78 | 79 | int linked_list_search(node *head, int val){ 80 | return 0; 81 | } 82 | 83 | node *linked_list_search_all(node *head, int val){ 84 | return linked_list_init(); 85 | } 86 | -------------------------------------------------------------------------------- /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 (you will need to include "limit.h" header file). 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 | if __name__ == "__main__": 155 | unittest.main() 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 | -------------------------------------------------------------------------------- /lab2/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 | -------------------------------------------------------------------------------- /lab2/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 | -------------------------------------------------------------------------------- /lab2/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 | -------------------------------------------------------------------------------- /lab2/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 | -------------------------------------------------------------------------------- /lab2/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 | -------------------------------------------------------------------------------- /lab2/test_1_r11.spl: -------------------------------------------------------------------------------- 1 | int test_1_r11() 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 | -------------------------------------------------------------------------------- /lab3/identifiers/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | FLEX=flex 3 | idcount: 4 | $(FLEX) lex.l 5 | $(CC) lex.yy.c -lfl -o idcount.out 6 | clean: 7 | @rm -f lex.yy.c *.out 8 | -------------------------------------------------------------------------------- /lab3/identifiers/lex.l: -------------------------------------------------------------------------------- 1 | %{ 2 | #define EXIT_OK 0 3 | #define EXIT_FAIL 1 4 | 5 | // global variables 6 | int identifiers = 0; 7 | int lines = 0; 8 | %} 9 | letter [a-zA-Z] 10 | letter_ {letter}|_ 11 | digit [0-9] 12 | 13 | %% 14 | {letter_}({letter_}|{digit})* { identifiers++; printf("line %d: %s\n", lines, yytext);} 15 | \n {} 16 | [\t\r ]+ { /* does nothing when seeing white spaces except new line */ } 17 | . { /* a final rule that matches when seeing any character but new line */ } 18 | <> { printf("There are %d occurrences of valid identifiers\n", identifiers); yyterminate(); } 19 | 20 | %% 21 | int main(int argc, char **argv){ 22 | char *file_path; 23 | if(argc < 2){ 24 | fprintf(stderr, "Usage: %s \n", argv[0]); 25 | return EXIT_FAIL; 26 | } else if(argc == 2){ 27 | file_path = argv[1]; 28 | if(!(yyin = fopen(file_path, "r"))){ 29 | perror(argv[1]); 30 | return EXIT_FAIL; 31 | } 32 | yylex(); 33 | return EXIT_OK; 34 | } else{ 35 | fputs("Too many arguments! Expected: 2.\n", stderr); 36 | return EXIT_FAIL; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /lab3/identifiers/test.c: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | int a = 0; 4 | int BBA = a_; 5 | int _; 6 | int 3a; 7 | if (a0 == 0) _ = b0; 8 | else _= -b0; 9 | while(b != 0) {b1 = b0 - b2;} 10 | char c = 'a'; 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /lab3/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 | -------------------------------------------------------------------------------- /lab3/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 | -------------------------------------------------------------------------------- /lab3/wc/lex.l: -------------------------------------------------------------------------------- 1 | %{ 2 | // In this example, we assume that words can only contain English letters. If there are special symbols such as hyphen or apostrophe, we count multiple times (for example, "isn't" will be counted as two words and "world-class" will also be counted as two words. 3 | // just let you know you have macros! 4 | // C macro tutorial in Chinese: http://c.biancheng.net/view/446.html 5 | #define EXIT_OK 0 6 | #define EXIT_FAIL 1 7 | 8 | // global variables 9 | int chars = 0; 10 | int words = 0; 11 | int lines = 0; 12 | %} 13 | letter [a-zA-Z] 14 | 15 | %% 16 | {letter}+ { words++; chars+=strlen(yytext); } 17 | \n { chars++; lines++; } 18 | . { chars++; } 19 | 20 | %% 21 | int main(int argc, char **argv){ 22 | char *file_path; 23 | if(argc < 2){ 24 | fprintf(stderr, "Usage: %s \n", argv[0]); 25 | return EXIT_FAIL; 26 | } else if(argc == 2){ 27 | file_path = argv[1]; 28 | if(!(yyin = fopen(file_path, "r"))){ 29 | perror(argv[1]); 30 | return EXIT_FAIL; 31 | } 32 | yylex(); 33 | printf("%-8s%-8s%-8s%s\n", "#lines", "#words", "#chars", "file path"); 34 | printf("%-8d%-8d%-8d%s\n", lines, words, chars, file_path); 35 | return EXIT_OK; 36 | } else{ 37 | fputs("Too many arguments! Expected: 2.\n", stderr); 38 | return EXIT_FAIL; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lab4/comment_sanitizer/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | FLEX=flex 3 | sanitizer: 4 | $(FLEX) lex.l 5 | $(CC) lex.yy.c -lfl -o sanitizer.out 6 | clean: 7 | @rm -f lex.yy.c *.out 8 | .PHONY: sanitizer 9 | -------------------------------------------------------------------------------- /lab4/comment_sanitizer/lex.l: -------------------------------------------------------------------------------- 1 | %{ 2 | #define EXIT_OK 0 3 | #define EXIT_FAIL 1 4 | char c; 5 | %} 6 | %% 7 | "//" { 8 | // ignore the following chars until seeing a newline character 9 | while((c = input()) != '\n'); 10 | // put the newline character back to the input buffer 11 | unput(c); 12 | } 13 | . { printf("%s", yytext); } 14 | %% 15 | int main(int argc, char **argv){ 16 | char *file_path; 17 | if(argc < 2){ 18 | fprintf(stderr, "Usage: %s \n", argv[0]); 19 | return EXIT_FAIL; 20 | } else if(argc == 2){ 21 | file_path = argv[1]; 22 | if(!(yyin = fopen(file_path, "r"))){ 23 | perror(argv[1]); 24 | return EXIT_FAIL; 25 | } 26 | printf("The code after sanitization:\n"); 27 | yylex(); 28 | return EXIT_OK; 29 | } else{ 30 | fputs("Too many arguments! Expected: 2.\n", stderr); 31 | return EXIT_FAIL; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lab4/comment_sanitizer/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main() { 3 | printf("Hello world\n"); // print a message 4 | } 5 | -------------------------------------------------------------------------------- /lab4/nested_quotation_marks/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | FLEX=flex 3 | nest: 4 | $(FLEX) lex.l 5 | $(CC) lex.yy.c -lfl -o nest.out 6 | clean: 7 | @rm -f lex.yy.c *.out 8 | .PHONY: nest 9 | -------------------------------------------------------------------------------- /lab4/nested_quotation_marks/lex.l: -------------------------------------------------------------------------------- 1 | %{ 2 | #define EXIT_OK 0 3 | #define EXIT_FAIL 1 4 | %} 5 | %% 6 | \"[^\"]*\" { printf("Matched a string literal: %s\n", yytext); } 7 | \n {} 8 | . {} 9 | %% 10 | int main(int argc, char **argv){ 11 | char *file_path; 12 | if(argc < 2){ 13 | fprintf(stderr, "Usage: %s \n", argv[0]); 14 | return EXIT_FAIL; 15 | } else if(argc == 2){ 16 | file_path = argv[1]; 17 | if(!(yyin = fopen(file_path, "r"))){ 18 | perror(argv[1]); 19 | return EXIT_FAIL; 20 | } 21 | yylex(); 22 | return EXIT_OK; 23 | } else{ 24 | fputs("Too many arguments! Expected: 2.\n", stderr); 25 | return EXIT_FAIL; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /lab4/nested_quotation_marks/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main() { 3 | printf("This is a string literal without nested quotation marks"); 4 | printf("And God said, \"Let there be light,\" and there was light."); 5 | } 6 | -------------------------------------------------------------------------------- /lab6/calc/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.c syntax.tab.h *.out 10 | .PHONY: calc 11 | -------------------------------------------------------------------------------- /lab6/calc/lex.l: -------------------------------------------------------------------------------- 1 | %{ 2 | #include "syntax.tab.h" 3 | #include "stdlib.h" 4 | %} 5 | %% 6 | [0-9]+ { yylval = atoi(yytext); return INT; } 7 | "+" { return ADD; } 8 | "-" { return SUB; } 9 | "*" { return MUL; } 10 | "/" { return DIV; } 11 | [ \n\r\t] {} 12 | . { fprintf(stderr, "unknown symbol: %s\n", yytext); exit(1); } 13 | -------------------------------------------------------------------------------- /lab6/calc/syntax.y: -------------------------------------------------------------------------------- 1 | %{ 2 | #include "lex.yy.c" 3 | void yyerror(const char*); 4 | %} 5 | %token INT 6 | %token ADD SUB MUL DIV 7 | %% 8 | Calc: /* to allow empty input */ 9 | | Exp { printf("= %d\n", $1); } 10 | ; 11 | Exp: Factor 12 | | Exp ADD Factor { $$ = $1 + $3; } 13 | | Exp SUB Factor { $$ = $1 - $3; } 14 | ; 15 | Factor: Term 16 | | Factor MUL Term { $$ = $1 * $3; } 17 | | Factor DIV Term { $$ = $1 / $3; } 18 | Term: INT 19 | ; 20 | %% 21 | void yyerror(const char *s) { 22 | fprintf(stderr, "%s\n", s); 23 | } 24 | int main() { 25 | yyparse(); 26 | } 27 | -------------------------------------------------------------------------------- /lab7/ipaddr/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | FLEX=flex 3 | BISON=bison 4 | ip: 5 | $(BISON) -d syntax.y 6 | $(FLEX) lex.l 7 | $(CC) syntax.tab.c -lfl -ly -o ip.out 8 | clean: 9 | @rm -f lex.yy.c syntax.tab.c syntax.tab.h *.out 10 | .PHONY: ip 11 | -------------------------------------------------------------------------------- /lab7/ipaddr/lex.l: -------------------------------------------------------------------------------- 1 | %{ 2 | #define YYSTYPE char * 3 | #include "syntax.tab.h" 4 | #include "string.h" 5 | %} 6 | 7 | digitLetter [0-9a-fA-F] 8 | 9 | %% 10 | {digitLetter}+ { yylval = strdup(yytext); return X; } 11 | \. { return DOT; } 12 | : { return COLON; } 13 | \n {} 14 | . {return *yytext;} 15 | %% 16 | -------------------------------------------------------------------------------- /lab7/ipaddr/syntax.y: -------------------------------------------------------------------------------- 1 | %{ 2 | #define YYSTYPE char * 3 | #include "lex.yy.c" 4 | int yyerror(char* s); 5 | %} 6 | 7 | %token X 8 | %token DOT 9 | %token COLON 10 | 11 | %% 12 | 13 | // please design a grammar for the valid ip addresses and provide necessary semantic actions for production rules 14 | 15 | %% 16 | 17 | int yyerror(char* s) { 18 | fprintf(stderr, "%s\n", "Invalid"); 19 | return 1; 20 | } 21 | int main() { 22 | yyparse(); 23 | } 24 | -------------------------------------------------------------------------------- /lab8/calc/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.c syntax.tab.h *.out syntax.output 10 | .PHONY: calc 11 | -------------------------------------------------------------------------------- /lab8/calc/lex.l: -------------------------------------------------------------------------------- 1 | %{ 2 | #include "syntax.tab.h" 3 | #include "stdlib.h" 4 | %} 5 | %% 6 | [0-9]+ { yylval = atoi(yytext); return INT; } 7 | "+" { return ADD; } 8 | "-" { return SUB; } 9 | "*" { return MUL; } 10 | "/" { return DIV; } 11 | "(" { return LP; } 12 | ")" { return RP; } 13 | [ \n\r\t] {} 14 | . { fprintf(stderr, "unknown symbol: %s\n", yytext); exit(1); } 15 | -------------------------------------------------------------------------------- /lab8/calc/syntax.y: -------------------------------------------------------------------------------- 1 | %{ 2 | #include "lex.yy.c" 3 | void yyerror(const char*); 4 | %} 5 | %token INT ADD SUB MUL DIV LP RP 6 | 7 | %% 8 | Calc: /* to allow empty input */ 9 | | Exp { printf("= %d\n", $1); } 10 | ; 11 | Exp: INT 12 | | LP Exp RP { $$ = $2; } 13 | | Exp ADD Exp { $$ = $1 + $3; } 14 | | Exp SUB Exp { $$ = $1 - $3; } 15 | | Exp MUL Exp { $$ = $1 * $3; } 16 | | Exp DIV Exp { if($3 != 0) $$ = $1 / $3; else $$ = 0; } 17 | ; 18 | %% 19 | void yyerror(const char *s) { 20 | fprintf(stderr, "%s\n", s); 21 | } 22 | int main() { 23 | yyparse(); 24 | } 25 | -------------------------------------------------------------------------------- /lab8/jp/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 | jp: .lex .syntax 11 | $(CC) syntax.tab.c -lfl -ly -o jp.out 12 | clean: 13 | @rm -f lex.yy.c syntax.tab.* *.out 14 | -------------------------------------------------------------------------------- /lab8/jp/data/.gitignore: -------------------------------------------------------------------------------- 1 | roundtrip 2 | **/*_EXCLUDE.json -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/fail02.json: -------------------------------------------------------------------------------- 1 | ["Unclosed array" -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/fail03.json: -------------------------------------------------------------------------------- 1 | {unquoted_key: "keys must be quoted"} -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/fail04.json: -------------------------------------------------------------------------------- 1 | ["extra comma",] -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/fail05.json: -------------------------------------------------------------------------------- 1 | ["double extra comma",,] -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/fail06.json: -------------------------------------------------------------------------------- 1 | [ , "<-- missing value"] -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/fail07.json: -------------------------------------------------------------------------------- 1 | ["Comma after the close"], -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/fail08.json: -------------------------------------------------------------------------------- 1 | ["Extra close"]] -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/fail09.json: -------------------------------------------------------------------------------- 1 | {"Extra comma": true,} -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/fail10.json: -------------------------------------------------------------------------------- 1 | {"Extra value after close": true} "misplaced quoted value" -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/fail11.json: -------------------------------------------------------------------------------- 1 | {"Illegal expression": 1 + 2} -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/fail12.json: -------------------------------------------------------------------------------- 1 | {"Illegal invocation": alert()} -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/fail13.json: -------------------------------------------------------------------------------- 1 | {"Numbers cannot have leading zeroes": 013} -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/fail14.json: -------------------------------------------------------------------------------- 1 | {"Numbers cannot be hex": 0x14} -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/fail15.json: -------------------------------------------------------------------------------- 1 | ["Illegal backslash escape: \x15"] -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/fail16.json: -------------------------------------------------------------------------------- 1 | [\naked] -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/fail17.json: -------------------------------------------------------------------------------- 1 | ["Illegal backslash escape: \017"] -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/fail19.json: -------------------------------------------------------------------------------- 1 | {"Missing colon" null} -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/fail20.json: -------------------------------------------------------------------------------- 1 | {"Double colon":: null} -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/fail21.json: -------------------------------------------------------------------------------- 1 | {"Comma instead of colon", null} -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/fail22.json: -------------------------------------------------------------------------------- 1 | ["Colon instead of comma": false] -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/fail23.json: -------------------------------------------------------------------------------- 1 | ["Bad value", truth] -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/fail24.json: -------------------------------------------------------------------------------- 1 | ['single quote'] -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/fail25.json: -------------------------------------------------------------------------------- 1 | [" tab character in string "] -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/fail26.json: -------------------------------------------------------------------------------- 1 | ["tab\ character\ in\ string\ "] -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/fail27.json: -------------------------------------------------------------------------------- 1 | ["line 2 | break"] -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/fail28.json: -------------------------------------------------------------------------------- 1 | ["line\ 2 | break"] -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/fail29.json: -------------------------------------------------------------------------------- 1 | [0e] -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/fail30.json: -------------------------------------------------------------------------------- 1 | [0e+] -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/fail31.json: -------------------------------------------------------------------------------- 1 | [0e+-1] -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/fail32.json: -------------------------------------------------------------------------------- 1 | {"Comma instead if closing brace": true, -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/fail33.json: -------------------------------------------------------------------------------- 1 | ["mismatch"} -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/pass01.json: -------------------------------------------------------------------------------- 1 | [ 2 | "JSON Test Pattern pass1", 3 | {"object with 1 member":["array with 1 element"]}, 4 | {}, 5 | [], 6 | -42, 7 | true, 8 | false, 9 | null, 10 | { 11 | "integer": 1234567890, 12 | "real": -9876.543210, 13 | "e": 0.123456789e-12, 14 | "E": 1.234567890E+34, 15 | "": 23456789012E66, 16 | "zero": 0, 17 | "one": 1, 18 | "space": " ", 19 | "quote": "\"", 20 | "backslash": "\\", 21 | "controls": "\b\f\n\r\t", 22 | "slash": "/ & \/", 23 | "alpha": "abcdefghijklmnopqrstuvwyz", 24 | "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ", 25 | "digit": "0123456789", 26 | "0123456789": "digit", 27 | "special": "`1~!@#$%^&*()_+-={':[,]}|;.?", 28 | "hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A", 29 | "true": true, 30 | "false": false, 31 | "null": null, 32 | "array":[ ], 33 | "object":{ }, 34 | "address": "50 St. James Street", 35 | "url": "http://www.JSON.org/", 36 | "comment": "// /* */": " ", 38 | " s p a c e d " :[1,2 , 3 39 | 40 | , 41 | 42 | 4 , 5 , 6 ,7 ],"compact":[1,2,3,4,5,6,7], 43 | "jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}", 44 | "quotes": "" \u0022 %22 0x22 034 "", 45 | "\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?" 46 | : "A key can be any string" 47 | }, 48 | 0.5 ,98.6 49 | , 50 | 99.44 51 | , 52 | 53 | 1066, 54 | 1e1, 55 | 0.1e1, 56 | 1e-1, 57 | 1e00,2e+00,2e-00 58 | ,"rosebud"] -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/pass02.json: -------------------------------------------------------------------------------- 1 | [[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]] -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/pass03.json: -------------------------------------------------------------------------------- 1 | { 2 | "JSON Test Pattern pass3": { 3 | "The outermost value": "must be an object or array.", 4 | "In this test": "It is an object." 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /lab8/jp/data/jsonchecker/readme.txt: -------------------------------------------------------------------------------- 1 | Test suite from http://json.org/JSON_checker/. 2 | 3 | If the JSON_checker is working correctly, it must accept all of the pass*.json files and reject all of the fail*.json files. 4 | -------------------------------------------------------------------------------- /lab8/jp/jsonparser_test.py: -------------------------------------------------------------------------------- 1 | import pathlib 2 | import re 3 | import subprocess 4 | 5 | 6 | DATA = pathlib.Path('data') 7 | 8 | 9 | def jsonparser_output(json_file): 10 | out = subprocess.check_output(['./jp.out', json_file]) 11 | return out.decode().strip() 12 | 13 | 14 | def check_jsonchecker_fail_withlexical(): 15 | data = DATA/'jsonchecker' 16 | for failjson in data.glob('fail*.json'): 17 | out = jsonparser_output(failjson) 18 | if ('lexical error' not in out) or ('_EXCLUDE' in failjson.name): 19 | continue 20 | print(f'For file {failjson.name}:') 21 | print(out) 22 | print('-'*80) 23 | 24 | 25 | def check_jsonchecker_fail_syntaxonly(): 26 | data = DATA/'jsonchecker' 27 | recovered, total = 0, 0 28 | for failjson in data.glob('fail*.json'): 29 | out = jsonparser_output(failjson) 30 | if ('lexical error' in out) or ('_EXCLUDE' in failjson.name): 31 | continue 32 | print(f'For file {failjson.name}:') 33 | print('-'*24) 34 | print(open(failjson).read()) 35 | print('-'*80) 36 | print(out) 37 | print('#'*80) 38 | m = re.match(r'^syntax(.*?)recovered$', out) 39 | recovered += bool(m) 40 | total += 1 41 | print(f'Recovered/Total: {recovered}/{total}') 42 | 43 | 44 | 45 | # check_jsonchecker_fail_withlexical() 46 | check_jsonchecker_fail_syntaxonly() 47 | -------------------------------------------------------------------------------- /lab8/jp/lex.l: -------------------------------------------------------------------------------- 1 | %{ 2 | #include"syntax.tab.h" 3 | %} 4 | %option noyywrap 5 | 6 | unic u[0-9a-fA-F]{4} 7 | esc \\([\"\\/bfnrt]|{unic}) 8 | scp [^"\\\x00-\x1f] 9 | string \"({esc}|{scp})*\" 10 | 11 | int 0|[1-9][0-9]* 12 | frac \.[0-9]+ 13 | exp [Ee][+-]?[0-9]+ 14 | number -?{int}{frac}?{exp}? 15 | 16 | empty [ \n\r\t] 17 | 18 | %% 19 | 20 | "{" { return LC; } 21 | "}" { return RC; } 22 | "[" { return LB; } 23 | "]" { return RB; } 24 | ":" { return COLON; } 25 | "," { return COMMA; } 26 | 27 | "true" { return TRUE; } 28 | "false" { return FALSE; } 29 | "null" { return VNULL; } 30 | 31 | {string} { return STRING; } 32 | {number} { return NUMBER; } 33 | 34 | {empty} {} 35 | 36 | . { printf("lexical error: %s\n", yytext); } 37 | -------------------------------------------------------------------------------- /lab8/jp/syntax.y: -------------------------------------------------------------------------------- 1 | %{ 2 | #include"lex.yy.c" 3 | void yyerror(const char*); 4 | %} 5 | 6 | %token LC RC LB RB COLON COMMA 7 | %token STRING NUMBER 8 | %token TRUE FALSE VNULL 9 | %% 10 | 11 | Json: 12 | Value 13 | ; 14 | Value: 15 | Object 16 | | Array 17 | | STRING 18 | | NUMBER 19 | | TRUE 20 | | FALSE 21 | | VNULL 22 | ; 23 | Object: 24 | LC RC 25 | | LC Members RC 26 | ; 27 | Members: 28 | Member 29 | | Member COMMA Members 30 | ; 31 | Member: 32 | STRING COLON Value 33 | ; 34 | Array: 35 | LB RB 36 | | LB Values RB error {puts("Comma after the close, recovered");} 37 | | LB Values RC error { puts("unmatched right bracket, recovered"); } 38 | ; 39 | Values: 40 | Value 41 | | Value COMMA Values 42 | ; 43 | %% 44 | 45 | void yyerror(const char *s){ 46 | printf("syntax error: "); 47 | } 48 | 49 | int main(int argc, char **argv){ 50 | if(argc != 2) { 51 | fprintf(stderr, "Usage: %s \n", argv[0]); 52 | exit(-1); 53 | } 54 | else if(!(yyin = fopen(argv[1], "r"))) { 55 | perror(argv[1]); 56 | exit(-1); 57 | } 58 | yyparse(); 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /project/phase2/test_2_r01.out: -------------------------------------------------------------------------------- 1 | Error type 1 at Line 3: "z" is used without a definition 2 | Error type 1 at Line 9: "a" is used without a definition 3 | Error type 1 at Line 10: "a" is used without a definition 4 | Error type 3 at Line 10: "b" is redefined 5 | -------------------------------------------------------------------------------- /project/phase2/test_2_r01.spl: -------------------------------------------------------------------------------- 1 | int sum(int x, int y) 2 | { 3 | int res = x + y + z; 4 | return res; 5 | } 6 | int test_2_r01() 7 | { 8 | int a1 = 1; 9 | int b = a1 + a; 10 | int b = sum(a, b); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /project/phase2/test_2_r02.out: -------------------------------------------------------------------------------- 1 | Error type 2 at Line 9: "diff" is invoked without a definition 2 | Error type 8 at Line 10: incompatiable return type 3 | -------------------------------------------------------------------------------- /project/phase2/test_2_r02.spl: -------------------------------------------------------------------------------- 1 | int sum(int x, int y) 2 | { 3 | int res = x + y; 4 | return res; 5 | } 6 | int test_2_r02() 7 | { 8 | int a1, a2; 9 | float b = diff(a1, a2); 10 | return b; 11 | } 12 | -------------------------------------------------------------------------------- /project/phase2/test_2_r03.out: -------------------------------------------------------------------------------- 1 | Error type 3 at Line 4: variable "weight" is redefined in the same scope 2 | Error type 3 at Line 10: variable "age" is redefined in the same scope 3 | -------------------------------------------------------------------------------- /project/phase2/test_2_r03.spl: -------------------------------------------------------------------------------- 1 | struct Student 2 | { 3 | int weight; 4 | float weight; 5 | }; 6 | int test_2_r07() 7 | { 8 | struct Student amy; 9 | int age; 10 | float age; 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /project/phase2/test_2_r04.out: -------------------------------------------------------------------------------- 1 | Error type 4 at Line 6: "sum" is redefined 2 | Error type 8 at Line 9: incompatiable return type 3 | -------------------------------------------------------------------------------- /project/phase2/test_2_r04.spl: -------------------------------------------------------------------------------- 1 | int sum(int x, int y) 2 | { 3 | int res = x + y; 4 | return res; 5 | } 6 | float sum(int x, int y) 7 | { 8 | int res = x + y; 9 | return res; 10 | } 11 | int test_2_r04() 12 | { 13 | int a1, a2; 14 | int b = sum(a1, a2); 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /project/phase2/test_2_r05.out: -------------------------------------------------------------------------------- 1 | Error type 7 at Line 11: unmatching operands 2 | Error type 5 at Line 11: unmatching type on both sides of assignment 3 | Error type 5 at Line 12: unmatching type on both sides of assignment 4 | -------------------------------------------------------------------------------- /project/phase2/test_2_r05.spl: -------------------------------------------------------------------------------- 1 | struct Apple 2 | { 3 | int weight; 4 | float round; 5 | }; 6 | int test_2_r05() 7 | { 8 | int w1; 9 | float w2 = 1.05; 10 | struct Apple aa; 11 | aa.weight = w1 + w2; 12 | aa.round = 'c'; 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /project/phase2/test_2_r06.out: -------------------------------------------------------------------------------- 1 | Error type 5 at Line 9: unmatching type on both sides of assignment 2 | Error type 6 at Line 10: rvalue appears on the left-side of assignment 3 | -------------------------------------------------------------------------------- /project/phase2/test_2_r06.spl: -------------------------------------------------------------------------------- 1 | struct Apple 2 | { 3 | int weight; 4 | float round; 5 | }; 6 | int test_2_r05() 7 | { 8 | struct Apple aa; 9 | aa.weight = 2.5; 10 | 1.1 = aa.round; 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /project/phase2/test_2_r07.out: -------------------------------------------------------------------------------- 1 | Error type 7 at Line 11: unmatching operand 2 | Error type 5 at Line 11: unmatching types on both sides of assignment 3 | Error type 7 at Line 12: unmatching operand 4 | Error type 5 at Line 12: unmatching types on both sides of assignment 5 | -------------------------------------------------------------------------------- /project/phase2/test_2_r07.spl: -------------------------------------------------------------------------------- 1 | struct Apple 2 | { 3 | int weight; 4 | float round; 5 | }; 6 | int test_2_r05() 7 | { 8 | int w; 9 | float r = 2.5; 10 | struct Apple aa; 11 | aa.weight = w + 1.05; 12 | aa.round = r + aa; 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /project/phase2/test_2_r08.out: -------------------------------------------------------------------------------- 1 | Error type 8 at Line 19: incompatiable return type -------------------------------------------------------------------------------- /project/phase2/test_2_r08.spl: -------------------------------------------------------------------------------- 1 | int test1() 2 | { 3 | return 1; 4 | } 5 | 6 | float test2() 7 | { 8 | return 1.0; 9 | } 10 | 11 | int test_2_r08(int a, int b) 12 | { 13 | if (a > b) 14 | { 15 | return test1(); 16 | } 17 | else 18 | { 19 | return test2(); 20 | } 21 | } -------------------------------------------------------------------------------- /project/phase2/test_2_r09.out: -------------------------------------------------------------------------------- 1 | Error type 9 at Line 12: invalid argument number, except 2, got 3 2 | Error type 9 at Line 14: invalid argument number, except 2, got 1 3 | Error type 9 at line 15: invalid argument number, except 2, got 0 -------------------------------------------------------------------------------- /project/phase2/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 | int a = 5; 10 | int b = 9; 11 | int c = 7; 12 | return compare(a, b, c); 13 | return compare(a, b); 14 | return compare(a); 15 | return compare(); 16 | } 17 | -------------------------------------------------------------------------------- /project/phase2/test_2_r10.out: -------------------------------------------------------------------------------- 1 | Error type 10 at line 12: indexing on non-array variable -------------------------------------------------------------------------------- /project/phase2/test_2_r10.spl: -------------------------------------------------------------------------------- 1 | int test_2_r10() 2 | { 3 | int a[2][4][6][8]; 4 | int b[4][6][8]; 5 | int c[6][8]; 6 | int d[8]; 7 | int e; 8 | a[0] = b; 9 | a[0][1] = c; 10 | a[0][1][3] = d; 11 | a[0][1][3][5] = e; 12 | return a[e][e][e][e][e]; 13 | } -------------------------------------------------------------------------------- /project/phase2/test_2_r11.out: -------------------------------------------------------------------------------- 1 | Error type 11 at Line 5: invoking non-function variable -------------------------------------------------------------------------------- /project/phase2/test_2_r11.spl: -------------------------------------------------------------------------------- 1 | int test_2_r11() 2 | { 3 | int abc; 4 | int a[1][5]; 5 | a[0][1] = abc(); 6 | return a[abc][abc]; 7 | } -------------------------------------------------------------------------------- /project/phase2/test_2_r12.out: -------------------------------------------------------------------------------- 1 | Error type 12 at Line 7: indexing by non-integer 2 | Error type 5 at Line 7: unmatching type on both sides of assignment -------------------------------------------------------------------------------- /project/phase2/test_2_r12.spl: -------------------------------------------------------------------------------- 1 | int test_2_r12() 2 | { 3 | int a[3]; 4 | float b[4]; 5 | a[0] = a[a[2]]; 6 | b[0] = b[a[1]]; 7 | a[0] = a[b[0]]; 8 | return 0; 9 | } -------------------------------------------------------------------------------- /project/phase2/test_2_r13.out: -------------------------------------------------------------------------------- 1 | Error type 13 at Line 19: accessing with non-struct variable 2 | Error type 13 at Line 19: accessing with non-struct variable 3 | -------------------------------------------------------------------------------- /project/phase2/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 | -------------------------------------------------------------------------------- /project/phase2/test_2_r14.out: -------------------------------------------------------------------------------- 1 | Error type 14 at Line 11: accessing an undefined structure member 2 | Error type 5 at Line 11: unmatching types appear at both sides of the assignment operator 3 | -------------------------------------------------------------------------------- /project/phase2/test_2_r14.spl: -------------------------------------------------------------------------------- 1 | struct test 2 | { 3 | int a; 4 | float b; 5 | }; 6 | int test_2_r14() 7 | { 8 | struct test t; 9 | t.a = 1; 10 | t.b = 20.0; 11 | t.c = t.a; 12 | return 0; 13 | } -------------------------------------------------------------------------------- /project/phase2/test_2_r15.out: -------------------------------------------------------------------------------- 1 | Error type 15 at Line 7: redefine the same structure type 2 | 3 | -------------------------------------------------------------------------------- /project/phase2/test_2_r15.spl: -------------------------------------------------------------------------------- 1 | struct Apple 2 | { 3 | int weight; 4 | float round; 5 | float price; 6 | }; 7 | struct Apple 8 | { 9 | int round; 10 | float weight; 11 | float price; 12 | }; 13 | int test_2_r15() 14 | { 15 | struct Apple aa; 16 | aa.price = 2; 17 | return 0; 18 | } -------------------------------------------------------------------------------- /project/phase3/test_3_r01.spl: -------------------------------------------------------------------------------- 1 | int mod(int x, int n) 2 | { 3 | return x - (x / n) * n; 4 | } 5 | 6 | int isPalindrome(int num) { 7 | int reversed = 0; 8 | int original = num; 9 | int digit = 0; 10 | while (num != 0) { 11 | digit = mod(num , 10); 12 | reversed = reversed * 10 + digit; 13 | num = num / 10; 14 | } 15 | if(reversed == original){ 16 | return 1; 17 | }else{ 18 | return 0; 19 | } 20 | } 21 | 22 | int main() { 23 | int number; 24 | number = read(); 25 | if (isPalindrome(number)==1) { 26 | write(1); 27 | } else { 28 | write(-1); 29 | } 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /project/phase3/test_3_r02.spl: -------------------------------------------------------------------------------- 1 | int calculateBinomialCoefficient(int row, int col) { 2 | int coefficient = 1; 3 | int i = 0; 4 | 5 | if (row < col) { 6 | return 0; 7 | } 8 | 9 | if (col > row - col) { 10 | col = row - col; 11 | } 12 | 13 | while (i < col) { 14 | coefficient = coefficient * (row - i); 15 | coefficient = coefficient / (i + 1); 16 | i=i+1; 17 | } 18 | 19 | return coefficient; 20 | } 21 | 22 | int main() { 23 | int r, c, coe; 24 | r = read(); 25 | c = read(); 26 | coe = calculateBinomialCoefficient(r, c); 27 | write(coe); 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /project/phase3/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 | -------------------------------------------------------------------------------- /project/phase3/test_3_r04.spl: -------------------------------------------------------------------------------- 1 | int mod(int x,int n) 2 | { 3 | return x -(x / n) * n; 4 | } 5 | 6 | 7 | int isPerfectNumber(int number) { 8 | int sum = 0; 9 | int j = 1; 10 | while( j <= number / 2) { 11 | if ( mod(number , j) == 0) { 12 | sum = sum + j; 13 | } 14 | j = j + 1; 15 | } 16 | 17 | if (sum == number) { 18 | return 1; 19 | } else { 20 | return 0; 21 | } 22 | } 23 | 24 | int main() { 25 | int count = 0; 26 | int i = 1; 27 | while(i <= 100) { 28 | if (isPerfectNumber(i) == 1 ) { 29 | write(i); 30 | } 31 | i = i + 1; 32 | } 33 | 34 | return 0; 35 | } -------------------------------------------------------------------------------- /project/phase3/test_3_r05.spl: -------------------------------------------------------------------------------- 1 | int main() { 2 | int i, tu1, tu2, tu3, m, a, b, c; 3 | a = 1; 4 | b = 2; 5 | c = 3; 6 | tu1 = 1; 7 | tu2 = 1; 8 | m = read(); 9 | if(m < 1) 10 | write(0); 11 | else if(m == 1||m == 2) 12 | write(1); 13 | else if(m > 2) { 14 | i = 3; 15 | while(i <= m) { 16 | tu3 = tu1 + tu2; 17 | tu1 = tu2; 18 | tu2 = tu3; 19 | i = i + 1; 20 | } 21 | write(tu3); 22 | } 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /project/phase3/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 | 13 | int main(){ 14 | int sum = 3; 15 | hanoi(sum, 1, 2, 3); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /project/phase4/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 | -------------------------------------------------------------------------------- /project/phase4/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 | -------------------------------------------------------------------------------- /project/phase4/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 | -------------------------------------------------------------------------------- /project/phase4/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 | -------------------------------------------------------------------------------- /project/phase4/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 | -------------------------------------------------------------------------------- /project/phase4/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 | -------------------------------------------------------------------------------- /project/phase4/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 | -------------------------------------------------------------------------------- /project/phase4/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 | if (*str == '\0' || str == NULL || delim == '\0') 34 | { 35 | // Either of those will cause problems 36 | *n = -1; 37 | return NULL; 38 | } 39 | 40 | char** result = 0; 41 | size_t count = 0; 42 | char* tmp = str; 43 | char* last_comma = 0; 44 | char delims[2]; 45 | delims[0] = delim; 46 | delims[1] = 0; 47 | 48 | /* Count how many elements will be extracted. */ 49 | while (*tmp) { 50 | if (delim == *tmp) { 51 | count++; 52 | last_comma = tmp; 53 | } 54 | tmp++; 55 | } 56 | /* Add space for trailing token. */ 57 | count += last_comma < (str + strlen(str) - 1); 58 | *n = count; 59 | 60 | result = malloc(sizeof(char*) * (count + 1)); 61 | if (result) { 62 | size_t idx = 0; 63 | char* token = strtok(str, delims); 64 | 65 | while (token) { 66 | assert(idx < count); 67 | *(result + idx++) = strdup(token); 68 | token = strtok(0, delims); 69 | } 70 | assert(idx == count); 71 | *(result + idx) = 0; 72 | } 73 | return result; 74 | } 75 | 76 | tac_opd *_tac_opd_from_str(char *tk){ 77 | int i; 78 | 79 | if(tk[0] == '#'){ 80 | i = atoi(tk+1); 81 | return tac_opd_constant(i); 82 | } 83 | else if(tk[0] == '&'){ 84 | return tac_opd_pointer(tk+1); 85 | } 86 | else if(memcmp(tk, "label", 5) == 0){ 87 | i = atoi(tk+5); 88 | return tac_opd_label(i); 89 | } 90 | else{ 91 | return tac_opd_variable(tk); 92 | } 93 | } 94 | 95 | tac *_tac_from_line(char *ln){ 96 | tac_opd *t1, *t2, *t3; 97 | tac *code; 98 | char **tokens; 99 | int i, count; 100 | 101 | ln = _str_trim(ln); 102 | tokens = _str_split(ln, ' ', &count); 103 | 104 | if (tokens == NULL){ 105 | return tac_init_none(); 106 | } 107 | 108 | if(count == 2){ 109 | code = tac_init_none(); 110 | t1 = _tac_opd_from_str(tokens[1]); 111 | if(strcmp(tokens[0], "GOTO") == 0) 112 | code = tac_init_goto(t1); 113 | else if(strcmp(tokens[0], "RETURN") == 0) 114 | code = tac_init_return(t1); 115 | else if(strcmp(tokens[0], "ARG") == 0) 116 | code = tac_init_arg(t1); 117 | else if(strcmp(tokens[0], "PARAM") == 0) 118 | code = tac_init_param(t1); 119 | else if(strcmp(tokens[0], "READ") == 0) 120 | code = tac_init_read(t1); 121 | else if(strcmp(tokens[0], "WRITE") == 0) 122 | code = tac_init_write(t1); 123 | else 124 | assert(0); 125 | } 126 | else if(count == 3){ 127 | if(strcmp(tokens[0], "LABEL") == 0){ 128 | t1 = _tac_opd_from_str(tokens[1]); 129 | code = tac_init_label(t1); 130 | } 131 | else if(strcmp(tokens[0], "FUNCTION") == 0){ 132 | code = tac_init_function(tokens[1]); 133 | } 134 | else if(strcmp(tokens[0], "DEC") == 0){ 135 | t1 = tac_opd_pointer(tokens[1]); 136 | i = atoi(tokens[2]); 137 | code = tac_init_dec(t1, i); 138 | } 139 | else{ 140 | if(tokens[0][0] == '*'){ 141 | t1 = _tac_opd_from_str(tokens[0]+1); 142 | t2 = _tac_opd_from_str(tokens[2]); 143 | code = tac_init_deref(t1, t2); 144 | } 145 | else if(tokens[2][0] == '*'){ 146 | t1 = _tac_opd_from_str(tokens[0]); 147 | t2 = _tac_opd_from_str(tokens[2]+1); 148 | code = tac_init_fetch(t1, t2); 149 | } 150 | else if(tokens[2][0] == '&'){ 151 | t1 = _tac_opd_from_str(tokens[0]); 152 | t2 = _tac_opd_from_str(tokens[2]); 153 | code = tac_init_addr(t1, t2); 154 | } 155 | else{ 156 | t1 = _tac_opd_from_str(tokens[0]); 157 | t2 = _tac_opd_from_str(tokens[2]); 158 | code = tac_init_assign(t1, t2); 159 | } 160 | } 161 | } 162 | else if(count == 4){ 163 | t1 = _tac_opd_from_str(tokens[0]); 164 | code = tac_init_call(t1, tokens[3]); 165 | } 166 | else if(count == 5){ 167 | t1 = _tac_opd_from_str(tokens[0]); 168 | t2 = _tac_opd_from_str(tokens[2]); 169 | t3 = _tac_opd_from_str(tokens[4]); 170 | switch(tokens[3][0]){ 171 | case '+': 172 | code = tac_init_add(t1, t2, t3); 173 | break; 174 | case '-': 175 | code = tac_init_sub(t1, t2, t3); 176 | break; 177 | case '*': 178 | code = tac_init_mul(t1, t2, t3); 179 | break; 180 | case '/': 181 | code = tac_init_div(t1, t2, t3); 182 | break; 183 | } 184 | } 185 | else{ // count == 6 186 | t1 = _tac_opd_from_str(tokens[1]); 187 | t2 = _tac_opd_from_str(tokens[3]); 188 | t3 = _tac_opd_from_str(tokens[5]); 189 | if(strlen(tokens[2]) == 1){ 190 | if(tokens[2][0] == '<') 191 | code = tac_init_iflt(t1, t2, t3); 192 | else // > 193 | code = tac_init_ifgt(t1, t2, t3); 194 | } 195 | else{ // == 2 196 | if(tokens[2][0] == '<') 197 | code = tac_init_ifle(t1, t2, t3); 198 | else if(tokens[2][0] == '>') 199 | code = tac_init_ifge(t1, t2, t3); 200 | else if(tokens[2][0] == '!') 201 | code = tac_init_ifne(t1, t2, t3); 202 | else // == 203 | code = tac_init_ifeq(t1, t2, t3); 204 | } 205 | } 206 | 207 | free(tokens); 208 | return code; 209 | } 210 | 211 | tac *tac_from_buffer(char *buf){ 212 | tac *self, *inst; 213 | char lnbuf[64]; 214 | int buf_i, i; 215 | 216 | self = tac_init_none(); 217 | for(buf_i = i = 0; buf[buf_i] != '\x7f'; buf_i++){ 218 | if(buf[buf_i] != '\n'){ 219 | lnbuf[i++] = buf[buf_i]; 220 | } 221 | else{ 222 | lnbuf[i] = '\0'; 223 | inst = _tac_from_line(lnbuf); 224 | tac_append(self, inst); 225 | i = 0; 226 | } 227 | } 228 | return self; 229 | } 230 | 231 | void tac_opd_print(tac_opd *self, FILE *fd){ 232 | switch(self->kind){ 233 | case OP_LABEL: 234 | fprintf(fd, "label%d", self->int_val); 235 | break; 236 | case OP_VARIABLE: 237 | fprintf(fd, "%s", self->char_val); 238 | break; 239 | case OP_CONSTANT: 240 | fprintf(fd, "#%d", self->int_val); 241 | break; 242 | case OP_POINTER: 243 | fprintf(fd, "&%s", self->char_val); 244 | break; 245 | } 246 | } 247 | 248 | tac_opd *tac_opd_label(int lval){ 249 | tac_opd *self = (tac_opd*)malloc(sizeof(tac_opd)); 250 | self->kind = OP_LABEL; 251 | self->int_val = lval; 252 | return self; 253 | } 254 | 255 | tac_opd *tac_opd_variable(char *vname){ 256 | tac_opd *self = (tac_opd*)malloc(sizeof(tac_opd)); 257 | self->kind = OP_VARIABLE; 258 | sprintf(self->char_val, "%s", vname); 259 | return self; 260 | } 261 | 262 | tac_opd *tac_opd_constant(int cval){ 263 | tac_opd *self = (tac_opd*)malloc(sizeof(tac_opd)); 264 | self->kind = OP_CONSTANT; 265 | self->int_val = cval; 266 | return self; 267 | } 268 | 269 | tac_opd *tac_opd_pointer(char *pname){ 270 | tac_opd *self = (tac_opd*)malloc(sizeof(tac_opd)); 271 | self->kind = OP_POINTER; 272 | sprintf(self->char_val, "%s", pname); 273 | return self; 274 | } 275 | 276 | void tac_print(tac *head, FILE *fd){ 277 | tac *p = head; 278 | while(p != NULL){ 279 | switch(p->code.kind){ 280 | case LABEL: 281 | fprintf(fd, "LABEL "); 282 | tac_opd_print(p->code.label.labelno, fd); 283 | fprintf(fd, " :\n"); 284 | break; 285 | case FUNCTION: 286 | fprintf(fd, "FUNCTION %s :\n", p->code.function.funcname); 287 | break; 288 | case ASSIGN: 289 | tac_opd_print(p->code.assign.left, fd); 290 | fprintf(fd, " := "); 291 | tac_opd_print(p->code.assign.right, fd); 292 | fprintf(fd, "\n"); 293 | break; 294 | case ADD: 295 | tac_opd_print(p->code.add.left, fd); 296 | fprintf(fd, " := "); 297 | tac_opd_print(p->code.add.r1, fd); 298 | fprintf(fd, " + "); 299 | tac_opd_print(p->code.add.r2, fd); 300 | fprintf(fd, "\n"); 301 | break; 302 | case SUB: 303 | tac_opd_print(p->code.sub.left, fd); 304 | fprintf(fd, " := "); 305 | tac_opd_print(p->code.sub.r1, fd); 306 | fprintf(fd, " - "); 307 | tac_opd_print(p->code.sub.r2, fd); 308 | fprintf(fd, "\n"); 309 | break; 310 | case MUL: 311 | tac_opd_print(p->code.mul.left, fd); 312 | fprintf(fd, " := "); 313 | tac_opd_print(p->code.mul.r1, fd); 314 | fprintf(fd, " * "); 315 | tac_opd_print(p->code.mul.r2, fd); 316 | fprintf(fd, "\n"); 317 | break; 318 | case DIV: 319 | tac_opd_print(p->code.div.left, fd); 320 | fprintf(fd, " := "); 321 | tac_opd_print(p->code.div.r1, fd); 322 | fprintf(fd, " / "); 323 | tac_opd_print(p->code.div.r2, fd); 324 | fprintf(fd, "\n"); 325 | break; 326 | case ADDR: 327 | fprintf(fd, "%s := &%s\n", p->code.addr.left->char_val, p->code.addr.right->char_val); 328 | break; 329 | case FETCH: 330 | fprintf(fd, "%s := *%s\n", p->code.fetch.left->char_val, p->code.fetch.raddr->char_val); 331 | break; 332 | case DEREF: 333 | fprintf(fd, "*%s := ", p->code.deref.laddr->char_val); 334 | tac_opd_print(p->code.deref.right, fd); 335 | fprintf(fd, "\n"); 336 | break; 337 | case GOTO: 338 | fprintf(fd, "GOTO "); 339 | tac_opd_print(p->code.goto_.labelno, fd); 340 | fprintf(fd, "\n"); 341 | break; 342 | case IFLT: 343 | fprintf(fd, "IF "); 344 | tac_opd_print(p->code.iflt.c1, fd); 345 | fprintf(fd, " < "); 346 | tac_opd_print(p->code.iflt.c2, fd); 347 | fprintf(fd, " GOTO "); 348 | tac_opd_print(p->code.iflt.labelno, fd); 349 | fprintf(fd, "\n"); 350 | break; 351 | case IFLE: 352 | fprintf(fd, "IF "); 353 | tac_opd_print(p->code.ifle.c1, fd); 354 | fprintf(fd, " <= "); 355 | tac_opd_print(p->code.ifle.c2, fd); 356 | fprintf(fd, " GOTO "); 357 | tac_opd_print(p->code.ifle.labelno, fd); 358 | fprintf(fd, "\n"); 359 | break; 360 | case IFGT: 361 | fprintf(fd, "IF "); 362 | tac_opd_print(p->code.ifgt.c1, fd); 363 | fprintf(fd, " > "); 364 | tac_opd_print(p->code.ifgt.c2, fd); 365 | fprintf(fd, " GOTO "); 366 | tac_opd_print(p->code.ifgt.labelno, fd); 367 | fprintf(fd, "\n"); 368 | break; 369 | case IFGE: 370 | fprintf(fd, "IF "); 371 | tac_opd_print(p->code.ifge.c1, fd); 372 | fprintf(fd, " >= "); 373 | tac_opd_print(p->code.ifge.c2, fd); 374 | fprintf(fd, " GOTO "); 375 | tac_opd_print(p->code.ifge.labelno, fd); 376 | fprintf(fd, "\n"); 377 | break; 378 | case IFNE: 379 | fprintf(fd, "IF "); 380 | tac_opd_print(p->code.ifne.c1, fd); 381 | fprintf(fd, " != "); 382 | tac_opd_print(p->code.ifne.c2, fd); 383 | fprintf(fd, " GOTO "); 384 | tac_opd_print(p->code.ifne.labelno, fd); 385 | fprintf(fd, "\n"); 386 | break; 387 | case IFEQ: 388 | fprintf(fd, "IF "); 389 | tac_opd_print(p->code.ifeq.c1, fd); 390 | fprintf(fd, " == "); 391 | tac_opd_print(p->code.ifeq.c2, fd); 392 | fprintf(fd, " GOTO "); 393 | tac_opd_print(p->code.ifeq.labelno, fd); 394 | fprintf(fd, "\n"); 395 | break; 396 | case RETURN: 397 | fprintf(fd, "RETURN "); 398 | tac_opd_print(p->code.return_.var, fd); 399 | fprintf(fd, "\n"); 400 | break; 401 | case DEC: 402 | assert(p->code.dec.var->kind == OP_POINTER); 403 | // DEC should not followed &v 404 | fprintf(fd, "DEC %s %d\n", p->code.dec.var->char_val, p->code.dec.size); 405 | break; 406 | case ARG: 407 | fprintf(fd, "ARG "); 408 | tac_opd_print(p->code.arg.var, fd); 409 | fprintf(fd, "\n"); 410 | break; 411 | case CALL: 412 | tac_opd_print(p->code.call.ret, fd); 413 | fprintf(fd, " := CALL %s\n", p->code.call.funcname); 414 | break; 415 | case PARAM: 416 | fprintf(fd, "PARAM "); 417 | tac_opd_print(p->code.param.p, fd); 418 | fprintf(fd, "\n"); 419 | break; 420 | case READ: 421 | fprintf(fd, "READ "); 422 | tac_opd_print(p->code.read.p, fd); 423 | fprintf(fd, "\n"); 424 | break; 425 | case WRITE: 426 | fprintf(fd, "WRITE "); 427 | tac_opd_print(p->code.write.p, fd); 428 | fprintf(fd, "\n"); 429 | break; 430 | case NONE: 431 | break; 432 | } 433 | p = p->next; 434 | } 435 | } 436 | 437 | void tac_insert(tac *head, tac *seg){ 438 | tac *p, *q; 439 | q = head->next; 440 | head->next = seg; 441 | seg->prev = head; 442 | p = seg; 443 | while(p->next != NULL) 444 | p = p->next; 445 | p->next = q; 446 | if(q != NULL) 447 | q->prev = p; 448 | } 449 | 450 | void tac_append(tac *head, tac *seg){ 451 | tac *p; 452 | p = head; 453 | while(p->next != NULL) 454 | p = p->next; 455 | tac_insert(p, seg); 456 | } 457 | 458 | tac *tac_init_label(tac_opd *labelno){ 459 | tac *self = (tac*)malloc(sizeof(tac)); 460 | self->code.kind = LABEL; 461 | self->code.label.labelno = labelno; 462 | self->prev = self->next = NULL; 463 | return self; 464 | } 465 | 466 | tac *tac_init_function(char *funcname){ 467 | tac *self = (tac*)malloc(sizeof(tac)); 468 | self->code.kind = FUNCTION; 469 | self->code.function.funcname = (char*)malloc(32); 470 | sprintf(self->code.function.funcname, "%s", funcname); 471 | self->prev = self->next = NULL; 472 | return self; 473 | } 474 | 475 | tac *tac_init_assign(tac_opd *left, tac_opd *right){ 476 | tac *self = (tac*)malloc(sizeof(tac)); 477 | self->code.kind = ASSIGN; 478 | self->code.assign.left = left; 479 | self->code.assign.right = right; 480 | self->prev = self->next = NULL; 481 | return self; 482 | } 483 | 484 | tac *tac_init_add(tac_opd *left, tac_opd *r1, tac_opd *r2){ 485 | tac *self = (tac*)malloc(sizeof(tac)); 486 | self->code.kind = ADD; 487 | self->code.add.left = left; 488 | self->code.add.r1 = r1; 489 | self->code.add.r2 = r2; 490 | self->prev = self->next = NULL; 491 | return self; 492 | } 493 | 494 | tac *tac_init_sub(tac_opd *left, tac_opd *r1, tac_opd *r2){ 495 | tac *self = (tac*)malloc(sizeof(tac)); 496 | self->code.kind = SUB; 497 | self->code.sub.left = left; 498 | self->code.sub.r1 = r1; 499 | self->code.sub.r2 = r2; 500 | self->prev = self->next = NULL; 501 | return self; 502 | } 503 | 504 | tac *tac_init_mul(tac_opd *left, tac_opd *r1, tac_opd *r2){ 505 | tac *self = (tac*)malloc(sizeof(tac)); 506 | self->code.kind = MUL; 507 | self->code.mul.left = left; 508 | self->code.mul.r1 = r1; 509 | self->code.mul.r2 = r2; 510 | self->prev = self->next = NULL; 511 | return self; 512 | } 513 | 514 | tac *tac_init_div(tac_opd *left, tac_opd *r1, tac_opd *r2){ 515 | tac *self = (tac*)malloc(sizeof(tac)); 516 | self->code.kind = DIV; 517 | self->code.div.left = left; 518 | self->code.div.r1 = r1; 519 | self->code.div.r2 = r2; 520 | self->prev = self->next = NULL; 521 | return self; 522 | } 523 | 524 | tac *tac_init_addr(tac_opd *left, tac_opd *right){ 525 | assert(right->kind == OP_POINTER); 526 | tac *self = (tac*)malloc(sizeof(tac)); 527 | self->code.kind = ADDR; 528 | self->code.addr.left = left; 529 | self->code.addr.right = right; 530 | self->prev = self->next = NULL; 531 | return self; 532 | } 533 | 534 | tac *tac_init_fetch(tac_opd *left, tac_opd *raddr){ 535 | tac *self = (tac*)malloc(sizeof(tac)); 536 | self->code.kind = FETCH; 537 | self->code.fetch.left = left; 538 | self->code.fetch.raddr = raddr; 539 | self->prev = self->next = NULL; 540 | return self; 541 | } 542 | 543 | tac *tac_init_deref(tac_opd *laddr, tac_opd *right){ 544 | tac *self = (tac*)malloc(sizeof(tac)); 545 | self->code.kind = DEREF ; 546 | self->code.deref.laddr = laddr; 547 | self->code.deref.right = right; 548 | self->prev = self->next = NULL; 549 | return self; 550 | } 551 | 552 | tac *tac_init_goto(tac_opd *labelno){ 553 | tac *self = (tac*)malloc(sizeof(tac)); 554 | self->code.kind = GOTO; 555 | self->code.goto_.labelno = labelno; 556 | self->prev = self->next = NULL; 557 | return self; 558 | } 559 | 560 | tac *tac_init_iflt(tac_opd *c1, tac_opd *c2, tac_opd *labelno){ 561 | tac *self = (tac*)malloc(sizeof(tac)); 562 | self->code.kind = IFLT; 563 | self->code.iflt.c1 = c1; 564 | self->code.iflt.c2 = c2; 565 | self->code.iflt.labelno = labelno; 566 | self->prev = self->next = NULL; 567 | return self; 568 | } 569 | 570 | tac *tac_init_ifle(tac_opd *c1, tac_opd *c2, tac_opd *labelno){ 571 | tac *self = (tac*)malloc(sizeof(tac)); 572 | self->code.kind = IFLE; 573 | self->code.ifle.c1 = c1; 574 | self->code.ifle.c2 = c2; 575 | self->code.ifle.labelno = labelno; 576 | self->prev = self->next = NULL; 577 | return self; 578 | } 579 | 580 | tac *tac_init_ifgt(tac_opd *c1, tac_opd *c2, tac_opd *labelno){ 581 | tac *self = (tac*)malloc(sizeof(tac)); 582 | self->code.kind = IFGT; 583 | self->code.ifgt.c1 = c1; 584 | self->code.ifgt.c2 = c2; 585 | self->code.ifgt.labelno = labelno; 586 | self->prev = self->next = NULL; 587 | return self; 588 | } 589 | 590 | tac *tac_init_ifge(tac_opd *c1, tac_opd *c2, tac_opd *labelno){ 591 | tac *self = (tac*)malloc(sizeof(tac)); 592 | self->code.kind = IFGE; 593 | self->code.ifge.c1 = c1; 594 | self->code.ifge.c2 = c2; 595 | self->code.ifge.labelno = labelno; 596 | self->prev = self->next = NULL; 597 | return self; 598 | } 599 | 600 | tac *tac_init_ifne(tac_opd *c1, tac_opd *c2, tac_opd *labelno){ 601 | tac *self = (tac*)malloc(sizeof(tac)); 602 | self->code.kind = IFNE; 603 | self->code.ifne.c1 = c1; 604 | self->code.ifne.c2 = c2; 605 | self->code.ifne.labelno = labelno; 606 | self->prev = self->next = NULL; 607 | return self; 608 | } 609 | 610 | tac *tac_init_ifeq(tac_opd *c1, tac_opd *c2, tac_opd *labelno){ 611 | tac *self = (tac*)malloc(sizeof(tac)); 612 | self->code.kind = IFEQ; 613 | self->code.ifeq.c1 = c1; 614 | self->code.ifeq.c2 = c2; 615 | self->code.ifeq.labelno = labelno; 616 | self->prev = self->next = NULL; 617 | return self; 618 | } 619 | 620 | tac *tac_init_return(tac_opd *var){ 621 | tac *self = (tac*)malloc(sizeof(tac)); 622 | self->code.kind = RETURN; 623 | self->code.return_.var = var; 624 | self->prev = self->next = NULL; 625 | return self; 626 | } 627 | 628 | tac *tac_init_dec(tac_opd *var, int size){ 629 | tac *self = (tac*)malloc(sizeof(tac)); 630 | self->code.kind = DEC; 631 | self->code.dec.var = var; 632 | self->code.dec.size = size; 633 | self->prev = self->next = NULL; 634 | return self; 635 | } 636 | 637 | tac *tac_init_arg(tac_opd *var){ 638 | tac *self = (tac*)malloc(sizeof(tac)); 639 | self->code.kind = ARG; 640 | self->code.arg.var = var; 641 | self->prev = self->next = NULL; 642 | return self; 643 | } 644 | 645 | tac *tac_init_call(tac_opd *ret, char *funcname){ 646 | tac *self = (tac*)malloc(sizeof(tac)); 647 | self->code.kind = CALL; 648 | self->code.call.ret = ret; 649 | self->code.call.funcname = (char*)malloc(32); 650 | sprintf(self->code.call.funcname, "%s", funcname); 651 | self->prev = self->next = NULL; 652 | return self; 653 | } 654 | 655 | tac *tac_init_param(tac_opd *p){ 656 | tac *self = (tac*)malloc(sizeof(tac)); 657 | self->code.kind = PARAM; 658 | self->code.param.p = p; 659 | self->prev = self->next = NULL; 660 | return self; 661 | } 662 | 663 | tac *tac_init_read(tac_opd *p){ 664 | tac *self = (tac*)malloc(sizeof(tac)); 665 | self->code.kind = READ; 666 | self->code.read.p = p; 667 | self->prev = self->next = NULL; 668 | return self; 669 | } 670 | 671 | tac *tac_init_write(tac_opd *p){ 672 | tac *self = (tac*)malloc(sizeof(tac)); 673 | self->code.kind = WRITE; 674 | self->code.write.p = p; 675 | self->prev = self->next = NULL; 676 | return self; 677 | } 678 | 679 | tac *tac_init_none(){ 680 | tac *self = (tac*)malloc(sizeof(tac)); 681 | self->code.kind = NONE; 682 | self->prev = self->next = NULL; 683 | return self; 684 | } 685 | -------------------------------------------------------------------------------- /project/phase4/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 | -------------------------------------------------------------------------------- /project/phase4/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 | -------------------------------------------------------------------------------- /project/phase4/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 | -------------------------------------------------------------------------------- /project/phase4/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 | -------------------------------------------------------------------------------- /project/phase4/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 | -------------------------------------------------------------------------------- /project/phase4/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 | -------------------------------------------------------------------------------- /project/phase4/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 | -------------------------------------------------------------------------------- /spl-spec/syntax.txt: -------------------------------------------------------------------------------- 1 | /* 2 | * Error type: 3 | * 1. missing closing symbol, eg. parenthese, quotation, etc. 4 | * 2. missing comma or semicolon 5 | * 6 | * (remark: '$' stands for empty terminal) 7 | */ 8 | 9 | /* high-level definition */ 10 | Program -> ExtDefList 11 | ExtDefList -> ExtDef ExtDefList 12 | | $ 13 | ExtDef -> Specifier ExtDecList SEMI 14 | | Specifier SEMI 15 | | Specifier FunDec CompSt 16 | ExtDecList -> VarDec 17 | | VarDec COMMA ExtDecList 18 | 19 | /* specifier */ 20 | Specifier -> TYPE 21 | | StructSpecifier 22 | StructSpecifier -> STRUCT ID LC DefList RC 23 | | STRUCT ID 24 | 25 | /* declarator */ 26 | VarDec -> ID 27 | | VarDec LB INT RB 28 | FunDec -> ID LP VarList RP 29 | | ID LP RP 30 | VarList -> ParamDec COMMA VarList 31 | | ParamDec 32 | ParamDec -> Specifier VarDec 33 | 34 | /* statement */ 35 | CompSt -> LC DefList StmtList RC 36 | StmtList -> Stmt StmtList 37 | | $ 38 | Stmt -> Exp SEMI 39 | | CompSt 40 | | RETURN Exp SEMI 41 | | IF LP Exp RP Stmt 42 | | IF LP Exp RP Stmt ELSE Stmt 43 | | WHILE LP Exp RP Stmt 44 | 45 | /* local definition */ 46 | DefList -> Def DefList 47 | | $ 48 | Def -> Specifier DecList SEMI 49 | DecList -> Dec 50 | | Dec COMMA DecList 51 | Dec -> VarDec 52 | | VarDec ASSIGN Exp 53 | 54 | /* Expression */ 55 | Exp -> Exp ASSIGN Exp 56 | | Exp AND Exp 57 | | Exp OR Exp 58 | | Exp LT Exp 59 | | Exp LE Exp 60 | | Exp GT Exp 61 | | Exp GE Exp 62 | | Exp NE Exp 63 | | Exp EQ Exp 64 | | Exp PLUS Exp 65 | | Exp MINUS Exp 66 | | Exp MUL Exp 67 | | Exp DIV Exp 68 | | LP Exp RP 69 | | MINUS Exp 70 | | NOT Exp 71 | | ID LP Args RP 72 | | ID LP RP 73 | | Exp LB Exp RB 74 | | Exp DOT ID 75 | | ID 76 | | INT 77 | | FLOAT 78 | | CHAR 79 | Args -> Exp COMMA Args 80 | | Exp -------------------------------------------------------------------------------- /spl-spec/token.txt: -------------------------------------------------------------------------------- 1 | /* 2 | * Error type: 3 | * 1. undefined tokens, eg., '@', '#' as non-literal token 4 | * 2. illegal hex int, eg., 0x5gg 5 | * 3. illegal hex char, eg., '\x9', '\xt0' 6 | */ 7 | 8 | INT -> /* integer in 32-bits (decimal or hexadecimal) */ 9 | FLOAT -> /* floating point number (only dot-form) */ 10 | CHAR -> /* single character (printable or hex-form) */ 11 | ID -> /* identifier */ 12 | TYPE -> int | float | char 13 | STRUCT -> struct 14 | IF -> if 15 | ELSE -> else 16 | WHILE -> while 17 | RETURN -> return 18 | DOT -> . 19 | SEMI -> ; 20 | COMMA -> , 21 | ASSIGN -> = 22 | LT -> < 23 | LE -> <= 24 | GT -> > 25 | GE -> >= 26 | NE -> != 27 | EQ -> == 28 | PLUS -> + 29 | MINUS -> - 30 | MUL -> * 31 | DIV -> / 32 | AND -> && 33 | OR -> || 34 | NOT -> ! 35 | LP -> ( 36 | RP -> ) 37 | LB -> [ 38 | RB -> ] 39 | LC -> { 40 | RC -> } --------------------------------------------------------------------------------