├── Lab1 ├── Digit.cpp ├── LexicalAnalysis.cpp ├── README.md └── 词法分析器.pdf ├── Lab2 ├── LL.cpp ├── LR(1).cpp ├── README.md ├── action.txt ├── exp.txt ├── goto.txt └── 语法分析.pdf └── README.md /Lab1/Digit.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Digit.cpp 3 | // Compilation principle 4 | // 5 | // Created by 周天逸 on 2023/11/19. 6 | // 7 | 8 | #include 9 | using namespace std; 10 | 11 | 12 | 13 | class Solution { 14 | public: 15 | enum State { 16 | STATE_INITIAL, 17 | STATE_INT_SIGN, 18 | STATE_INTEGER, 19 | STATE_POINT, 20 | STATE_POINT_WITHOUT_INT, 21 | STATE_FRACTION, 22 | STATE_EXP, 23 | STATE_EXP_SIGN, 24 | STATE_EXP_NUMBER, 25 | STATE_END 26 | }; 27 | 28 | enum CharType { 29 | CHAR_NUMBER, 30 | CHAR_EXP, 31 | CHAR_POINT, 32 | CHAR_SIGN, 33 | CHAR_ILLEGAL 34 | }; 35 | 36 | CharType toCharType(char ch) { 37 | if (ch >= '0' && ch <= '9') { 38 | return CHAR_NUMBER; 39 | } else if (ch == 'e' || ch == 'E') { 40 | return CHAR_EXP; 41 | } else if (ch == '.') { 42 | return CHAR_POINT; 43 | } else if (ch == '+' || ch == '-') { 44 | return CHAR_SIGN; 45 | } else { 46 | return CHAR_ILLEGAL; 47 | } 48 | } 49 | 50 | bool isNumber(string s) { 51 | unordered_map> transfer{ 52 | { 53 | STATE_INITIAL, { 54 | {CHAR_NUMBER, STATE_INTEGER}, 55 | {CHAR_POINT, STATE_POINT_WITHOUT_INT}, 56 | {CHAR_SIGN, STATE_INT_SIGN} 57 | } 58 | }, { 59 | STATE_INT_SIGN, { 60 | {CHAR_NUMBER, STATE_INTEGER}, 61 | {CHAR_POINT, STATE_POINT_WITHOUT_INT} 62 | } 63 | }, { 64 | STATE_INTEGER, { 65 | {CHAR_NUMBER, STATE_INTEGER}, 66 | {CHAR_EXP, STATE_EXP}, 67 | {CHAR_POINT, STATE_POINT} 68 | } 69 | }, { 70 | STATE_POINT, { 71 | {CHAR_NUMBER, STATE_FRACTION}, 72 | {CHAR_EXP, STATE_EXP} 73 | } 74 | }, { 75 | STATE_POINT_WITHOUT_INT, { 76 | {CHAR_NUMBER, STATE_FRACTION} 77 | } 78 | }, { 79 | STATE_FRACTION, 80 | { 81 | {CHAR_NUMBER, STATE_FRACTION}, 82 | {CHAR_EXP, STATE_EXP} 83 | } 84 | }, { 85 | STATE_EXP, 86 | { 87 | {CHAR_NUMBER, STATE_EXP_NUMBER}, 88 | {CHAR_SIGN, STATE_EXP_SIGN} 89 | } 90 | }, { 91 | STATE_EXP_SIGN, { 92 | {CHAR_NUMBER, STATE_EXP_NUMBER} 93 | } 94 | }, { 95 | STATE_EXP_NUMBER, { 96 | {CHAR_NUMBER, STATE_EXP_NUMBER} 97 | } 98 | } 99 | }; 100 | 101 | int len = s.length(); 102 | State st = STATE_INITIAL; 103 | 104 | for (int i = 0; i < len; i++) { 105 | CharType typ = toCharType(s[i]); 106 | if (transfer[st].find(typ) == transfer[st].end()) { 107 | return false; 108 | } else { 109 | st = transfer[st][typ]; 110 | } 111 | } 112 | return st == STATE_INTEGER || st == STATE_POINT || st == STATE_FRACTION || st == STATE_EXP_NUMBER || st == STATE_END; 113 | } 114 | }; 115 | 116 | -------------------------------------------------------------------------------- /Lab1/LexicalAnalysis.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinZhou6/SEU-Compiler-Project/88ca049511a03371572620815a8a596b7c27d2e6/Lab1/LexicalAnalysis.cpp -------------------------------------------------------------------------------- /Lab1/README.md: -------------------------------------------------------------------------------- 1 | # Lab1 2 | -------------------------------------------------------------------------------- /Lab1/词法分析器.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinZhou6/SEU-Compiler-Project/88ca049511a03371572620815a8a596b7c27d2e6/Lab1/词法分析器.pdf -------------------------------------------------------------------------------- /Lab2/LL.cpp: -------------------------------------------------------------------------------- 1 | //// 2 | //// LL.cpp 3 | //// Compilation principle 4 | //// 5 | //// Created by 周天逸 on 2023/11/25. 6 | //// 7 | // 8 | //#include 9 | //#include 10 | //#include 11 | //#define M 5 12 | //#define N 8 13 | // 14 | //using namespace std; 15 | // 16 | //stack analyse; 17 | //char Vn[M] = { 'E', 'G', 'T', 'S', 'F' }; 18 | //char Vt[N] = { 'i', '+', '-', '*', '/', '(', ')', '$' }; 19 | //string L[M][N] = { 20 | // { "TG", "ERROR", "ERROR", "ERROR", "ERROR", "TG", "ERROR", "ERROR" }, 21 | // { "ERROR", "+TG", "-TG", "ERROR", "ERROR", "ERROR", "NULL", "NULL" }, 22 | // { "FS", "ERROR", "ERROR", "ERROR", "ERROR", "FS", "ERROR", "ERROR" }, 23 | // { "ERROR", "NULL", "NULL", "*FS", "/FS", "ERROR", "NULL", "NULL" }, 24 | // { "i", "ERROR", "ERROR", "ERROR", "ERROR", "(E)", "ERROR", "ERROR" } 25 | //}; 26 | // 27 | //void outstack() 28 | //{ 29 | // 30 | // stack temp; 31 | // 32 | // int l = analyse.size(); 33 | // for (int i = 0; i < l; i++) 34 | // { 35 | // char a = analyse.top(); 36 | // analyse.pop(); 37 | // temp.push(a); 38 | // } 39 | // 40 | // l = temp.size(); 41 | // for (int i = 0; i < l; i++) 42 | // { 43 | // char a = temp.top(); 44 | // temp.pop(); 45 | // analyse.push(a); 46 | // cout << a; 47 | // } 48 | //} 49 | // 50 | //void outinput(string s, int n) 51 | //{ 52 | // for (; n < s.length(); n++) 53 | // cout << s[n]; 54 | //} 55 | // 56 | //void LL_1(string input) 57 | //{ 58 | // 59 | // analyse.push('$'); 60 | // analyse.push(Vn[0]); 61 | // // 62 | // cout << "步骤" << "\t 剩余分析栈" << "\t 剩余输入串" << "产生式" << "\t动作" << endl; 63 | // cout << '0' << "\t"; 64 | // outstack(); 65 | // cout << "\t\t" << input; 66 | // cout << "\t\t\t\t" << "初始化" << endl; 67 | // 68 | // int i = 0; 69 | // for (int j = 1; i < input.length(); j++) 70 | // { 71 | // 72 | // char v = analyse.top(); 73 | // analyse.pop(); 74 | // 75 | // if (v == input[i]) 76 | // { 77 | // cout << j << "\t"; 78 | // outstack(); 79 | // cout << "\t\t"; 80 | // outinput(input, i+1); 81 | // cout << "\t\t" << input[i] << "匹配" << "\t\tPOP" << endl; 82 | // i++; 83 | // continue; 84 | // } 85 | // else 86 | // { 87 | // int m, n; 88 | // m = -1; 89 | // 90 | // for (int j = 0; j < M; j++) 91 | // { 92 | // if (v == Vn[j]) 93 | // { 94 | // m = j; 95 | // break; 96 | // } 97 | // 98 | // } 99 | // 100 | // if (m == -1) 101 | // { 102 | // cout << "失败"; 103 | // cout << "第" << i << "个字符" << input[i] << "匹配错误" << endl; 104 | // cout << input << "非法串" << endl; 105 | // break; 106 | // } 107 | // 108 | // for (int j = 0; j < N; j++) 109 | // { 110 | // if (input[i] == Vt[j]) 111 | // { 112 | // n = j; 113 | // break; 114 | // } 115 | // } 116 | // 117 | // if (L[m][n] == "ERROR") 118 | // { 119 | // cout << "第" << i << "个字符" << input[i] << "匹配错误" << endl; 120 | // cout << input << "非法串" << endl; 121 | // break; 122 | // } 123 | // if (L[m][n] == "NULL") 124 | // { 125 | // cout << j << "\t"; 126 | // outstack(); 127 | // cout << "\t\t"; 128 | // outinput(input, i); 129 | // cout << "\t\t\t\t" << v << "->" << "ɛ" << endl; 130 | // continue; 131 | // } 132 | // else 133 | // { 134 | // // 135 | // string t = ""; 136 | // for (int j = L[m][n].length() - 1; j >= 0; j--) 137 | // { 138 | // t += L[m][n][j]; 139 | // analyse.push(L[m][n][j]); 140 | // } 141 | // cout << j << "\t"; 142 | // outstack(); 143 | // cout << "\t\t"; 144 | // outinput(input, i); 145 | // cout << "\t\t" << v << "->" << L[m][n]; 146 | // cout << "\t\tPOP,PUSH(" << t << ")"; 147 | // } 148 | // } 149 | // cout << endl; 150 | // } 151 | // if (i == input.length()) 152 | // cout << input << "合法串" << endl; 153 | //} 154 | // 155 | //int main() 156 | //{ 157 | // cout << "输入以$结尾的符号串"; 158 | // string in; 159 | // cin >> in; 160 | // cout << "匹配过程" << endl; 161 | // LL_1(in); 162 | // 163 | //} 164 | // 165 | // 166 | -------------------------------------------------------------------------------- /Lab2/LR(1).cpp: -------------------------------------------------------------------------------- 1 | // 2 | // LR(1).cpp 3 | // Compilation principle 4 | // 5 | // Created by 周天逸 on 2023/11/26. 6 | // 7 | 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | using namespace std; 15 | const string ExpFileName = "exp.txt"; 16 | const string GotoFileName = "goto.txt"; 17 | const string ActionFileName = "action.txt"; 18 | const int Null = -1; 19 | // ACTION表 20 | // + * ( ) i # 21 | string action[12][6]; 22 | // goto表 23 | // a b # 24 | int _goto[12][3]; 25 | string vt = "+*()i#"; // 终结符表 26 | string vn = "ETF"; // 非终结符表 27 | string LR[6] = { "E->E+T", "E->T", "T->T*F", "T->F", "F->(E)", "F->i" }; // 存放产生式 28 | 29 | // 读文件 30 | vector readFile(string fileName) { 31 | vector res; 32 | try { 33 | ifstream fin; 34 | fin.open(fileName); 35 | string temp; 36 | while (getline(fin, temp)) 37 | res.push_back(temp); 38 | return res; 39 | } 40 | catch (const exception& e) { 41 | cerr << e.what() << '\n'; 42 | return res; 43 | } 44 | } 45 | void printActions() { 46 | cout << "-----------------ACTION表------------------" << endl; 47 | cout << "+\t*\t(\t)\ti\t$" << endl; 48 | for (int i = 0; i < 12; ++i) { 49 | for (int j = 0; j < 6; ++j) 50 | cout << action[i][j] << "\t"; 51 | cout << endl; 52 | } 53 | } 54 | void printGotos() { 55 | cout << "-----------------GOTO表------------------" << endl; 56 | cout << "E\tT\tF" << endl; 57 | for (int i = 0; i < 12; ++i) { 58 | for (int j = 0; j < 3; ++j) 59 | cout << _goto[i][j] << "\t"; 60 | cout << endl; 61 | } 62 | } 63 | void init() { 64 | vector actions = readFile(ActionFileName); 65 | for (int i = 0; i < 12; ++i) { 66 | int cnt = 0; 67 | string row = actions[i]; 68 | int len = actions[i].length(); 69 | for (int j = 0; j < len; ++j) { 70 | string temp = ""; 71 | while (j < len && row[j] != ' ' && row[j] != '\t') { 72 | temp += row[j]; 73 | ++j; 74 | } 75 | while (j < len && (row[j] == ' ' || row[j] == '\t')) 76 | ++j; 77 | --j; 78 | action[i][cnt++] = temp; 79 | } 80 | 81 | } 82 | printActions(); 83 | vector gotos = readFile(GotoFileName); 84 | for (int i = 0; i < 12; ++i) { 85 | int cnt = 0; 86 | string row = gotos[i]; 87 | int len = row.length(); 88 | for (int j = 0; j < len; ++j) { 89 | string temp = ""; 90 | while (j < len && row[j] != ' ' && row[j] != '\t') { 91 | temp += row[j]; 92 | ++j; 93 | } 94 | while (j < len && (row[j] == ' ' || row[j] == '\t')) 95 | ++j; 96 | --j; 97 | _goto[i][cnt++] = (temp == "N") ? Null : stoi(temp); 98 | } 99 | } 100 | printGotos(); 101 | } 102 | bool isTerminator(char c) { 103 | return vt.find(c) != string::npos; 104 | } 105 | int findTerminator(char c) { // 返回终结符所处下标 106 | return vt.find(c); 107 | } 108 | int findNonTerminator(char c) { // 返回非终结符的下标 109 | return vn.find(c); 110 | } 111 | // 将栈转换为字符串返回 112 | string s2string(stack s) { 113 | string str = ""; 114 | while(!s.empty()) { 115 | str += to_string(s.top()) + " "; 116 | s.pop(); 117 | } 118 | return str; 119 | } 120 | // 输出剩余输入串 121 | void printRestInput(string exp, int start, int len) { 122 | for(int i = start; i < len; ++i) 123 | cout << exp[i]; 124 | cout << '\t'; 125 | } 126 | void analyzeLR1(string exp) { // 分析一个表达式 127 | int len = exp.length(); 128 | stack chars; // 符号栈 129 | stack state; // 状态栈 130 | state.push(0); // 初始状态为0 131 | chars.push('#'); // 初始符号为# 132 | string charsStr = "#"; 133 | stack copyState; 134 | copyState.push(0); 135 | int cnt = 0; // 序号 136 | int idx = 0; // 当前输入指针 137 | cout << "序号\t\t状态栈\t\t符号栈\t\t输入串\t\t描述" << endl; 138 | cout << cnt++ << '\t' << s2string(copyState) << '\t' << charsStr << '\t' << exp << '\t' << " 初始状态 " << endl; 139 | while(1) { 140 | int nowState = state.top(); 141 | char nowChar = exp[idx]; // 当前输入字符 142 | int isT = findTerminator(nowChar); 143 | if(isT == Null) { // 非终结符 144 | cout << "Error!" << "出现非法字符,程序错误退出" < exps = readFile(ExpFileName); 197 | int len = exps.size(); 198 | for (int i = 0; i < len; i++) { 199 | string exp = exps[i]; 200 | cout << "\n------------------待分析表达式" << i+1 << ":"<< exp << "--------------------" << endl; 201 | bool flag = true; 202 | for (int j = 0; j < exp.length(); j++) { 203 | if (!isTerminator(exp[j])) { 204 | cout << "第 "<< i+1 << "行输入的字符串不合法,请重新输入" << endl; 205 | flag = false; 206 | break; 207 | } 208 | } 209 | if (flag) { 210 | cout << "表达式" << i+1 << ":" << exp << "分析开始" << endl; 211 | analyzeLR1(exp); 212 | } 213 | } 214 | return 0; 215 | } 216 | -------------------------------------------------------------------------------- /Lab2/README.md: -------------------------------------------------------------------------------- 1 | # Lab2 2 | #### 实验目的 3 | 构造LL(1)文法自顶向下语法分析程序 4 | 1. 输入字符串 5 | 2. 输出语法树(推导序列) 6 | 7 | #### 实验内容 8 | 1. 方法 9 | 1. 定义LL(1)文法 10 | 2. 求出First, Follow 集 11 | 3. 构造LL(1)分析表 12 | 4. 根据分析表编程 13 | 2. LL(1)文法 14 | ```cpp 15 | LL(1)文法 16 | (1)E->TG 17 | (2)G->+TG 18 | (3)G->-TG 19 | (4)G->ε 20 | (5)T->FS 21 | (6)S->*FS 22 | (7)S->/FS 23 | (8)S->ε 24 | (9)F->(E) 25 | (10)F->i 26 | ``` 27 | 3. 构造First,Follow 28 | 29 | 30 | | | First | Follow | 31 | |--------|-------|-------------| 32 | | E->TG | ( , i | $, ) | 33 | | G->+TG | + | $,) | 34 | | G->-TG | - | $,) | 35 | | G->ε | ε | $,) | 36 | | T->FS | (,i | +,-,$,) | 37 | | S->*FS | * | +,-,$,) | 38 | | S->/FS | / | +,-,$,) | 39 | | S->ε | ε | +,-,$,) | 40 | | F->(E) | ( | +,/,*,-,$,) | 41 | | F->i | i | +,/,*,-,$,) | 42 | 43 | 4. 核心算法描述 44 | 1. 先将‘$’与文法开始符E压入分析栈,并使输入字符指向input的第一位; 45 | 2. 弹出栈顶元素v,判断v是否与输入字符相同,是转至3,否转至4; 46 | 3. 输入字符移向input下一位,转至2;若已为最后一位转至8; 47 | 4. 判断v是否为非终结符,是转至5;否转至9; 48 | 5. 判断v与输入字符是否有产生式,是转至6,否转至9; 49 | 6. 判断产生式是否为ε;是转至2,否转至7; 50 | 7. 将产生式逆序压入分析栈中,转至2; 51 | 8. 输出过程步骤,以及为合法字符串; 52 | 9. 输出错误位置并结束; 53 | 5. 数据结构 54 | 1. 使用一维数组存放非终结符和终结符 55 | 2. 使用二位数组存放LL(1)分析表 56 | 57 | ### 构造LR(1)文法自底向上语法分析程序 58 | 1. 输入字符串 59 | 2. 输出语法树(推导序列) 60 | 3. 使用文法 61 | ```cpp 62 | (0)S’->E 63 | 64 | (1)E->E+T 65 | 66 | (2)E->T 67 | 68 | (3)T->T*F 69 | 70 | (4)T->F 71 | 72 | (5)F->(E) 73 | 74 | (6)F->i 75 | ``` 76 | 4. 核心算法 77 | 1. 使用两个栈,一个为状态栈一个是符号栈,最开始时,只有状态0和文法开始符号E 78 | 2. 使用一个指针依次遍历每一个输入符号。 79 | 3. 在action表中对应栈顶和输入符号,进行转移。如果发现表中为N,则说明匹配错误,是非法串。 80 | 4. 如果要进行规约时,遍历产生式数组,找到使用的产生式。之后弹出对应数目的符号和状态,并将产生式头部放入栈顶。 81 | 5. 查看Goto表,如果发现在当前状态下栈顶的非终结符满足要求,则将要转移的状态加入状态栈中。 82 | 6. 最后如果能到达acc状态则说明满足要求为合法串。 83 | 84 | -------------------------------------------------------------------------------- /Lab2/action.txt: -------------------------------------------------------------------------------- 1 | N N s4 N s5 N 2 | s6 N N N N acc 3 | r2 s7 N r2 N r2 4 | r4 r4 N r4 N r4 5 | N N s4 N s5 N 6 | r6 r6 N r6 N r6 7 | N N s4 N s5 N 8 | N N s4 N s5 N 9 | s6 N N s11 N N 10 | r1 s7 N r1 N r1 11 | r3 r3 N r3 N r3 12 | r5 r5 N r5 N r5 13 | -------------------------------------------------------------------------------- /Lab2/exp.txt: -------------------------------------------------------------------------------- 1 | i+(i*i)*(i+i)# 2 | 3 | -------------------------------------------------------------------------------- /Lab2/goto.txt: -------------------------------------------------------------------------------- 1 | 1 2 3 2 | N N N 3 | N N N 4 | N N N 5 | 8 2 3 6 | N N N 7 | N 9 3 8 | N N 10 9 | N N N 10 | N N N 11 | N N N 12 | N N N 13 | -------------------------------------------------------------------------------- /Lab2/语法分析.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinZhou6/SEU-Compiler-Project/88ca049511a03371572620815a8a596b7c27d2e6/Lab2/语法分析.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SEU-Compiler-Project 2 | Lexical Analyzer Programming & Syntax Parser Programming 3 | 4 | ## Requirements on Lab1 5 | 6 | Programming based on FA 7 | 8 | - (a) Define some REs by yourself 9 | - (b) Convert REs into NFAs 10 | - (c) Merge these NFAs into a single NFA 11 | - (d) Convert the NFA into a DFA with minimum states 12 | - (e) Programming based on the DFA' 13 | 14 | ## Requirements on Lab2 15 | 16 | 1. **Input** 17 | - Stream of characters 18 | - CFG (Combination of CFGs of some classes of sentences) 19 | 20 | 2. **Output (Syntax tree)** 21 | - Sequence of derivations if top-down syntax analyzing methods are used. 22 | - Sequence of reductions if bottom-up syntax analyzing methods are used. 23 | 24 | 25 | ## Content 26 | 27 | ### Lab1 28 | 1. 实现对输入的代码进行分析,输出token序列. 29 | 2. 输⼊字符串判断是否满⾜科学计数法 30 | 31 | ### Lab2 32 | 1. 构造LL(1)⽂法⾃顶向下语法分析程序 33 | 2. 构造SLR(1)⽂法⾃底向上语法分析程序 34 | --------------------------------------------------------------------------------