├── .DS_Store ├── Ccompi1er ├── 2 ├── .DS_Store ├── AST.txt ├── ErrorLog.cpp ├── ErrorLog.txt ├── FinalProcess.py ├── MIPS │ ├── .DS_Store │ ├── .idea │ │ ├── MIPS.iml │ │ ├── inspectionProfiles │ │ │ └── profiles_settings.xml │ │ ├── misc.xml │ │ ├── modules.xml │ │ └── workspace.xml │ ├── MIPS.py │ ├── intercode.txt │ ├── objectcode.asm │ └── result.asm ├── Makefile ├── README.md ├── RGenerator.cpp ├── compiler ├── compiler.cpp ├── compiler.hpp ├── compiler.l ├── compiler.y ├── element.h ├── main.cpp ├── mylex.cpp ├── node.h ├── result.asm ├── test.c └── test.txt ├── README.md ├── aweSomeEditorhiahia.pro ├── aweSomeEditorhiahia.pro.user ├── bash.txt ├── main.cpp ├── mainwindow.cpp ├── mainwindow.h ├── mainwindow.ui └── src ├── codeeditor.cpp ├── codeeditor.h ├── myhighlighter.cpp ├── myhighlighter.h └── typedef.h /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whatlulumomo/MiniCompiler/7b0d4c8328e1771e6239bea91f46b0f1e5f9184d/.DS_Store -------------------------------------------------------------------------------- /Ccompi1er/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whatlulumomo/MiniCompiler/7b0d4c8328e1771e6239bea91f46b0f1e5f9184d/Ccompi1er/.DS_Store -------------------------------------------------------------------------------- /Ccompi1er/AST.txt: -------------------------------------------------------------------------------- 1 | 中间树 2 | FUNCTION main : 3 | Temp0 = CALL read 4 | var1 = Temp0 5 | Temp0 = #0 6 | var0 = Temp0 7 | LABEL label_0 : 8 | Temp1 = var0 < var1 9 | IF Temp1 != 0 GOTO label_1 10 | GOTO label_3 11 | LABEL label_1 : 12 | Temp2 = #2 13 | Temp3 = var0 % Temp2 14 | Temp2 = #1 15 | Temp3 = Temp3 == Temp2 16 | IF Temp3 == 0 GOTO label_4 17 | GOTO label_5 18 | LABEL label_4 : 19 | GOTO label_2 20 | LABEL label_5 : 21 | ARG var0 22 | CALL print 23 | LABEL label_2 : 24 | Temp4 = #1 25 | Temp5 = var0 + Temp4 26 | var0 = Temp5 27 | GOTO label_0 28 | LABEL label_3 : 29 | 30 | 31 | 32 | 33 | --------------函数表---------------- 34 | void main 35 | -------------------------------------------------------------------------------- /Ccompi1er/ErrorLog.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | struct line{ 7 | string content; 8 | int linenum; 9 | }; 10 | 11 | class ErrorLog{ 12 | vector log; 13 | public: 14 | 15 | void addLog(string content, int linenum){ 16 | struct line t; 17 | t.content = content; 18 | t.linenum = linenum; 19 | log.push_back(t); 20 | } 21 | void printErrorLog(){ 22 | ofstream mycout("ErrorLog.txt"); 23 | //cout << endl << "----------------错误报告----------------" << endl; 24 | //mycout << "----------------错误报告----------------" << endl; 25 | for(int i=0; i 0: 33 | with open("Errorlog.txt","w+") as f: 34 | for s in errorlist: 35 | f.writelines(s) -------------------------------------------------------------------------------- /Ccompi1er/MIPS/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whatlulumomo/MiniCompiler/7b0d4c8328e1771e6239bea91f46b0f1e5f9184d/Ccompi1er/MIPS/.DS_Store -------------------------------------------------------------------------------- /Ccompi1er/MIPS/.idea/MIPS.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | -------------------------------------------------------------------------------- /Ccompi1er/MIPS/.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /Ccompi1er/MIPS/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Ccompi1er/MIPS/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Ccompi1er/MIPS/.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 58 | 59 | 60 | 61 | temp 62 | 63 | 64 | 65 | 71 | 72 | 73 | 74 | 75 | true 76 | DEFINITION_ORDER 77 | 78 | 79 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 105 | 106 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 132 | 133 | 134 | 135 | 153 | 154 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 203 | 204 | 217 | 218 | 236 | 237 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 279 | 280 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 308 | 309 | 310 | 311 | 1527837370822 312 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 345 | 346 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | -------------------------------------------------------------------------------- /Ccompi1er/MIPS/MIPS.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import os 3 | import re 4 | 5 | regs=['$t0','$t1','$t2','$t3','$t4','$t5','$t6','$s0','$s1','$s2','$s3','$s4','$s5','$s6','s7'] # 't8' 't9' 6 | # regs=['$t0','$t1'] # 't7' 't8' 't9' 7 | regspecial = ['$t7', '$t8', '$t9'] 8 | specialindex = 0 # 3个特殊寄存器,主要负责导入导出内存溢出变量 9 | specialrecord = {} # 记录这三个寄存器存的东西 10 | 11 | table={} 12 | reg_ok={} 13 | variables=[] 14 | blocks = [] 15 | 16 | Obj=[] 17 | 18 | def Load_Var(Inter): 19 | global variables 20 | temp_re='(Temp\d+)' 21 | for line in Inter: 22 | temps=re.findall(temp_re,' '.join(line)) 23 | variables+=temps 24 | 25 | def Load_Inter(filename): 26 | lines=[] 27 | block = [] 28 | flag = False 29 | for line in open(filename,'r'): 30 | line=line.replace('\r','').replace('\n','') 31 | if line =='': 32 | flag = False 33 | continue 34 | if flag == False: 35 | if "中间树" in line: 36 | flag = True 37 | continue 38 | 39 | linelist = line.split(' ') 40 | lines.append(linelist) 41 | if linelist[0] == "FUNCTION": 42 | if len(block) > 0: 43 | blocks.append(block) 44 | block = [] 45 | block = [line] 46 | else: 47 | block.append(line) 48 | blocks.append(block) 49 | return lines 50 | 51 | 52 | GlobalRecord = {} 53 | spillBook = {} 54 | 55 | def getfromSpillReg(string): 56 | global specialindex,specialrecord 57 | for i in specialrecord: # 如果该内存变量正好和该寄存器匹配 58 | if string == specialrecord[i]: 59 | return i 60 | 61 | sreg = regspecial[specialindex] 62 | if sreg in specialrecord: 63 | print("\tsw %s,%d($sp)"%(sreg, spillBook[specialrecord[sreg]])) 64 | Obj.append("\tsw %s,%d($sp)"%(sreg, spillBook[specialrecord[sreg]])) 65 | 66 | specialrecord[sreg] = string 67 | print("\tlw %s,%d($sp)"%(sreg, spillBook[string])) 68 | Obj.append("\tlw %s,%d($sp)"%(sreg, spillBook[string])) 69 | specialindex = (specialindex+1)%3 70 | return sreg 71 | 72 | def GetRegFromRecord(string): 73 | if string in spillBook: 74 | return getfromSpillReg(string) 75 | return GlobalRecord[string][0] 76 | 77 | 78 | def get_R(string): 79 | if string in table: 80 | return table[string] 81 | for reg in regs: 82 | if reg_ok[reg] == 1: 83 | reg_ok[reg] = 0 84 | table[string] = reg 85 | return table[string] 86 | return None 87 | 88 | 89 | 90 | 91 | def translate(line): 92 | if line[0]=='LABEL': 93 | return line[1]+':' 94 | if line[1]=='=': 95 | if len(line)==3: 96 | if line[-1][0]=='#': 97 | return '\tli %s,%s'%(GetRegFromRecord(line[0]), line[-1].replace('#', '')) 98 | else: 99 | return '\tmove %s,%s'%(GetRegFromRecord(line[0]), GetRegFromRecord(line[2])) 100 | if len(line)==5: 101 | if line[3]=='+': 102 | if line[-1][0]=='#': 103 | return '\taddi %s,%s,%s'%(GetRegFromRecord(line[0]), GetRegFromRecord(line[2]), line[-1].replace('#', '')) 104 | else: 105 | return '\tadd %s,%s,%s'%(GetRegFromRecord(line[0]), GetRegFromRecord(line[2]), GetRegFromRecord( 106 | line[-1])) 107 | elif line[3]=='-': 108 | if line[-1][0]=='#': 109 | return '\taddi %s,%s,-%s'%(GetRegFromRecord(line[0]), GetRegFromRecord(line[2]), line[-1].replace('#', '')) 110 | else: 111 | return '\tsub %s,%s,%s'%(GetRegFromRecord(line[0]), GetRegFromRecord(line[2]), GetRegFromRecord( 112 | line[-1])) 113 | elif line[3]=='*': 114 | return '\tmul %s,%s,%s'%(GetRegFromRecord(line[0]), GetRegFromRecord(line[2]), GetRegFromRecord( 115 | line[-1])) 116 | elif line[3]=='/': 117 | return '\tdiv %s,%s\n\tmflo %s'%(GetRegFromRecord(line[2]), GetRegFromRecord(line[-1]), GetRegFromRecord( 118 | line[0])) 119 | elif line[3]=='<': 120 | return '\tslt %s,%s,%s'%(GetRegFromRecord(line[0]), GetRegFromRecord(line[2]), GetRegFromRecord( 121 | line[-1])) 122 | elif line[3]=='>': 123 | return '\tslt %s,%s,%s'%(GetRegFromRecord(line[0]), GetRegFromRecord(line[-1]), GetRegFromRecord( 124 | line[2])) 125 | elif line[3]=='==': 126 | return '\tsub %s,%s,%s'%(GetRegFromRecord(line[0]), GetRegFromRecord(line[-1]), GetRegFromRecord( 127 | line[2])) 128 | 129 | if line[2]=='CALL': 130 | if line[3]=='read' or line[3]=='print': 131 | return '\taddi $sp,$sp,-4\n\tsw $ra,0($sp)\n\tjal %s\n\tlw $ra,0($sp)\n\tmove %s,$v0\n\taddi $sp,$sp,4'%(line[-1], GetRegFromRecord( 132 | line[0])) 133 | else: 134 | return '\taddi $sp,$sp,-24\n\tsw $t0,0($sp)\n\tsw $ra,4($sp)\n\tsw $t1,8($sp)\n\tsw $t2,12($sp)\n\tsw $t3,16($sp)\n\tsw $t4,20($sp)\n\tjal %s\n\tlw $a0,0($sp)\n\tlw $ra,4($sp)\n\tlw $t1,8($sp)\n\tlw $t2,12($sp)\n\tlw $t3,16($sp)\n\tlw $t4,20($sp)\n\taddi $sp,$sp,24\n\tmove %s $v0'%(line[-1], GetRegFromRecord( 135 | line[0])) 136 | if line[0]=='GOTO': 137 | return '\tj %s'%line[1] 138 | if line[0]=='RETURN': 139 | return '\tmove $v0,%s\n\tjr $ra' % GetRegFromRecord(line[1]) 140 | if line[0]=='IF': 141 | if line[2]=='!=': 142 | return '\tbne %s,%s,%s'%(GetRegFromRecord(line[1]), "$zero", line[-1]) 143 | if line[2] == '==': 144 | return '\tbeq %s,%s,%s' % (GetRegFromRecord(line[1]), "$zero", line[-1]) 145 | if line[0]=='FUNCTION': 146 | return '%s:'%line[1] 147 | if line[0]=='CALL': 148 | if line[-1]=='read' or line[-1]=='print': 149 | return '\taddi $sp,$sp,-4\n\tsw $ra,0($sp)\n\tjal %s\n\tlw $ra,0($sp)\n\taddi $sp,$sp,4'%(line[-1]) 150 | else: 151 | return '\taddi $sp,$sp,-24\n\tsw $t0,0($sp)\n\tsw $ra,4($sp)\n\tsw $t1,8($sp)\n\tsw $t2,12($sp)\n\tsw $t3,16($sp)\n\tsw $t4,20($sp)\n\tjal %s\n\tlw $a0,0($sp)\n\tlw $ra,4($sp)\n\tlw $t1,8($sp)\n\tlw $t2,12($sp)\n\tlw $t3,16($sp)\n\tlw $t4,20($sp)\n\taddi $sp,$sp,24\n\tmove %s $v0'%(line[-1], GetRegFromRecord( 152 | line[0])) 153 | if line[0]=='ARG': 154 | return '\tmove $a0,%s' % GetRegFromRecord(line[-1]) 155 | if line[0]=='PARAM': 156 | return '\tmove %s,$a0'% GetRegFromRecord(line[1]) 157 | return '' 158 | 159 | 160 | 161 | 162 | 163 | def write_to_txt(Obj): 164 | f=open('./MIPS/objectcode.asm','w') 165 | template=''' 166 | .data 167 | _hint: .asciiz "Input:" 168 | _ret: .asciiz "\\n" 169 | .globl main 170 | .text 171 | read: 172 | li $v0,4 173 | la $a0,_hint 174 | syscall 175 | li $v0,5 176 | syscall 177 | jr $ra 178 | print: 179 | li $v0,1 180 | syscall 181 | li $v0,4 182 | la $a0,_ret 183 | syscall 184 | move $v0,$0 185 | jr $ra 186 | ''' 187 | f.write(template) 188 | for line in Obj: 189 | f.write(line+'\n') 190 | f.close() 191 | 192 | 193 | def init_reg(): 194 | global table,reg_ok,spillBook,spill_record,specialrecord 195 | specialrecord = {} 196 | spill_record = [] 197 | spillBook = {} 198 | table = {} 199 | reg_ok = {} 200 | for reg in regs: 201 | reg_ok[reg] = 1 # 初始化,所有寄存器都可用 202 | 203 | 204 | def findTime(reglist, regname): 205 | time = 0 206 | for i in range(len(reglist)): 207 | reg = reglist[i] 208 | if reg == regname: 209 | time += 1 210 | return time 211 | 212 | 213 | def findMinUse(record): 214 | min = 100000 215 | variname = "" 216 | for i in record: 217 | if record[i][1] <= min: 218 | min = record[i][1] 219 | variname = i 220 | return variname 221 | 222 | 223 | def parser(): 224 | Inter=Load_Inter('./MIPS/intercode.txt') #读取中间代码 225 | Load_Var(Inter) #第一遍扫描,记录所有变量 226 | 227 | 228 | 229 | 230 | for block in blocks: 231 | init_reg() 232 | reguse = [] 233 | for line in block: 234 | pattern = re.compile(r'Temp\d+|var\d+') 235 | list = re.findall(pattern, line) 236 | reguse += list 237 | regbook = {} 238 | for i in range(len(reguse)): 239 | thisreg = reguse[i] 240 | if thisreg not in regbook: 241 | time = findTime(reguse, thisreg) 242 | regbook[thisreg] = [thisreg, time] 243 | global GlobalRecord 244 | GlobalRecord = regbook 245 | 246 | 247 | while len(regbook) > len(regs): 248 | minreg = findMinUse(regbook) 249 | spillBook[minreg] = len(spillBook)*4 250 | regbook.pop(minreg) 251 | 252 | for reg in regbook: 253 | regbook[reg] = [get_R(reg), regbook[reg][1]] 254 | 255 | # print("RegUse", reguse) 256 | # print("RegBook", regbook) 257 | # print("RegSpill", spillBook) 258 | 259 | for line in block: 260 | linelist = line.split(" ") 261 | s = translate(linelist) # 翻译该句 262 | 263 | if len(s) > 0: # 长度大于0 , 打印, 避免空行 264 | Obj.append(s) 265 | 266 | if len(linelist) == 3 and linelist[2] == ":" and "label" not in line: # callee save , store regs to be used in this block 267 | count = len(regbook) + len(spillBook) 268 | print("\taddi $sp,$sp," + str(-count * 4)) 269 | Obj.append("\taddi $sp,$sp," + str(-count * 4)) 270 | 271 | count = len(spillBook) 272 | 273 | for i in regbook: 274 | print("\tsw %s,%d($sp)"%(regbook[i][0],count*4)) 275 | Obj.append("\tsw %s,%d($sp)"%(regbook[i][0],count*4)) 276 | count += 1 277 | # 块结束后恢复寄存器 278 | 279 | count = len(spillBook) 280 | 281 | for i in regbook: 282 | print("\tlw %s,%d($sp)" % (regbook[i][0], count * 4)) 283 | Obj.append("\tlw %s,%d($sp)" % (regbook[i][0], count * 4)) 284 | count += 1 285 | print("\taddi $sp,$sp," + str(count * 4)) 286 | Obj.append("\taddi $sp,$sp," + str(count * 4)) 287 | 288 | write_to_txt(Obj) 289 | 290 | parser() 291 | -------------------------------------------------------------------------------- /Ccompi1er/MIPS/intercode.txt: -------------------------------------------------------------------------------- 1 | void main(){ 2 | int i; 3 | int a = read(); 4 | for(i=0; i ./MIPS/intercode.txt 7 | echo "--------------AST代码----------------" 8 | cat ./MIPS/intercode.txt 9 | python ./MIPS/MIPS.py >> 2 10 | echo "" 11 | echo "--------------目标代码----------------" 12 | cat ./MIPS/objectcode.asm 13 | python ./FinalProcess.py 14 | echo "" 15 | echo "---------------错误报告-----------------" 16 | cat ./ErrorLog.txt 17 | -------------------------------------------------------------------------------- /Ccompi1er/README.md: -------------------------------------------------------------------------------- 1 | # Ccompiler 2 | 3 | ### 已实现(可实现中间代码输出) 4 | 5 | ``` 6 | inline float test() 7 | { 8 | int a; 9 | int b; 10 | float cc = a = b == 1+5*b,dd = cc * 2; 11 | } 12 | void main(int x,int y) 13 | { 14 | int b=20; 15 | } 16 | ``` 17 | ### 另,已实现 if while for 18 | --- 19 | 20 | 编译命令 21 | 22 | `bison -d -o compiler.cpp compiler.y` 23 | 24 | `flex -o mylex.cpp compiler.l` 25 | 26 | `g++ -std=c++11 -o compiler compiler.cpp mylex.cpp main.cpp` 27 | -------------------------------------------------------------------------------- /Ccompi1er/RGenerator.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "node.h" 3 | #include 4 | #include 5 | #include "ErrorLog.cpp" 6 | using namespace std; 7 | 8 | char* itoa(int i){ 9 | static char str[20]; 10 | sprintf(str,"%d",i); 11 | return str; 12 | } 13 | 14 | using namespace std; 15 | typedef struct { 16 | bool state; 17 | string name; 18 | string type; 19 | } VAR; 20 | class Data{ 21 | private: 22 | 23 | bool *temps;//false no use 24 | int num; 25 | VAR *vars; 26 | VAR *ARG; 27 | public: 28 | void operator=(const Data& d){ 29 | num=d.num; 30 | temps = new bool [num]; 31 | vars = new VAR [num]; 32 | ARG = new VAR [num]; 33 | for(int i=0;inum=num; 51 | temps = new bool [num]; 52 | vars = new VAR [num]; 53 | for(int i=0;i=0;i--)//find the recent one 93 | { 94 | if(vars[i].state==true) 95 | { 96 | if(vars[i].name==name) 97 | return i; 98 | } 99 | } 100 | return -1; 101 | } 102 | void releaseVar(int i){ 103 | vars[i].state=false; 104 | } 105 | 106 | }; 107 | 108 | struct para{ 109 | string paratype; 110 | string paraname; 111 | }; 112 | 113 | 114 | struct funcrecord{ 115 | string functype; 116 | string funcname; 117 | vector funcpara; 118 | int getParaNum(){ 119 | return funcpara.size(); 120 | } 121 | }; 122 | 123 | 124 | class Function{ 125 | public: 126 | vector Record; 127 | int size = 0; 128 | void addfunc(struct funcrecord record){ 129 | Record.push_back(record); 130 | size++; 131 | } 132 | 133 | void printAllFunc(){ 134 | cout << endl << "--------------函数表----------------" << endl; 135 | for(int i=0;iroot = root; 172 | labels = new bool[MAX_LABELS]; 173 | for(int i=0;iroot,r); 178 | cout << endl << endl << endl; 179 | FunctionRecord.printAllFunc(); 180 | Log.printErrorLog(); 181 | } 182 | 183 | ~RGenerator(){ 184 | delete[] labels; 185 | } 186 | 187 | int getLabel(){ 188 | for(int i=0;itype.compare("function_definition")==0){ 214 | cout << "FUNCTION " << t->contents[1]->content << " :" << endl; 215 | struct funcrecord f; 216 | f.functype = t->contents[0]->content; 217 | f.funcname = t->contents[1]->content; 218 | if(t->sub.size()>1){ 219 | node* psub = t->sub[0]; 220 | while(psub){ 221 | struct para p; 222 | p.paratype = psub->contents[0]->content; 223 | p.paraname = psub->contents[1]->content; 224 | //cout << "-----" << p.paratype << "----" << p.paraname << endl; 225 | f.funcpara.push_back(p); 226 | if(psub->next){ 227 | psub = psub->next; 228 | } 229 | else{ 230 | break; 231 | } 232 | } 233 | } 234 | FunctionRecord.addfunc(f); 235 | loop(t,r); 236 | } 237 | 238 | else if(t->type.compare("parameter_declaration")==0){ 239 | // cout << "PARAM " << t->contents[0]->content << endl; 240 | 241 | r.setVar(t->contents[1]->content,t->contents[0]->content); 242 | cout << "PARAM var" << r.getVar(t->contents[1]->content) << endl; 243 | loop(t,r); 244 | } 245 | else if (t->type.compare("declaration")==0){ 246 | string ttype = t->sub[0]->contents[0]->content; 247 | for(int i=0;isub[1]->sub.size();i++){ 248 | node* tt = t->sub[1]->sub[i]; 249 | //cout<<"debug----"<contents[0]->content<contents[0]->content,ttype); 251 | loop(tt,r); 252 | } 253 | } 254 | else if (t->type.find("expression")!=-1&&t->type.compare("conditional_expression2")!=0){ 255 | node* tt=t->sub[0]; 256 | string r1,r2,r3,l; 257 | if(tt->sub.size()==0){ 258 | if(tt->contents[0]->name.compare("IDENTIFIER")==0) 259 | r1 = string("var").append(itoa(r.getVar(tt->contents[0]->content))); 260 | else if(tt->contents[0]->name.compare("CONSTANT")==0){ 261 | int i = r.getTemp(); 262 | cout<<"Temp"<contents[0]->content<sub[2]; 271 | if(tt->sub.size()==0){ 272 | if(tt->contents[0]->name.compare("IDENTIFIER")==0) 273 | r3 = string("var").append(itoa(r.getVar(tt->contents[0]->content))); 274 | else if(tt->contents[0]->name.compare("CONSTANT")==0){ 275 | int i = r.getTemp(); 276 | cout<<"Temp"<contents[0]->content<type == "function_call"){ 282 | func_call_visual = false; 283 | stratTranslate(tt,r); 284 | int i = r.getTemp(); 285 | cout << "Temp" << i << " = CALL " << tt->sub[0]->contents[0]->content << endl; 286 | r3 = string("Temp") + to_string(i); 287 | r.releaseTemp(i); 288 | } 289 | else{ 290 | r3 = stratTranslate(tt,new Data(r)); 291 | } 292 | // 293 | } 294 | 295 | tt = t->sub[1]; 296 | r2 = tt->contents[0]->content; 297 | if(tt->contents[0]->name.compare("assignment_operator")==0){ 298 | cout<type == "if_statement"){ 310 | string resReg = stratTranslate(t->sub[0],r); 311 | int label_true = getLabel(); 312 | int label_false = getLabel(); 313 | cout << "IF " << resReg << " == 0 GOTO label_" << label_true << endl; 314 | cout << "GOTO label_" << label_false << endl; 315 | cout << "LABEL label_" << label_true<<" :" << endl; 316 | stratTranslate(t->sub[1],r); 317 | cout << "LABEL label_" << label_false <<" :" << endl; 318 | } 319 | 320 | 321 | else if(t->type == "if_else_statement"){ 322 | int label_true = getLabel(); 323 | int label_false = getLabel(); 324 | int label_next = getLabel(); 325 | string resReg = stratTranslate(t->sub[0],r); 326 | cout << "IF " << resReg << " != 0 GOTO label_" << label_true << endl; 327 | cout << "GOTO label_" << label_false << endl; 328 | cout << "LABEL label_" << label_true<<" :" << endl; 329 | stratTranslate(t->sub[1],r); 330 | cout << "GOTO label_" << label_next << endl; 331 | cout << "LABEL label_" << label_false <<" :" << endl; 332 | stratTranslate(t->sub[2],r); 333 | cout << "LABEL label_" << label_next <<" :" << endl; 334 | } 335 | 336 | else if(t->type == "break"){ 337 | cout << "GOTO label_" << this->endlabel << endl; 338 | } 339 | 340 | else if(t->type == "continue"){ 341 | cout << "GOTO label_" << this->startlabel << endl; 342 | } 343 | 344 | else if(t->type == "while_statement"){ 345 | int label_while = getLabel(); 346 | int label_start = getLabel(); 347 | int label_end = getLabel(); 348 | isloop = true; 349 | startlabel = label_while; 350 | endlabel = label_end; 351 | 352 | cout << "LABEL label_" << label_while <<" :" << endl; 353 | string resReg = stratTranslate(t->sub[0],r); 354 | cout << "IF " << resReg << " != 0 GOTO label_" << label_start << endl; 355 | cout << "GOTO label_" << label_end << endl; 356 | cout << "LABEL label_" << label_start <<" :" << endl; 357 | stratTranslate(t->sub[1],r); 358 | cout << "GOTO label_" << label_while << endl; 359 | cout << "LABEL label_" << label_end <<" :" << endl; 360 | } 361 | 362 | else if(t->type == "do_while_statement"){ 363 | int beginlabel = getLabel(); 364 | startlabel = getLabel(); 365 | endlabel = getLabel(); 366 | cout << "LABEL label_" << beginlabel <<" :" << endl; 367 | stratTranslate(t->sub[0],r); 368 | cout << "LABEL label_" << startlabel <<" :" << endl; 369 | string resReg = stratTranslate(t->sub[1],r); 370 | cout << "IF " << resReg << " != 0 GOTO label_" << beginlabel << endl; 371 | cout << "LABEL label_" << endlabel <<" :" << endl; 372 | 373 | } 374 | 375 | else if(t->type == "for_statement_exp3"){ 376 | int label_judge = getLabel(); 377 | int label_start = getLabel(); 378 | 379 | 380 | startlabel = getLabel(); 381 | endlabel = getLabel(); 382 | 383 | stratTranslate(t->sub[0],r); 384 | cout << "LABEL label_" << label_judge <<" :" << endl; 385 | string resReg = stratTranslate(t->sub[1],r); 386 | cout << "IF " << resReg << " != 0 GOTO label_" << label_start << endl; 387 | cout << "GOTO label_" << endlabel << endl; 388 | cout << "LABEL label_" << label_start <<" :" << endl; 389 | stratTranslate(t->sub[3],r); 390 | cout << "LABEL label_" << startlabel <<" :" << endl; 391 | stratTranslate(t->sub[2],r); 392 | cout << "GOTO label_" << label_judge << endl; 393 | cout << "LABEL label_" << endlabel <<" :" << endl; 394 | } 395 | 396 | else if(t->type == "function_call"){ 397 | string res; 398 | string funcname = t->sub[0]->contents[0]->content; 399 | if (FunctionRecord.funcExist(funcname)== false){ 400 | string hint = "No function named with "; 401 | hint += funcname; 402 | Log.addLog(hint,t->sub[0]->contents[0]->lineNum); 403 | } 404 | // have parameter 405 | if(t->sub.size()==2){ 406 | node* s = t->sub[1]; 407 | vector ARG; 408 | vector TEMP; 409 | while(s!=nullptr){ 410 | if(s->type == "primary_expression"){ 411 | if(s->contents[0]->name == "CONSTANT"){ 412 | int i = r.getTemp(); 413 | cout << "Temp" << i << " = #" << s->contents[0]->content <contents[0]->name == "IDENTIFIER"){ 421 | string varname = s->contents[0]->content; 422 | //cout << "ARG" << " Var" << r.getVar(s->contents[0]->content) << endl; 423 | string argname = "var"; 424 | argname += to_string(r.getVar(s->contents[0]->content)); 425 | ARG.push_back(argname); 426 | } 427 | } 428 | else if(s->type == "function_call"){ 429 | stratTranslate(s,r); 430 | int i = r.getTemp(); 431 | res = "Temp"; 432 | res += to_string(i); 433 | cout << res << " = " << "CALL " << s->sub[0]->contents[0]->content << endl; 434 | func_call_visual = false; 435 | cout << "ARG " << res << endl; 436 | ARG.push_back(res); 437 | r.releaseTemp(i); 438 | } 439 | else{ 440 | string res = stratTranslate(s,r); 441 | ARG.push_back(res); 442 | } 443 | 444 | s = s->next; 445 | } 446 | for(int j=ARG.size()-1;j>=0;j--){ 447 | cout << "ARG" << " " << ARG[j] << endl; 448 | } 449 | 450 | 451 | } 452 | if(func_call_visual == true) 453 | cout << "CALL " << t->sub[0]->contents[0]->content << endl; 454 | else{ 455 | func_call_visual = true; 456 | } 457 | } 458 | 459 | else if(t->type == "return_statement"){ 460 | if(t->sub.size()==0){ 461 | cout << "RETURN" << endl; 462 | } 463 | else{ 464 | node* s = t->sub[0]; 465 | string res; 466 | if(s->type == "primary_expression"){ 467 | if(s->contents[0]->name == "CONSTANT"){ 468 | int i = r.getTemp(); 469 | cout << "Temp" << i << " = #" << s->contents[0]->content << endl; 470 | res = "Temp"; 471 | res = res + to_string(i); 472 | } 473 | if(s->contents[0]->name == "IDENTIFIER"){ 474 | res = "var"; 475 | res += to_string(r.getVar(s->contents[0]->content)); 476 | } 477 | } 478 | else{ 479 | res = stratTranslate(s,r); 480 | } 481 | cout << "RETURN " << res << endl; 482 | } 483 | } 484 | t = t->next; 485 | } 486 | return value; 487 | } 488 | 489 | void loop(node* t,Data* r){ 490 | for (int i = 0; i < t->sub.size(); i++){ 491 | stratTranslate(t->sub[i],r); 492 | } 493 | } 494 | 495 | void loop(node* t,Data r){ 496 | for (int i = 0; i < t->sub.size(); i++){ 497 | stratTranslate(t->sub[i],r); 498 | } 499 | } 500 | 501 | 502 | }; 503 | 504 | -------------------------------------------------------------------------------- /Ccompi1er/compiler: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whatlulumomo/MiniCompiler/7b0d4c8328e1771e6239bea91f46b0f1e5f9184d/Ccompi1er/compiler -------------------------------------------------------------------------------- /Ccompi1er/compiler.hpp: -------------------------------------------------------------------------------- 1 | /* A Bison parser, made by GNU Bison 2.3. */ 2 | 3 | /* Skeleton interface for Bison's Yacc-like parsers in C 4 | 5 | Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 6 | Free Software Foundation, Inc. 7 | 8 | This program is free software; you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation; either version 2, or (at your option) 11 | any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software 20 | Foundation, Inc., 51 Franklin Street, Fifth Floor, 21 | Boston, MA 02110-1301, USA. */ 22 | 23 | /* As a special exception, you may create a larger work that contains 24 | part or all of the Bison parser skeleton and distribute that work 25 | under terms of your choice, so long as that work isn't itself a 26 | parser generator using the skeleton or a modified version thereof 27 | as a parser skeleton. Alternatively, if you modify or redistribute 28 | the parser skeleton itself, you may (at your option) remove this 29 | special exception, which will cause the skeleton and the resulting 30 | Bison output files to be licensed under the GNU General Public 31 | License without this special exception. 32 | 33 | This special exception was added by the Free Software Foundation in 34 | version 2.2 of Bison. */ 35 | 36 | /* Tokens. */ 37 | #ifndef YYTOKENTYPE 38 | # define YYTOKENTYPE 39 | /* Put the tokens into the symbol table, so that GDB and other debuggers 40 | know about them. */ 41 | enum yytokentype { 42 | IDENTIFIER = 258, 43 | CONSTANT = 259, 44 | STRING_LITERAL = 260, 45 | SIZEOF = 261, 46 | PTR_OP = 262, 47 | INC_OP = 263, 48 | DEC_OP = 264, 49 | LEFT_OP = 265, 50 | RIGHT_OP = 266, 51 | LE_OP = 267, 52 | GE_OP = 268, 53 | EQ_OP = 269, 54 | NE_OP = 270, 55 | AND_OP = 271, 56 | OR_OP = 272, 57 | MUL_ASSIGN = 273, 58 | DIV_ASSIGN = 274, 59 | MOD_ASSIGN = 275, 60 | ADD_ASSIGN = 276, 61 | SUB_ASSIGN = 277, 62 | LEFT_ASSIGN = 278, 63 | RIGHT_ASSIGN = 279, 64 | AND_ASSIGN = 280, 65 | XOR_ASSIGN = 281, 66 | OR_ASSIGN = 282, 67 | TYPE_NAME = 283, 68 | TYPEDEF = 284, 69 | EXTERN = 285, 70 | STATIC = 286, 71 | AUTO = 287, 72 | REGISTER = 288, 73 | INLINE = 289, 74 | RESTRICT = 290, 75 | CHAR = 291, 76 | SHORT = 292, 77 | INT = 293, 78 | LONG = 294, 79 | SIGNED = 295, 80 | UNSIGNED = 296, 81 | FLOAT = 297, 82 | DOUBLE = 298, 83 | CONST = 299, 84 | VOLATILE = 300, 85 | VOID = 301, 86 | BOOL = 302, 87 | COMPLEX = 303, 88 | IMAGINARY = 304, 89 | STRUCT = 305, 90 | UNION = 306, 91 | ENUM = 307, 92 | ELLIPSIS = 308, 93 | CASE = 309, 94 | DEFAULT = 310, 95 | IF = 311, 96 | ELSE = 312, 97 | SWITCH = 313, 98 | WHILE = 314, 99 | DO = 315, 100 | FOR = 316, 101 | GOTO = 317, 102 | CONTINUE = 318, 103 | BREAK = 319, 104 | RETURN = 320 105 | }; 106 | #endif 107 | /* Tokens. */ 108 | #define IDENTIFIER 258 109 | #define CONSTANT 259 110 | #define STRING_LITERAL 260 111 | #define SIZEOF 261 112 | #define PTR_OP 262 113 | #define INC_OP 263 114 | #define DEC_OP 264 115 | #define LEFT_OP 265 116 | #define RIGHT_OP 266 117 | #define LE_OP 267 118 | #define GE_OP 268 119 | #define EQ_OP 269 120 | #define NE_OP 270 121 | #define AND_OP 271 122 | #define OR_OP 272 123 | #define MUL_ASSIGN 273 124 | #define DIV_ASSIGN 274 125 | #define MOD_ASSIGN 275 126 | #define ADD_ASSIGN 276 127 | #define SUB_ASSIGN 277 128 | #define LEFT_ASSIGN 278 129 | #define RIGHT_ASSIGN 279 130 | #define AND_ASSIGN 280 131 | #define XOR_ASSIGN 281 132 | #define OR_ASSIGN 282 133 | #define TYPE_NAME 283 134 | #define TYPEDEF 284 135 | #define EXTERN 285 136 | #define STATIC 286 137 | #define AUTO 287 138 | #define REGISTER 288 139 | #define INLINE 289 140 | #define RESTRICT 290 141 | #define CHAR 291 142 | #define SHORT 292 143 | #define INT 293 144 | #define LONG 294 145 | #define SIGNED 295 146 | #define UNSIGNED 296 147 | #define FLOAT 297 148 | #define DOUBLE 298 149 | #define CONST 299 150 | #define VOLATILE 300 151 | #define VOID 301 152 | #define BOOL 302 153 | #define COMPLEX 303 154 | #define IMAGINARY 304 155 | #define STRUCT 305 156 | #define UNION 306 157 | #define ENUM 307 158 | #define ELLIPSIS 308 159 | #define CASE 309 160 | #define DEFAULT 310 161 | #define IF 311 162 | #define ELSE 312 163 | #define SWITCH 313 164 | #define WHILE 314 165 | #define DO 315 166 | #define FOR 316 167 | #define GOTO 317 168 | #define CONTINUE 318 169 | #define BREAK 319 170 | #define RETURN 320 171 | 172 | 173 | 174 | 175 | #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED 176 | typedef union YYSTYPE 177 | #line 15 "compiler.y" 178 | { 179 | class node* Node; 180 | class element* Element; 181 | } 182 | /* Line 1529 of yacc.c. */ 183 | #line 184 "compiler.hpp" 184 | YYSTYPE; 185 | # define yystype YYSTYPE /* obsolescent; will be withdrawn */ 186 | # define YYSTYPE_IS_DECLARED 1 187 | # define YYSTYPE_IS_TRIVIAL 1 188 | #endif 189 | 190 | extern YYSTYPE yylval; 191 | 192 | -------------------------------------------------------------------------------- /Ccompi1er/compiler.l: -------------------------------------------------------------------------------- 1 | %option yylineno 2 | D [0-9] 3 | L [a-zA-Z_] 4 | H [a-fA-F0-9] 5 | E ([Ee][+-]?{D}+) 6 | P ([Pp][+-]?{D}+) 7 | FS (f|F|l|L) 8 | IS ((u|U)|(u|U)?(l|L|ll|LL)|(l|L|ll|LL)(u|U)) 9 | 10 | %{ 11 | #include 12 | #include "compiler.hpp" 13 | #include "element.h" 14 | void count(void); 15 | void comment(); 16 | int check_type(); 17 | void yyerror(char const *s); 18 | %} 19 | 20 | %% 21 | "/*" { comment(); } 22 | "//"[^\n]* { /* consume //-comment */ } 23 | 24 | 25 | "auto" { count(); yylval.Element = new element(yylineno,"storage_class_specifier","auto");return(AUTO); } 26 | "_Bool" { count(); yylval.Element = new element(yylineno,"type_specifier","_Bool");return(BOOL); } 27 | "break" { count(); yylval.Element = new element(yylineno,"reserved_keywords","break");return(BREAK); } 28 | "case" { count(); return(CASE); } 29 | "char" { count(); yylval.Element = new element(yylineno,"type_specifier","char"); return(CHAR); } 30 | "_Complex" { count(); /*I abandon this. @txt*/return(COMPLEX); } 31 | "const" { count(); yylval.Element = new element(yylineno,"type_qualifier","const");return(CONST); } 32 | "continue" { count(); yylval.Element = new element(yylineno,"reserved_keywords","continue");return(CONTINUE); } 33 | "default" { count(); return(DEFAULT); } 34 | "do" { count(); yylval.Element = new element(yylineno, "iteration_specifier", "do"); return(DO); } 35 | "double" { count(); yylval.Element = new element(yylineno,"type_specifier","double"); return(DOUBLE); } 36 | "else" { count(); yylval.Element = new element(yylineno, "selection_specifier", "else"); return(ELSE); } 37 | "enum" { count(); return(ENUM); } 38 | "extern" { count(); yylval.Element = new element(yylineno,"storage_class_specifier","extern");return(EXTERN); } 39 | "float" { count(); yylval.Element = new element(yylineno,"type_specifier","float"); return(FLOAT); } 40 | "for" { count(); yylval.Element = new element(yylineno, "iteration_specifier", "for"); return(FOR); } 41 | "goto" { count(); return(GOTO); } 42 | "if" { count(); yylval.Element = new element(yylineno, "selection_specifier", "if"); return(IF); } 43 | "_Imaginary" { count(); /*I abandon this. @txt*/return(IMAGINARY); } 44 | "inline" { count(); yylval.Element = new element(yylineno,"function_specifier","inline");return(INLINE); } 45 | "int" { count(); yylval.Element = new element(yylineno,"type_specifier","int"); return(INT); } 46 | "long" { count(); yylval.Element = new element(yylineno,"type_specifier","long"); return(LONG); } 47 | "register" { count(); yylval.Element = new element(yylineno,"storage_class_specifier","register");return(REGISTER); } 48 | "restrict" { count(); yylval.Element = new element(yylineno,"type_qualifier","restrict");return(RESTRICT); } 49 | "return" { count(); yylval.Element = new element(yylineno,"reserved_keywords","return");return(RETURN); } 50 | "short" { count(); yylval.Element = new element(yylineno,"type_specifier","short"); return(SHORT); } 51 | "signed" { count(); yylval.Element = new element(yylineno,"type_specifier","signed");return(SIGNED); } 52 | "sizeof" { count(); return(SIZEOF); } 53 | "static" { count(); yylval.Element = new element(yylineno,"storage_class_specifier","static");return(STATIC); } 54 | "struct" { count(); return(STRUCT); } 55 | "switch" { count(); yylval.Element = new element(yylineno, "selection_specifier", "swtich"); return(SWITCH); } 56 | "typedef" { count(); yylval.Element = new element(yylineno,"storage_class_specifier","typedef");return(TYPEDEF); } 57 | "union" { count(); return(UNION); } 58 | "unsigned" { count(); yylval.Element = new element(yylineno,"type_specifier","unsigned");return(UNSIGNED); } 59 | "void" { count(); yylval.Element = new element(yylineno,"type_specifier","void"); return(VOID); } 60 | "volatile" { count(); yylval.Element = new element(yylineno,"type_qualifier","volatile");return(VOLATILE); } 61 | "while" { count(); yylval.Element = new element(yylineno, "iteration_specifier", "while"); return(WHILE); } 62 | 63 | {L}({L}|{D})* { count();yylval.Element = new element(yylineno,"IDENTIFIER",yytext); return(check_type()); } 64 | 65 | 0[xX]{H}+{IS}? { count(); yylval.Element = new element(yylineno,"CONSTANT",yytext);return(CONSTANT); } 66 | 0[0-7]*{IS}? { count(); yylval.Element = new element(yylineno,"CONSTANT",yytext);return(CONSTANT); } 67 | [1-9]{D}*{IS}? { count(); yylval.Element = new element(yylineno,"CONSTANT",yytext);return(CONSTANT); } 68 | L?'(\\.|[^\\'\n])+' { count(); yylval.Element = new element(yylineno,"CONSTANT",yytext);return(CONSTANT); } 69 | 70 | {D}+{E}{FS}? { count(); yylval.Element = new element(yylineno,"CONSTANT",yytext);return(CONSTANT); } 71 | {D}*"."{D}+{E}?{FS}? { count(); yylval.Element = new element(yylineno,"CONSTANT",yytext);return(CONSTANT); } 72 | {D}+"."{D}*{E}?{FS}? { count(); yylval.Element = new element(yylineno,"CONSTANT",yytext);return(CONSTANT); } 73 | 0[xX]{H}+{P}{FS}? { count(); yylval.Element = new element(yylineno,"CONSTANT",yytext);return(CONSTANT); } 74 | 0[xX]{H}*"."{H}+{P}{FS}? { count(); yylval.Element = new element(yylineno,"CONSTANT",yytext);return(CONSTANT); } 75 | 0[xX]{H}+"."{H}*{P}{FS}? { count(); yylval.Element = new element(yylineno,"CONSTANT",yytext);return(CONSTANT); } 76 | 77 | 78 | L?\"(\\.|[^\\"\n])*\" { count(); yylval.Element = new element(yylineno,"STRING_LITERAL",yytext);return(STRING_LITERAL); } 79 | 80 | "..." { count(); yylval.Element = new element(yylineno,"ELLIPSIS",yytext);return(ELLIPSIS); } 81 | ">>=" { count(); yylval.Element = new element(yylineno,"assignment_operator",yytext);return(RIGHT_ASSIGN); } 82 | "<<=" { count(); yylval.Element = new element(yylineno,"assignment_operator",yytext);return(LEFT_ASSIGN); } 83 | "+=" { count(); yylval.Element = new element(yylineno,"assignment_operator",yytext);return(ADD_ASSIGN); } 84 | "-=" { count(); yylval.Element = new element(yylineno,"assignment_operator",yytext);return(SUB_ASSIGN); } 85 | "*=" { count(); yylval.Element = new element(yylineno,"assignment_operator",yytext);return(MUL_ASSIGN); } 86 | "/=" { count(); yylval.Element = new element(yylineno,"assignment_operator",yytext);return(DIV_ASSIGN); } 87 | "%=" { count(); yylval.Element = new element(yylineno,"assignment_operator",yytext);return(MOD_ASSIGN); } 88 | "&=" { count(); yylval.Element = new element(yylineno,"assignment_operator",yytext);return(AND_ASSIGN); } 89 | "^=" { count(); yylval.Element = new element(yylineno,"assignment_operator",yytext);return(XOR_ASSIGN); } 90 | "|=" { count(); yylval.Element = new element(yylineno,"assignment_operator",yytext);return(OR_ASSIGN); } 91 | ">>" { count(); yylval.Element = new element(yylineno,"RIGHT_OP",yytext);return(RIGHT_OP); } 92 | "<<" { count(); yylval.Element = new element(yylineno,"LEFT_OP",yytext);return(LEFT_OP); } 93 | "++" { count(); yylval.Element = new element(yylineno,"INC_OP",yytext);return(INC_OP); } 94 | "--" { count(); yylval.Element = new element(yylineno,"DEC_OP",yytext);return(DEC_OP); } 95 | "->" { count(); yylval.Element = new element(yylineno,"PTR_OP",yytext);return(PTR_OP); } 96 | "&&" { count(); yylval.Element = new element(yylineno,"AND_OP",yytext);return(AND_OP); } 97 | "||" { count(); yylval.Element = new element(yylineno,"OR_OP",yytext);return(OR_OP); } 98 | "<=" { count(); yylval.Element = new element(yylineno,"LE_OP",yytext);return(LE_OP); } 99 | ">=" { count(); yylval.Element = new element(yylineno,"GE_OP",yytext);return(GE_OP); } 100 | "==" { count(); yylval.Element = new element(yylineno,"EQ_OP",yytext);return(EQ_OP); } 101 | "!=" { count(); yylval.Element = new element(yylineno,"NE_OP",yytext);return(NE_OP); } 102 | ";" { count(); return(';'); } 103 | ("{"|"<%") { count(); return('{'); } 104 | ("}"|"%>") { count(); return('}'); } 105 | "," { count(); return(','); } 106 | ":" { count(); return(':'); } 107 | "=" { count(); yylval.Element = new element(yylineno,"assignment_operator",yytext);return('='); } 108 | "(" { count(); return('('); } 109 | ")" { count(); return(')'); } 110 | ("["|"<:") { count(); return('['); } 111 | ("]"|":>") { count(); return(']'); } 112 | "." { count(); return('.'); } 113 | "&" { count(); yylval.Element = new element(yylineno,"unary_operator",yytext);return('&'); } 114 | "!" { count(); yylval.Element = new element(yylineno,"unary_operator",yytext);return('!'); } 115 | "~" { count(); yylval.Element = new element(yylineno,"unary_operator",yytext);return('~'); } 116 | "-" { count(); yylval.Element = new element(yylineno,"unary_operator",yytext);return('-'); } 117 | "+" { count(); yylval.Element = new element(yylineno,"unary_operator",yytext);return('+'); } 118 | "*" { count(); yylval.Element = new element(yylineno,"unary_operator",yytext);return('*'); } 119 | "/" { count(); yylval.Element = new element(yylineno,"unary_operator",yytext);return('/'); } 120 | "%" { count(); yylval.Element = new element(yylineno,"unary_operator",yytext);return('%'); } 121 | "<" { count(); yylval.Element = new element(yylineno,"unary_operator",yytext);return('<'); } 122 | ">" { count(); yylval.Element = new element(yylineno,"unary_operator",yytext);return('>'); } 123 | "^" { count(); yylval.Element = new element(yylineno,"unary_operator",yytext);return('^'); } 124 | "|" { count(); yylval.Element = new element(yylineno,"unary_operator",yytext);return('|'); } 125 | "?" { count(); yylval.Element = new element(yylineno,"unary_operator",yytext);return('?'); } 126 | 127 | [ \t\v\n\f] { count(); } 128 | . { /* Add code to complain about unmatched characters */ } 129 | 130 | %% 131 | 132 | int yywrap(void) 133 | { 134 | return 1; 135 | } 136 | 137 | 138 | void comment(void) 139 | { 140 | char c, prev = 0; 141 | 142 | while ((c = yyinput()) != 0) /* (EOF maps to 0) */ 143 | { 144 | if (c == '/' && prev == '*') 145 | return; 146 | prev = c; 147 | } 148 | yyerror("unterminated comment"); 149 | } 150 | 151 | 152 | int column = 0; 153 | 154 | void count(void) 155 | { 156 | int i; 157 | 158 | for (i = 0; yytext[i] != '\0'; i++) 159 | if (yytext[i] == '\n') 160 | column = 0; 161 | else if (yytext[i] == '\t') 162 | column += 8 - (column % 8); 163 | else 164 | column++; 165 | 166 | ECHO; 167 | } 168 | 169 | 170 | int check_type(void) 171 | { 172 | /* 173 | * pseudo code --- this is what it should check 174 | * 175 | * if (yytext == type_name) 176 | * return TYPE_NAME; 177 | * 178 | * return IDENTIFIER; 179 | */ 180 | 181 | /* 182 | * it actually will only return IDENTIFIER 183 | */ 184 | 185 | return IDENTIFIER; 186 | } 187 | -------------------------------------------------------------------------------- /Ccompi1er/compiler.y: -------------------------------------------------------------------------------- 1 | %{ 2 | #include"node.h" 3 | #include"element.h" 4 | #include 5 | #include 6 | extern char yytext[]; 7 | extern int column; 8 | extern FILE *yyin; 9 | void yyerror(char const *s); 10 | int yylex(); 11 | node* root = NULL; 12 | bool hasError = false; 13 | int errorNum = 0; 14 | %} 15 | %union{ 16 | class node* Node; 17 | class element* Element; 18 | } 19 | %token IDENTIFIER CONSTANT STRING_LITERAL SIZEOF 20 | %token PTR_OP INC_OP DEC_OP LEFT_OP RIGHT_OP LE_OP GE_OP EQ_OP NE_OP 21 | %token AND_OP OR_OP MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ADD_ASSIGN 22 | %token SUB_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN 23 | %token XOR_ASSIGN OR_ASSIGN TYPE_NAME 24 | 25 | %token TYPEDEF EXTERN STATIC AUTO REGISTER INLINE RESTRICT 26 | %token CHAR SHORT INT LONG SIGNED UNSIGNED FLOAT DOUBLE CONST VOLATILE VOID 27 | %token BOOL COMPLEX IMAGINARY 28 | %token STRUCT UNION ENUM ELLIPSIS 29 | %token '&' '*' '+' '-' '~' '!' '/' '<' '>' '^' '|' '%' '=' 30 | %token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN 31 | %type primary_expression postfix_expression argument_expression_list unary_expression unary_operator 32 | %type multiplicative_expression additive_expression shift_expression relational_expression equality_expression cast_expression 33 | %type and_expression exclusive_or_expression inclusive_or_expression logical_and_expression logical_or_expression 34 | %type assignment_expression assignment_operator expression conditional_expression constant_expression 35 | %type declaration init_declarator_list init_declarator type_specifier declaration_specifiers storage_class_specifier type_qualifier function_specifier 36 | %type declarator direct_declarator 37 | %type parameter_list parameter_declaration identifier_list parameter_type_list 38 | %type abstract_declarator initializer initializer_list designation designator_list 39 | %type designator statement labeled_statement compound_statement block_item_list block_item expression_statement 40 | %type selection_statement iteration_statement jump_statement translation_unit external_declaration function_definition 41 | %type declaration_list 42 | %type start 43 | %start start 44 | %% 45 | 46 | primary_expression 47 | : IDENTIFIER {$$=new node("primary_expression",NULL,1,$1);} 48 | | CONSTANT {$$=new node("primary_expression",NULL,1,$1);} 49 | | STRING_LITERAL {$$=new node("primary_expression",NULL,1,$1);} 50 | | '(' expression ')' {$$=$2;} 51 | ; 52 | 53 | postfix_expression 54 | : primary_expression {$$=$1;} 55 | | postfix_expression '[' expression ']' {node* t=$1;while(t->next)t=t->next;t->next=$3;} 56 | | postfix_expression '(' ')' {$$=new node("function_call",NULL,0);$$->addSub(1,$1);} 57 | | postfix_expression '(' argument_expression_list ')' {$$=new node("function_call",NULL,0);$$->addSub(2,$1,$3);} 58 | | postfix_expression '.' IDENTIFIER //abandoned 59 | | postfix_expression PTR_OP IDENTIFIER //abandoned 60 | | postfix_expression INC_OP //wait to be updated 61 | | postfix_expression DEC_OP //wait to be updated 62 | | '(' type_name ')' '{' initializer_list '}' //abandoned 63 | | '(' type_name ')' '{' initializer_list ',' '}' //abandoned 64 | ; 65 | 66 | argument_expression_list 67 | : assignment_expression {$$=$1;} 68 | | argument_expression_list ',' assignment_expression {node* t=$1;while(t->next)t=t->next;t->next=$3;} 69 | ; 70 | 71 | unary_expression 72 | : postfix_expression {$$=$1;} 73 | | INC_OP unary_expression //wait to be updated 74 | | DEC_OP unary_expression //wait to be updated 75 | | unary_operator cast_expression //abandoned? 76 | | SIZEOF unary_expression //abandoned 77 | | SIZEOF '(' type_name ')' //abandoned 78 | ; 79 | 80 | unary_operator 81 | : '&' {$$=new node("unary_operator",NULL,1,$1);} 82 | | '*' {$$=new node("unary_operator",NULL,1,$1);} 83 | | '+' {$$=new node("unary_operator",NULL,1,$1);} 84 | | '-' {$$=new node("unary_operator",NULL,1,$1);} 85 | | '~' {$$=new node("unary_operator",NULL,1,$1);} 86 | | '!' {$$=new node("unary_operator",NULL,1,$1);} 87 | ; 88 | 89 | cast_expression 90 | : unary_expression {$$=$1;} 91 | | '(' type_name ')' cast_expression //abandoned 92 | ; 93 | 94 | multiplicative_expression 95 | : cast_expression {$$=$1;} 96 | | multiplicative_expression '*' cast_expression {$$=new node("multiplicative_expression",NULL,0); $$->addSub(3,$1,new node("unary_operator",NULL,1,$2),$3);} 97 | | multiplicative_expression '/' cast_expression {$$=new node("multiplicative_expression",NULL,0); $$->addSub(3,$1,new node("unary_operator",NULL,1,$2),$3);} 98 | | multiplicative_expression '%' cast_expression {$$=new node("multiplicative_expression",NULL,0); $$->addSub(3,$1,new node("unary_operator",NULL,1,$2),$3);} 99 | ; 100 | 101 | additive_expression 102 | : multiplicative_expression {$$=$1;} 103 | | additive_expression '+' multiplicative_expression {$$=new node("additive_expression",NULL,0); $$->addSub(3,$1,new node("unary_operator",NULL,1,$2),$3);} 104 | | additive_expression '-' multiplicative_expression {$$=new node("additive_expression",NULL,0); $$->addSub(3,$1,new node("unary_operator",NULL,1,$2),$3);} 105 | ; 106 | 107 | shift_expression 108 | : additive_expression {$$=$1;} 109 | | shift_expression LEFT_OP additive_expression {$$=new node("shift_expression",NULL,0); $$->addSub(3,$1,new node("unary_operator",NULL,1,$2),$3);} 110 | | shift_expression RIGHT_OP additive_expression {$$=new node("shift_expression",NULL,0); $$->addSub(3,$1,new node("unary_operator",NULL,1,$2),$3);} 111 | ; 112 | 113 | relational_expression 114 | : shift_expression {$$=$1;} 115 | | relational_expression '<' shift_expression {$$=new node("relational_expression",NULL,0); $$->addSub(3,$1,new node("unary_operator",NULL,1,$2),$3);} 116 | | relational_expression '>' shift_expression {$$=new node("relational_expression",NULL,0); $$->addSub(3,$1,new node("unary_operator",NULL,1,$2),$3);} 117 | | relational_expression LE_OP shift_expression {$$=new node("relational_expression",NULL,0); $$->addSub(3,$1,new node("unary_operator",NULL,1,$2),$3);} 118 | | relational_expression GE_OP shift_expression {$$=new node("relational_expression",NULL,0); $$->addSub(3,$1,new node("unary_operator",NULL,1,$2),$3);} 119 | ; 120 | 121 | equality_expression 122 | : relational_expression {$$=$1;} 123 | | equality_expression EQ_OP relational_expression {$$=new node("equality_expression",NULL,0); $$->addSub(3,$1,new node("unary_operator",NULL,1,$2),$3);} 124 | | equality_expression NE_OP relational_expression {$$=new node("equality_expression",NULL,0); $$->addSub(3,$1,new node("unary_operator",NULL,1,$2),$3);} 125 | ; 126 | 127 | and_expression 128 | : equality_expression {$$=$1;} 129 | | and_expression '&' equality_expression {$$=new node("and_expression",NULL,0); $$->addSub(3,$1,new node("unary_operator",NULL,1,$2),$3);} 130 | ; 131 | 132 | exclusive_or_expression 133 | : and_expression {$$=$1;} 134 | | exclusive_or_expression '^' and_expression {$$=new node("exclusive_or_expression",NULL,0); $$->addSub(3,$1,new node("unary_operator",NULL,1,$2),$3);} 135 | ; 136 | 137 | inclusive_or_expression 138 | : exclusive_or_expression {$$=$1;} 139 | | inclusive_or_expression '|' exclusive_or_expression {$$=new node("exclusive_or_expression",NULL,0); $$->addSub(3,$1,new node("unary_operator",NULL,1,$2),$3);} 140 | ; 141 | 142 | logical_and_expression 143 | : inclusive_or_expression {$$=$1;} 144 | | logical_and_expression AND_OP inclusive_or_expression {$$=new node("logical_and_expression",NULL,0); $$->addSub(3,$1,new node("unary_operator",NULL,1,$2),$3);} 145 | ; 146 | 147 | logical_or_expression 148 | : logical_and_expression {$$=$1;} 149 | | logical_or_expression OR_OP logical_and_expression {$$=new node("logical_or_expression",NULL,0); $$->addSub(3,$1,new node("unary_operator",NULL,1,$2),$3);} 150 | ; 151 | 152 | conditional_expression 153 | : logical_or_expression {$$=$1;} 154 | | logical_or_expression '?' expression ':' conditional_expression {$$=new node("conditional_expression2",NULL,0); $$->addSub(3,$1,$3,$5);} 155 | ; 156 | 157 | assignment_expression 158 | : conditional_expression {$$=$1;} 159 | | unary_expression assignment_operator assignment_expression {$$=new node("assignment_expression",NULL,0);$$->addSub(3,$1,$2,$3);} 160 | ; 161 | 162 | assignment_operator 163 | : '=' {$$=new node("assignment_operator",NULL,1,$1);} 164 | | MUL_ASSIGN {$$=new node("assignment_operator",NULL,1,$1);} 165 | | DIV_ASSIGN {$$=new node("assignment_operator",NULL,1,$1);} 166 | | MOD_ASSIGN {$$=new node("assignment_operator",NULL,1,$1);} 167 | | ADD_ASSIGN {$$=new node("assignment_operator",NULL,1,$1);} 168 | | SUB_ASSIGN {$$=new node("assignment_operator",NULL,1,$1);} 169 | | LEFT_ASSIGN {$$=new node("assignment_operator",NULL,1,$1);} 170 | | RIGHT_ASSIGN {$$=new node("assignment_operator",NULL,1,$1);} 171 | | AND_ASSIGN {$$=new node("assignment_operator",NULL,1,$1);} 172 | | XOR_ASSIGN {$$=new node("assignment_operator",NULL,1,$1);} 173 | | OR_ASSIGN {$$=new node("assignment_operator",NULL,1,$1);} 174 | ; 175 | 176 | expression 177 | : assignment_expression {$$=$1;} 178 | | expression ',' assignment_expression 179 | ; 180 | 181 | constant_expression 182 | : conditional_expression {$$=$1;} 183 | ; 184 | 185 | declaration 186 | : declaration_specifiers ';' //I don't think we will use this, which supports "int;". 187 | | declaration_specifiers init_declarator_list ';' {$$=new node("declaration",NULL,0);$$->addSub(2,$1,$2);} 188 | ; 189 | 190 | declaration_specifiers 191 | : storage_class_specifier {$$=$1;} 192 | | storage_class_specifier declaration_specifiers {$$=new node("declaration_specifiers",NULL,0);$$->addContents(2,$1,$2);}//Risk of "auto auto int" 193 | | type_specifier {$$=$1;} 194 | | type_specifier declaration_specifiers {$$=new node("declaration_specifiers",NULL,0);$$->addContents(2,$1,$2);}//It's a sweet drug."int int" "int const" 195 | | type_qualifier {$$=$1;} 196 | | type_qualifier declaration_specifiers {$$=new node("declaration_specifiers",NULL,0);$$->addContents(2,$1,$2);}//Also a sweet drug. 197 | | function_specifier {$$=$1;}//inline 198 | | function_specifier declaration_specifiers {$$=new node("declaration_specifiers",NULL,0);$$->addContents(2,$1,$2);}//Risk of "inline inline int" 199 | ; 200 | 201 | init_declarator_list 202 | : init_declarator {$$=new node("init_declarator_list",NULL,0);$$->addSub(1,$1);} 203 | | init_declarator_list ',' init_declarator {$1->addSub(1,$3);$$=$1;} 204 | ; 205 | 206 | init_declarator 207 | : declarator {$$=$1;} 208 | | declarator '=' initializer {$$ = $1;node* t = new node("initializer_expression",NULL,0);t->addSub(3,$1->copy(),new node("assignment_operator",NULL,1,$2),$3);$$->addSub(1,t);} 209 | ; 210 | 211 | storage_class_specifier 212 | : TYPEDEF {$$=new node("storage_class_specifier",NULL,1,$1);}//Maybe we will not deal with this. 213 | | EXTERN {$$=new node("storage_class_specifier",NULL,1,$1);} 214 | | STATIC {$$=new node("storage_class_specifier",NULL,1,$1);} 215 | | AUTO {$$=new node("storage_class_specifier",NULL,1,$1);} 216 | | REGISTER {$$=new node("storage_class_specifier",NULL,1,$1);} 217 | ; 218 | 219 | type_specifier 220 | : VOID {$$=new node("type_specifier",NULL,1,$1);} 221 | | CHAR {$$=new node("type_specifier",NULL,1,$1);} 222 | | SHORT {$$=new node("type_specifier",NULL,1,$1);} 223 | | INT {$$=new node("type_specifier",NULL,1,$1);} 224 | | LONG {$$=new node("type_specifier",NULL,1,$1);} 225 | | FLOAT {$$=new node("type_specifier",NULL,1,$1);} 226 | | DOUBLE {$$=new node("type_specifier",NULL,1,$1);} 227 | | SIGNED {$$=new node("type_specifier",NULL,1,$1);} 228 | | UNSIGNED {$$=new node("type_specifier",NULL,1,$1);} 229 | | BOOL {$$=new node("type_specifier",NULL,1,$1);} 230 | | COMPLEX //Does C supports this? 231 | | IMAGINARY //Ignore 232 | | struct_or_union_specifier //Ignore. Should we deal with it? 233 | | enum_specifier //Ignore. Should we deal with it? 234 | | TYPE_NAME //lex will not generate TYPE_NAME 235 | ; 236 | 237 | struct_or_union_specifier 238 | : struct_or_union IDENTIFIER '{' struct_declaration_list '}' 239 | | struct_or_union '{' struct_declaration_list '}' 240 | | struct_or_union IDENTIFIER 241 | ; 242 | 243 | struct_or_union 244 | : STRUCT 245 | | UNION 246 | ; 247 | 248 | struct_declaration_list 249 | : struct_declaration 250 | | struct_declaration_list struct_declaration 251 | ; 252 | 253 | struct_declaration 254 | : specifier_qualifier_list struct_declarator_list ';' 255 | ; 256 | 257 | specifier_qualifier_list 258 | : type_specifier specifier_qualifier_list 259 | | type_specifier 260 | | type_qualifier specifier_qualifier_list 261 | | type_qualifier 262 | ; 263 | 264 | struct_declarator_list 265 | : struct_declarator 266 | | struct_declarator_list ',' struct_declarator 267 | ; 268 | 269 | struct_declarator 270 | : declarator 271 | | ':' constant_expression 272 | | declarator ':' constant_expression 273 | ; 274 | 275 | enum_specifier 276 | : ENUM '{' enumerator_list '}' 277 | | ENUM IDENTIFIER '{' enumerator_list '}' 278 | | ENUM '{' enumerator_list ',' '}' 279 | | ENUM IDENTIFIER '{' enumerator_list ',' '}' 280 | | ENUM IDENTIFIER 281 | ; 282 | 283 | enumerator_list 284 | : enumerator 285 | | enumerator_list ',' enumerator 286 | ; 287 | 288 | enumerator 289 | : IDENTIFIER 290 | | IDENTIFIER '=' constant_expression 291 | ; 292 | 293 | type_qualifier 294 | : CONST {$$=new node("type_qualifier",NULL,1,$1);} 295 | | RESTRICT {$$=new node("type_qualifier",NULL,1,$1);} 296 | | VOLATILE {$$=new node("type_qualifier",NULL,1,$1);} 297 | ; 298 | 299 | function_specifier 300 | : INLINE {$$=new node("function_specifier",NULL,1,$1);} 301 | ; 302 | 303 | declarator 304 | : pointer direct_declarator //wait to be updated... 305 | | direct_declarator {$$=$1;} 306 | ; 307 | 308 | 309 | direct_declarator 310 | : IDENTIFIER {$$=new node("direct_declarator",NULL,1,$1);} 311 | | '(' declarator ')' 312 | | direct_declarator '[' type_qualifier_list assignment_expression ']' //wait to be updated... 313 | | direct_declarator '[' type_qualifier_list ']' //wait to be updated... 314 | | direct_declarator '[' assignment_expression ']' //wait to be updated... 315 | | direct_declarator '[' STATIC type_qualifier_list assignment_expression ']' //wait to be updated... 316 | | direct_declarator '[' type_qualifier_list STATIC assignment_expression ']' //wait to be updated... 317 | | direct_declarator '[' type_qualifier_list '*' ']' //wait to be updated... 318 | | direct_declarator '[' '*' ']' //wait to be updated... 319 | | direct_declarator '[' ']' //wait to be updated... 320 | | direct_declarator '(' parameter_type_list ')' {$$=$1;$$->addSub(1,$3);} 321 | | direct_declarator '(' identifier_list ')' //wait to be updated... 322 | | direct_declarator '(' ')' {$$=$1;} 323 | ; 324 | 325 | pointer 326 | : '*' 327 | | '*' type_qualifier_list 328 | | '*' pointer 329 | | '*' type_qualifier_list pointer 330 | ; 331 | 332 | type_qualifier_list 333 | : type_qualifier 334 | | type_qualifier_list type_qualifier 335 | ; 336 | 337 | 338 | parameter_type_list 339 | : parameter_list {$$=$1;} 340 | | parameter_list ',' ELLIPSIS //This means "void main(int xx,...)". Shall we give up? 341 | ; 342 | 343 | parameter_list 344 | : parameter_declaration {$$=$1;} 345 | | parameter_list ',' parameter_declaration {node* t=$1;while(t->next)t=t->next;t->next=$3;} 346 | ; 347 | 348 | parameter_declaration 349 | : declaration_specifiers declarator {$$=new node("parameter_declaration",NULL,0);$$->addContents(2,$1,$2);} 350 | | declaration_specifiers abstract_declarator //wait to be updated... 351 | | declaration_specifiers //It's be abandoned. 352 | ; 353 | 354 | identifier_list 355 | : IDENTIFIER 356 | | identifier_list ',' IDENTIFIER 357 | ; 358 | 359 | type_name 360 | : specifier_qualifier_list 361 | | specifier_qualifier_list abstract_declarator 362 | ; 363 | 364 | abstract_declarator 365 | : pointer 366 | | direct_abstract_declarator 367 | | pointer direct_abstract_declarator 368 | ; 369 | 370 | direct_abstract_declarator 371 | : '(' abstract_declarator ')' 372 | | '[' ']' 373 | | '[' assignment_expression ']' 374 | | direct_abstract_declarator '[' ']' 375 | | direct_abstract_declarator '[' assignment_expression ']' 376 | | '[' '*' ']' 377 | | direct_abstract_declarator '[' '*' ']' 378 | | '(' ')' 379 | | '(' parameter_type_list ')' 380 | | direct_abstract_declarator '(' ')' 381 | | direct_abstract_declarator '(' parameter_type_list ')' 382 | ; 383 | 384 | initializer 385 | : assignment_expression {$$=$1;} 386 | | '{' initializer_list '}' 387 | | '{' initializer_list ',' '}' 388 | ; 389 | 390 | initializer_list 391 | : initializer 392 | | designation initializer 393 | | initializer_list ',' initializer 394 | | initializer_list ',' designation initializer 395 | ; 396 | 397 | designation 398 | : designator_list '=' 399 | ; 400 | 401 | designator_list 402 | : designator 403 | | designator_list designator 404 | ; 405 | 406 | designator 407 | : '[' constant_expression ']' 408 | | '.' IDENTIFIER 409 | ; 410 | 411 | statement 412 | : labeled_statement 413 | | compound_statement 414 | | expression_statement {$$=$1;} 415 | | selection_statement {$$=$1;} 416 | | iteration_statement {$$=$1;} 417 | | jump_statement 418 | | error 419 | ; 420 | 421 | labeled_statement 422 | : IDENTIFIER ':' statement 423 | | CASE constant_expression ':' statement 424 | | DEFAULT ':' statement 425 | ; 426 | 427 | compound_statement 428 | : '{' '}' //This case means nothing. 429 | | '{' block_item_list '}' {$$=$2;} 430 | ; 431 | 432 | block_item_list 433 | : block_item {$$=$1;} 434 | | block_item_list block_item {node* t=$1;while(t->next)t=t->next;t->next=$2;} 435 | ; 436 | 437 | block_item 438 | : declaration {$$=$1;} 439 | | statement {$$=$1;} 440 | ; 441 | 442 | expression_statement 443 | : ';' {$$=new node("null", NULL, 0);} 444 | | expression ';' {$$=$1;} 445 | ; 446 | 447 | selection_statement 448 | : IF '(' expression ')' statement {$$=new node("if_statement", NULL, 0); $$->addSub(2,$3,$5);} 449 | | IF '(' expression ')' statement ELSE statement {$$=new node("if_else_statement", NULL, 0); $$->addSub(3,$3,$5,$7);} 450 | | SWITCH '(' expression ')' statement {$$=new node("switch_statement", NULL, 0); $$->addSub(2,$3,$5);} 451 | ; 452 | 453 | iteration_statement 454 | : WHILE '(' expression ')' statement {$$=new node("while_statement", NULL, 0); $$->addSub(2,$3,$5);} 455 | | DO statement WHILE '(' expression ')' ';' {$$=new node("do_while_statement", NULL, 0); $$->addSub(2,$2,$5);} 456 | | FOR '(' expression_statement expression_statement ')' statement {$$=new node("for_statement_exp2", NULL, 0); $$->addSub(3,$3,$4,$6);} 457 | | FOR '(' expression_statement expression_statement expression ')' statement {$$=new node("for_statement_exp3", NULL, 0); $$->addSub(4,$3,$4,$5,$7);} 458 | | FOR '(' declaration expression_statement ')' statement {$$=new node("for_statement_dcl2", NULL, 0); $$->addSub(3,$3,$4,$6);} 459 | | FOR '(' declaration expression_statement expression ')' statement {$$=new node("for_statement_dcl3", NULL, 0); $$->addSub(4,$3,$4,$5,$7);} 460 | ; 461 | 462 | jump_statement 463 | : GOTO IDENTIFIER ';' //no use 464 | | CONTINUE ';' {$$=new node("continue",NULL,1,$1);} 465 | | BREAK ';' {$$=new node("break",NULL,1,$1);} 466 | | RETURN ';' {$$=new node("return_statement",NULL,1,$1);} 467 | | RETURN expression ';' {$$=new node("return_statement",NULL,1,$1); $$->addSub(1,$2);} 468 | ; 469 | start 470 | : 471 | translation_unit {root=$1;} 472 | ; 473 | translation_unit 474 | : external_declaration {$$=$1;} 475 | | translation_unit external_declaration {node* t=$1;while(t->next)t=t->next;t->next=$2;} 476 | | error 477 | ; 478 | 479 | external_declaration 480 | : function_definition {$$=$1;} 481 | | declaration {$$=$1;} 482 | ; 483 | 484 | function_definition 485 | : declaration_specifiers declarator declaration_list compound_statement //We will not deal with this case! 486 | | declaration_specifiers declarator compound_statement {$$=new node("function_definition",NULL,0);$$->addContents(2,$1,$2);$$->addSub(1,$3);} 487 | ; 488 | 489 | declaration_list //This case is abandoned. 490 | : declaration 491 | | declaration_list declaration 492 | | error 493 | ; 494 | 495 | 496 | %% 497 | void yyerror(char const *s) 498 | { 499 | fflush(stdout); 500 | //printf("\n%*s\n%*s\n", column, "^", column, s); 501 | printf("%----------s--------error here!\n",s); 502 | hasError = true; 503 | errorNum++; 504 | } 505 | 506 | -------------------------------------------------------------------------------- /Ccompi1er/element.h: -------------------------------------------------------------------------------- 1 | #ifndef _ELEMENT_H 2 | #define _ELEMENT_H 3 | #include 4 | using namespace std; 5 | class element 6 | { 7 | public: 8 | int lineNum; 9 | string content; 10 | string name; 11 | element(int lineNum,string name,string content){ 12 | this->lineNum = lineNum; 13 | this->name = name; 14 | this->content = content; 15 | } 16 | }; 17 | #endif 18 | -------------------------------------------------------------------------------- /Ccompi1er/main.cpp: -------------------------------------------------------------------------------- 1 | #include"node.h" 2 | #include"compiler.hpp" 3 | #include 4 | #include "RGenerator.cpp" 5 | extern FILE *yyin; 6 | using namespace std; 7 | extern node* root; 8 | extern bool hasError; 9 | extern int errorNum; 10 | int yyparse(); 11 | int main() 12 | { 13 | yyin = fopen("test.c","r"); 14 | yyparse(); 15 | //root->debugInfo(true,true); //show info all the instructions following,no extand 16 | cout<next->next->debugInfo(false,true);//only show this instruction,extand 18 | if(!hasError){ 19 | cout << endl << "中间树" << endl; 20 | RGenerator translator(root); 21 | } 22 | else{ 23 | cout<<"There are "< 4 | #include 5 | #include"element.h" 6 | #include 7 | #include 8 | using namespace std; 9 | class node{ 10 | public: 11 | string type; 12 | node* next; 13 | vector contents; 14 | vector sub; 15 | node* parent; 16 | node(string type,node* next,int eleNum,...){ 17 | this->type = type; 18 | this->next = next; 19 | this->parent = NULL; 20 | va_list ap; 21 | va_start(ap, eleNum); 22 | for(int i=0;icontents=contents; 28 | return t; 29 | } 30 | void reName(string newtype){ 31 | type = newtype; 32 | } 33 | void addSub(int subNum,...){ 34 | va_list ap; 35 | va_start(ap, subNum); 36 | for(int i=0;iparent = this; 39 | sub.push_back(t); 40 | } 41 | } 42 | void addContents(int nodeNum,...){ 43 | va_list ap; 44 | va_start(ap, nodeNum); 45 | for(int i=0;icontents.insert(this->contents.end(),t->contents.begin(),t->contents.end()); 49 | for (int i = 0; i < t->sub.size(); i++){ 50 | t->sub[i]->parent = this; 51 | sub.push_back(t->sub[i]); 52 | } 53 | delete t; 54 | } 55 | } 56 | void debugInfo(bool next=true,bool expand=true) { 57 | node* t = this; 58 | while (t) { 59 | cout << t->type << endl; 60 | for (int i = 0; i < t->contents.size(); i++) 61 | cout << t->contents[i]->lineNum << " " << t->contents[i]->name << " " << t->contents[i]->content << endl; 62 | if(expand) 63 | for (int i = 0; i < t->sub.size(); i++) 64 | {cout<<"sub"<sub[i]->debugInfo();} 65 | if(next) 66 | t = t->next; 67 | else 68 | break; 69 | } 70 | } 71 | }; 72 | #endif 73 | -------------------------------------------------------------------------------- /Ccompi1er/result.asm: -------------------------------------------------------------------------------- 1 | 2 | .data 3 | _prompt: .asciiz "Enter an integer:" 4 | _ret: .asciiz "\n" 5 | .globl main 6 | .text 7 | read: 8 | li $v0,4 9 | la $a0,_prompt 10 | syscall 11 | li $v0,5 12 | syscall 13 | jr $ra 14 | print: 15 | li $v0,1 16 | syscall 17 | li $v0,4 18 | la $a0,_ret 19 | syscall 20 | move $v0,$0 21 | jr $ra 22 | main: 23 | addi $sp,$sp,-4 24 | sw $ra,0($sp) 25 | jal read 26 | lw $ra,0($sp) 27 | move $t1,$v0 28 | addi $sp,$sp,4 29 | move $t2,$t1 30 | li $t1,1 31 | move $t3,$t1 32 | li $t1,1 33 | move $t4,$t1 34 | li $t1,0 35 | move $t5,$t1 36 | label_0: 37 | slt $t1,$t5,$t2 38 | bne $t1,$zero,label_1 39 | j label_3 40 | label_1: 41 | li $t1,0 42 | sub $t6,$t1,$t5 43 | beq $t6,$zero,label_4 44 | j label_5 45 | label_4: 46 | li $t1,1 47 | move $t0,$a0 48 | move $a0,$t1 49 | addi $sp,$sp,-4 50 | sw $ra,0($sp) 51 | jal print 52 | lw $ra,0($sp) 53 | addi $sp,$sp,4 54 | j label_2 55 | label_5: 56 | li $t1,1 57 | sub $t6,$t1,$t5 58 | beq $t6,$zero,label_6 59 | j label_7 60 | label_6: 61 | li $t1,1 62 | move $t0,$a0 63 | move $a0,$t1 64 | addi $sp,$sp,-4 65 | sw $ra,0($sp) 66 | jal print 67 | lw $ra,0($sp) 68 | addi $sp,$sp,4 69 | j label_2 70 | label_7: 71 | add $t1,$t3,$t4 72 | move $t7,$t1 73 | move $t3,$t4 74 | move $t4,$t7 75 | move $t0,$a0 76 | move $a0,$t4 77 | addi $sp,$sp,-4 78 | sw $ra,0($sp) 79 | jal print 80 | lw $ra,0($sp) 81 | addi $sp,$sp,4 82 | label_2: 83 | li $t1,1 84 | add $t6,$t5,$t1 85 | move $t5,$t6 86 | j label_0 87 | -------------------------------------------------------------------------------- /Ccompi1er/test.c: -------------------------------------------------------------------------------- 1 | void main(){ 2 | int i; 3 | int a = read(); 4 | for(i=0; i 2 | 3 | 4 | 5 | 6 | EnvironmentId 7 | {eb4cdf42-d3cc-43f2-b875-c1a9027a70c6} 8 | 9 | 10 | ProjectExplorer.Project.ActiveTarget 11 | 0 12 | 13 | 14 | ProjectExplorer.Project.EditorSettings 15 | 16 | true 17 | false 18 | true 19 | 20 | Cpp 21 | 22 | CppGlobal 23 | 24 | 25 | 26 | QmlJS 27 | 28 | QmlJSGlobal 29 | 30 | 31 | 2 32 | UTF-8 33 | false 34 | 4 35 | false 36 | 80 37 | true 38 | true 39 | 1 40 | true 41 | false 42 | 0 43 | true 44 | true 45 | 0 46 | 8 47 | true 48 | 1 49 | true 50 | true 51 | true 52 | false 53 | 54 | 55 | 56 | ProjectExplorer.Project.PluginSettings 57 | 58 | 59 | 60 | ProjectExplorer.Project.Target.0 61 | 62 | Desktop Qt 5.8.0 clang 64bit 63 | Desktop Qt 5.8.0 clang 64bit 64 | qt.58.clang_64_kit 65 | 0 66 | 0 67 | 0 68 | 69 | /Users/geshuaiqi/Desktop/SyntaxHighlighterEditor/build-aweSomeEditorhiahia-Desktop_Qt_5_8_0_clang_64bit-Debug 70 | 71 | 72 | true 73 | qmake 74 | 75 | QtProjectManager.QMakeBuildStep 76 | true 77 | 78 | false 79 | false 80 | false 81 | 82 | 83 | true 84 | Make 85 | 86 | Qt4ProjectManager.MakeStep 87 | 88 | -w 89 | -r 90 | 91 | false 92 | 93 | 94 | 95 | 2 96 | 构建 97 | 98 | ProjectExplorer.BuildSteps.Build 99 | 100 | 101 | 102 | true 103 | Make 104 | 105 | Qt4ProjectManager.MakeStep 106 | 107 | -w 108 | -r 109 | 110 | true 111 | clean 112 | 113 | 114 | 1 115 | 清理 116 | 117 | ProjectExplorer.BuildSteps.Clean 118 | 119 | 2 120 | false 121 | 122 | Debug 123 | 124 | Qt4ProjectManager.Qt4BuildConfiguration 125 | 2 126 | true 127 | 128 | 129 | /Users/geshuaiqi/Desktop/SyntaxHighlighterEditor/build-aweSomeEditorhiahia-Desktop_Qt_5_8_0_clang_64bit-Release 130 | 131 | 132 | true 133 | qmake 134 | 135 | QtProjectManager.QMakeBuildStep 136 | false 137 | 138 | false 139 | false 140 | false 141 | 142 | 143 | true 144 | Make 145 | 146 | Qt4ProjectManager.MakeStep 147 | 148 | -w 149 | -r 150 | 151 | false 152 | 153 | 154 | 155 | 2 156 | 构建 157 | 158 | ProjectExplorer.BuildSteps.Build 159 | 160 | 161 | 162 | true 163 | Make 164 | 165 | Qt4ProjectManager.MakeStep 166 | 167 | -w 168 | -r 169 | 170 | true 171 | clean 172 | 173 | 174 | 1 175 | 清理 176 | 177 | ProjectExplorer.BuildSteps.Clean 178 | 179 | 2 180 | false 181 | 182 | Release 183 | 184 | Qt4ProjectManager.Qt4BuildConfiguration 185 | 0 186 | true 187 | 188 | 189 | /Users/geshuaiqi/Desktop/SyntaxHighlighterEditor/build-aweSomeEditorhiahia-Desktop_Qt_5_8_0_clang_64bit-Profile 190 | 191 | 192 | true 193 | qmake 194 | 195 | QtProjectManager.QMakeBuildStep 196 | true 197 | 198 | false 199 | true 200 | false 201 | 202 | 203 | true 204 | Make 205 | 206 | Qt4ProjectManager.MakeStep 207 | 208 | -w 209 | -r 210 | 211 | false 212 | 213 | 214 | 215 | 2 216 | 构建 217 | 218 | ProjectExplorer.BuildSteps.Build 219 | 220 | 221 | 222 | true 223 | Make 224 | 225 | Qt4ProjectManager.MakeStep 226 | 227 | -w 228 | -r 229 | 230 | true 231 | clean 232 | 233 | 234 | 1 235 | 清理 236 | 237 | ProjectExplorer.BuildSteps.Clean 238 | 239 | 2 240 | false 241 | 242 | Profile 243 | 244 | Qt4ProjectManager.Qt4BuildConfiguration 245 | 0 246 | true 247 | 248 | 3 249 | 250 | 251 | 0 252 | 部署 253 | 254 | ProjectExplorer.BuildSteps.Deploy 255 | 256 | 1 257 | 在本地部署 258 | 259 | ProjectExplorer.DefaultDeployConfiguration 260 | 261 | 1 262 | 263 | 264 | false 265 | false 266 | 1000 267 | 268 | true 269 | 270 | false 271 | false 272 | false 273 | false 274 | true 275 | 0.01 276 | 10 277 | true 278 | 1 279 | 25 280 | 281 | 1 282 | true 283 | false 284 | true 285 | valgrind 286 | 287 | 0 288 | 1 289 | 2 290 | 3 291 | 4 292 | 5 293 | 6 294 | 7 295 | 8 296 | 9 297 | 10 298 | 11 299 | 12 300 | 13 301 | 14 302 | 303 | 2 304 | 305 | aweSomeEditorhiahia 306 | 307 | Qt4ProjectManager.Qt4RunConfiguration:/Users/geshuaiqi/Desktop/MiniCompiler/aweSomeEditorhiahia.pro 308 | true 309 | 310 | aweSomeEditorhiahia.pro 311 | false 312 | 313 | 314 | 3768 315 | false 316 | true 317 | false 318 | false 319 | true 320 | 321 | 1 322 | 323 | 324 | 325 | ProjectExplorer.Project.TargetCount 326 | 1 327 | 328 | 329 | ProjectExplorer.Project.Updater.FileVersion 330 | 18 331 | 332 | 333 | Version 334 | 18 335 | 336 | 337 | -------------------------------------------------------------------------------- /bash.txt: -------------------------------------------------------------------------------- 1 | mkdir s -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | #include 3 | 4 | int main(int argc, char *argv[]) 5 | { 6 | QApplication a(argc, argv); 7 | MainWindow w; 8 | w.resize(1600,800); 9 | w.show(); 10 | 11 | return a.exec(); 12 | } 13 | -------------------------------------------------------------------------------- /mainwindow.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | #include "QMenu" 3 | #include "QMenuBar" 4 | #include "QAction" 5 | #include "QToolBar" 6 | #include "QDebug" 7 | #include "QPushButton" 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include "QTextBrowser" 16 | #include //ifstream 17 | #include 18 | #include"QString" 19 | #include"QFile" 20 | 21 | using namespace std ; 22 | 23 | MainWindow::MainWindow(QWidget *parent) : 24 | QMainWindow(parent) 25 | { 26 | this->setupUi(this); 27 | 28 | //菜单栏 29 | QMenuBar *mBar = menuBar(); 30 | 31 | //添加菜单 32 | QMenu *pFile = mBar->addMenu("开始"); 33 | pFile->addSeparator(); 34 | QAction * pOpen = pFile->addAction("打开"); 35 | 36 | //工具栏--菜单项的快捷方式 37 | QToolBar *toolBar = addToolBar("toolbar");//创建工具栏 38 | QPushButton * b = new QPushButton(this); 39 | b->setText("运行"); 40 | toolBar->addWidget(b);//工具栏添加其他组件--按钮 41 | 42 | QTextBrowser* report = textBrowser; 43 | QTextBrowser* intercode = textBrowser_2; 44 | QTextBrowser* assembly = textBrowser_3; 45 | 46 | configEditor = new CodeEditor(); 47 | configEditor->setMode(EDIT); 48 | gridLayout->addWidget(configEditor); 49 | MyHighLighter *highlighter = new MyHighLighter(configEditor->document()); 50 | 51 | ifstream inf; 52 | string s; 53 | 54 | inf.open("/Users/geshuaiqi/desktop/SyntaxHighlighterEditor/aweSomeEditorhiahia/Ccompi1er/test.c"); 55 | while (getline(inf, s)) { 56 | cout << s << endl; 57 | QString qstring = QString(QString::fromLocal8Bit(s.c_str())); 58 | configEditor->appendPlainText(qstring); 59 | } 60 | inf.close(); 61 | 62 | 63 | 64 | 65 | connect(b,&QPushButton::clicked, 66 | [=](){ 67 | 68 | 69 | textBrowser->setPlainText(""); 70 | textBrowser_2->setPlainText(""); 71 | textBrowser_3->setPlainText(""); 72 | 73 | QString content = configEditor->toPlainText(); 74 | QFile outFile("/Users/geshuaiqi/desktop/SyntaxHighlighterEditor/aweSomeEditorhiahia/Ccompi1er/test.c"); 75 | outFile.open(QIODevice::WriteOnly); 76 | QTextStream ts(&outFile); 77 | ts << content << endl; 78 | 79 | ifstream inf; 80 | string s; 81 | chdir("/Users/geshuaiqi/desktop/SyntaxHighlighterEditor/aweSomeEditorhiahia/Ccompi1er"); 82 | system("pwd"); 83 | system("bash Makefile"); 84 | 85 | 86 | inf.open("/Users/geshuaiqi/desktop/SyntaxHighlighterEditor/aweSomeEditorhiahia/Ccompi1er/ErrorLog.txt"); 87 | while (getline(inf, s)) { 88 | cout << s << endl; 89 | QString qstring = QString(QString::fromLocal8Bit(s.c_str())); 90 | textBrowser->append(QString(qstring)); 91 | } 92 | inf.close(); 93 | 94 | inf.open("/Users/geshuaiqi/desktop/SyntaxHighlighterEditor/aweSomeEditorhiahia/Ccompi1er/AST.txt"); 95 | while (getline(inf, s)) { 96 | cout << s << endl; 97 | QString qstring = QString(QString::fromLocal8Bit(s.c_str())); 98 | textBrowser_2->append(QString(qstring)); 99 | } 100 | inf.close(); 101 | 102 | inf.open("/Users/geshuaiqi/desktop/SyntaxHighlighterEditor/aweSomeEditorhiahia/Ccompi1er/MIPS/objectcode.asm"); 103 | while (getline(inf, s)) { 104 | cout << s << endl; 105 | QString qstring = QString(QString::fromLocal8Bit(s.c_str())); 106 | textBrowser_3->append(QString(qstring)); 107 | } 108 | inf.close(); 109 | 110 | }); 111 | 112 | 113 | 114 | 115 | 116 | } 117 | 118 | MainWindow::~MainWindow() 119 | { 120 | } 121 | -------------------------------------------------------------------------------- /mainwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINWINDOW_H 2 | #define MAINWINDOW_H 3 | 4 | #include 5 | #include "ui_mainwindow.h" 6 | #include "src/codeeditor.h" 7 | #include "src/myhighlighter.h" 8 | #include "src/typedef.h" 9 | class MainWindow : public QMainWindow,Ui::MainWindow 10 | { 11 | Q_OBJECT 12 | 13 | public: 14 | explicit MainWindow(QWidget *parent = 0); 15 | ~MainWindow(); 16 | 17 | private: 18 | CodeEditor *configEditor; 19 | CodeEditor *configEditor2; 20 | CodeEditor *configEditor3; 21 | }; 22 | 23 | #endif // MAINWINDOW_H 24 | -------------------------------------------------------------------------------- /mainwindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 591 10 | 489 11 | 12 | 13 | 14 | MainWindow 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 350 25 | 0 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 350 35 | 0 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 350 45 | 0 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /src/codeeditor.cpp: -------------------------------------------------------------------------------- 1 | #include "codeeditor.h" 2 | #include 3 | 4 | CodeEditor::CodeEditor(QWidget *parent) : QPlainTextEdit(parent) 5 | { 6 | lineNumberArea = new LineNumberArea(this); 7 | 8 | connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int))); 9 | connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateLineNumberArea(QRect,int))); 10 | connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(highlightCurrentLine())); 11 | 12 | updateLineNumberAreaWidth(0); 13 | setMode(BROWSE); 14 | } 15 | int CodeEditor::lineNumberAreaWidth() 16 | { 17 | int digits = 1; 18 | int max = qMax(1, blockCount()); 19 | while (max >= 10) { 20 | max /= 10; 21 | ++digits; 22 | } 23 | 24 | int space = 3 + fontMetrics().width(QLatin1Char('9')) * digits; 25 | 26 | return space; 27 | } 28 | 29 | void CodeEditor::updateLineNumberAreaWidth(int /* newBlockCount */) 30 | { 31 | setViewportMargins(lineNumberAreaWidth(), 0, 0, 0); 32 | } 33 | 34 | void CodeEditor::updateLineNumberArea(const QRect &rect, int dy) 35 | { 36 | if (dy) 37 | lineNumberArea->scroll(0, dy); 38 | else 39 | lineNumberArea->update(0, rect.y(), lineNumberArea->width(), rect.height()); 40 | 41 | if (rect.contains(viewport()->rect())) 42 | updateLineNumberAreaWidth(0); 43 | } 44 | 45 | void CodeEditor::resizeEvent(QResizeEvent *e) 46 | { 47 | QPlainTextEdit::resizeEvent(e); 48 | 49 | QRect cr = contentsRect(); 50 | lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height())); 51 | } 52 | void CodeEditor::highlightCurrentLine() 53 | { 54 | QList extraSelections; 55 | 56 | if (!isReadOnly()) { 57 | QTextEdit::ExtraSelection selection; 58 | 59 | QColor lineColor = QColor(Qt::yellow).lighter(160); 60 | 61 | selection.format.setBackground(lineColor); 62 | selection.format.setProperty(QTextFormat::FullWidthSelection, true); 63 | //selection.cursor = textCursor(); 64 | //selection.cursor.clearSelection(); 65 | extraSelections.append(selection); 66 | } 67 | 68 | setExtraSelections(extraSelections); 69 | } 70 | 71 | void CodeEditor::lineNumberAreaPaintEvent(QPaintEvent *event) 72 | { 73 | QPainter painter(lineNumberArea); 74 | painter.fillRect(event->rect(), Qt::lightGray); 75 | 76 | 77 | QTextBlock block = firstVisibleBlock(); 78 | int blockNumber = block.blockNumber(); 79 | int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top(); 80 | int bottom = top + (int) blockBoundingRect(block).height(); 81 | 82 | while (block.isValid() && top <= event->rect().bottom()) { 83 | if (block.isVisible() && bottom >= event->rect().top()) { 84 | QString number = QString::number(blockNumber + 1); 85 | painter.setPen(Qt::black); 86 | painter.drawText(-2, top, lineNumberArea->width(), fontMetrics().height(), 87 | Qt::AlignRight, number); 88 | } 89 | 90 | block = block.next(); 91 | top = bottom; 92 | bottom = top + (int) blockBoundingRect(block).height(); 93 | ++blockNumber; 94 | } 95 | } 96 | void CodeEditor::setMode(editorMode mode) 97 | { 98 | if(mode == BROWSE) 99 | { 100 | this->setReadOnly(true); 101 | this->setStyleSheet("background:#f2f2f3;"); 102 | highlightCurrentLine(); 103 | } 104 | else if(mode == EDIT) 105 | { 106 | this->setReadOnly(false); 107 | this->setStyleSheet("background:#ffffff;"); 108 | highlightCurrentLine(); 109 | } 110 | } -------------------------------------------------------------------------------- /src/codeeditor.h: -------------------------------------------------------------------------------- 1 | #ifndef CODEEDITOR_H 2 | #define CODEEDITOR_H 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | class LineNumberArea; 13 | 14 | class CodeEditor : public QPlainTextEdit 15 | { 16 | Q_OBJECT 17 | 18 | public: 19 | CodeEditor(QWidget *parent = 0); 20 | void setMode(editorMode mode); 21 | void lineNumberAreaPaintEvent(QPaintEvent *event); 22 | int lineNumberAreaWidth(); 23 | 24 | protected: 25 | void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE; 26 | 27 | private slots: 28 | void updateLineNumberAreaWidth(int newBlockCount); 29 | void highlightCurrentLine(); 30 | void updateLineNumberArea(const QRect &, int); 31 | 32 | private: 33 | QWidget *lineNumberArea; 34 | }; 35 | 36 | 37 | class LineNumberArea : public QWidget 38 | { 39 | public: 40 | LineNumberArea(CodeEditor *editor) : QWidget(editor) { 41 | codeEditor = editor; 42 | } 43 | 44 | QSize sizeHint() const Q_DECL_OVERRIDE { 45 | return QSize(codeEditor->lineNumberAreaWidth(), 0); 46 | } 47 | 48 | protected: 49 | void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE { 50 | codeEditor->lineNumberAreaPaintEvent(event); 51 | } 52 | 53 | private: 54 | CodeEditor *codeEditor; 55 | }; 56 | 57 | #endif // CODEEDITOR_H 58 | -------------------------------------------------------------------------------- /src/myhighlighter.cpp: -------------------------------------------------------------------------------- 1 | #include "myhighlighter.h" 2 | 3 | MyHighLighter::MyHighLighter(QTextDocument *parent) 4 | : QSyntaxHighlighter(parent) 5 | { 6 | HighlightingRule rule; 7 | 8 | keywordFormat.setForeground(Qt::darkBlue); 9 | keywordFormat.setFontWeight(QFont::Bold); 10 | QStringList keywordPatterns; 11 | keywordPatterns << "\\bchar\\b" << "\\bclass\\b" << "\\bconst\\b" 12 | << "\\bdouble\\b" << "\\benum\\b" << "\\bexplicit\\b" 13 | << "\\bfriend\\b" << "\\binline\\b" << "\\bint\\b" 14 | << "\\blong\\b" << "\\bnamespace\\b" << "\\boperator\\b" 15 | << "\\bprivate\\b" << "\\bprotected\\b" << "\\bpublic\\b" 16 | << "\\bshort\\b" << "\\bsignals\\b" << "\\bsigned\\b" 17 | << "\\bslots\\b" << "\\bstatic\\b" << "\\bstruct\\b" 18 | << "\\btemplate\\b" << "\\btypedef\\b" << "\\btypename\\b" 19 | << "\\bunion\\b" << "\\bunsigned\\b" << "\\bvirtual\\b" 20 | << "\\bvoid\\b" << "\\bvolatile\\b"; 21 | foreach (const QString &pattern, keywordPatterns) { 22 | rule.pattern = QRegExp(pattern); 23 | rule.format = keywordFormat; 24 | highlightingRules.append(rule); 25 | } 26 | classFormat.setFontWeight(QFont::Bold); 27 | classFormat.setForeground(Qt::darkMagenta); 28 | rule.pattern = QRegExp("\\bQ[A-Za-z]+\\b"); 29 | rule.format = classFormat; 30 | highlightingRules.append(rule); 31 | 32 | singleLineCommentFormat.setForeground(Qt::red); 33 | rule.pattern = QRegExp("//[^\n]*"); 34 | rule.format = singleLineCommentFormat; 35 | highlightingRules.append(rule); 36 | 37 | multiLineCommentFormat.setForeground(Qt::red); 38 | 39 | quotationFormat.setForeground(Qt::darkGreen); 40 | rule.pattern = QRegExp("\".*\""); 41 | rule.format = quotationFormat; 42 | highlightingRules.append(rule); 43 | 44 | functionFormat.setFontItalic(true); 45 | functionFormat.setForeground(Qt::blue); 46 | rule.pattern = QRegExp("\\b[A-Za-z0-9_]+(?=\\()"); 47 | rule.format = functionFormat; 48 | highlightingRules.append(rule); 49 | 50 | commentStartExpression = QRegExp("/\\*"); 51 | commentEndExpression = QRegExp("\\*/"); 52 | } 53 | 54 | void MyHighLighter::highlightBlock(const QString &text) 55 | { 56 | foreach (const HighlightingRule &rule, highlightingRules) { 57 | QRegExp expression(rule.pattern); 58 | int index = expression.indexIn(text); 59 | while (index >= 0) { 60 | int length = expression.matchedLength(); 61 | setFormat(index, length, rule.format); 62 | index = expression.indexIn(text, index + length); 63 | } 64 | } 65 | 66 | setCurrentBlockState(0); 67 | 68 | int startIndex = 0; 69 | if (previousBlockState() != 1) 70 | startIndex = commentStartExpression.indexIn(text); 71 | 72 | 73 | while (startIndex >= 0) { 74 | int endIndex = commentEndExpression.indexIn(text, startIndex); 75 | int commentLength; 76 | if (endIndex == -1) { 77 | setCurrentBlockState(1); 78 | commentLength = text.length() - startIndex; 79 | } else { 80 | commentLength = endIndex - startIndex 81 | + commentEndExpression.matchedLength(); 82 | } 83 | setFormat(startIndex, commentLength, multiLineCommentFormat); 84 | startIndex = commentStartExpression.indexIn(text, startIndex + commentLength); 85 | } 86 | } -------------------------------------------------------------------------------- /src/myhighlighter.h: -------------------------------------------------------------------------------- 1 | #ifndef MYHIGHLIGHTER_H 2 | #define MYHIGHLIGHTER_H 3 | #include 4 | #include 5 | #include 6 | class MyHighLighter : public QSyntaxHighlighter 7 | { 8 | Q_OBJECT 9 | 10 | public: 11 | MyHighLighter(QTextDocument *parent = 0); 12 | 13 | protected: 14 | void highlightBlock(const QString &text) Q_DECL_OVERRIDE; 15 | 16 | private: 17 | struct HighlightingRule 18 | { 19 | QRegExp pattern; 20 | QTextCharFormat format; 21 | }; 22 | QVector highlightingRules; 23 | 24 | QRegExp commentStartExpression; 25 | QRegExp commentEndExpression; 26 | 27 | QTextCharFormat keywordFormat; 28 | QTextCharFormat classFormat; 29 | QTextCharFormat singleLineKey; 30 | QTextCharFormat singleLineValue; 31 | QTextCharFormat singleLineCommentFormat; 32 | QTextCharFormat multiLineCommentFormat; 33 | QTextCharFormat quotationFormat; 34 | QTextCharFormat functionFormat; 35 | }; 36 | #endif // MYHIGHLIGHTER_H 37 | -------------------------------------------------------------------------------- /src/typedef.h: -------------------------------------------------------------------------------- 1 | #ifndef TYPEDEF_H 2 | #define TYPEDEF_H 3 | 4 | typedef enum{ 5 | BROWSE, 6 | EDIT, 7 | }editorMode; 8 | 9 | 10 | #endif // TYPEDEF_H 11 | 12 | --------------------------------------------------------------------------------