在维护新建对象的时候,利用对象休眠的闲暇,写了个习作。
咸盐少许。
通常,编译原理或编译技术都会建议使用yacc或lex来实现语言、公式的解释器或编译器。鉴于实现一个语言编译器或解释器的困难,大多数猿类都会使用这类工具。不过,本文穿越到了工具出现以前的时代,同时又开启了金手指:带了c#、Flex和Bison。既是习作,故使用c#手工打造了一个简单的c语言解释器,而并未使用Flex和Bison。遂有此文。
这个解释器,斗胆命名为SharpC。它实现了c语言的如下部分功能:
1. 基本的类型:char, short, int, float。
对于unsigned, signed的区分不明显,不支持const关键字。
2. 支持函数。
包括不定参数函数,支持递归,支持嵌套定义。
3. 支持几乎所有表达式。
不支持?:三元操作符,逗号操作符未测试。
4. 支持指针。
这意味着支持内存操作,也意味支持字符串。
5. 支持除goto外的所有控制结构。
包括:if/else, for, while, do/while, switch/case/default/break, return, continue.
6. 其它。
内建了几个基本的辅助函数:malloc, free, print, vararg, varlen, input, prompt, confirm。
7.所有其他c语言功能皆不支持。
诸如#符号,typedef, struct等。
我们先看看最终结果,对于这样的一个c源代码:
/* * This is a multi-line comment. * */ // This is a single line comment. char globalChar = 'A'; short globalShort = 333; int globalInt = 1; // Global scope declaration float globalFloat = 1.2345; char* ptr = "abcdefg" "hijklmn"; void funcFwdDecl(); // forwarding declaration void funcWithoutArg() { // Variable declaration and initialization int x = 1; // Empty statement ; { // anonymous block int y = 3; } // end of block // Test bare expression 1 < 2; 1 <= 2; 2 > 1; 2 >= 1; // Test comments x += 1 // This is a comment ; // Test assign x = 10 - 3; x += 1; x -= 1; x *= 1; x /= 1; x %= 1; x &= 1; x |= 1; x ^= 1; x <<= 1; x >>= 1; // Test pre/post operator x = x++; x = x--; x = ++x; x = --x; // Control flow // If with statement if (x <= 1) x++; // If/else if (x <= 2) x--; else x++; // if/else matching 1 if (x <= 3) --x; else if (x <= 4) x++; if (x <= 5) x += 1; else if (x <= 6) x += 2; else x += 3; // If with block if (x <= 7) { x /= 10; } else { x *= 10; } if (1 < 2) x = 0; else if (3 < 4) x = 1; else x = 2; // for loop // Commonly for loop with single statemnt for(int i = 0; i < 100; i++) x++; // for loop with block for(int i = 0; i < 100; i++) { x++; x--; } // for loop with long initializer int i = 0; for(i = 1, x = 0; i < 100; i++) { x--; x++; } // for loop with long iterator for(int l = 0; l < 100; l++, x--, x++, x--) x--; // for loop with break & continue for(int l = 0; l < 100; l++) { if (l > 100) break; else if (l > 50) continue; } // while with single statement while(1 < 2) x++; // while with block while(x < 3) { x++; x; } // while with break & continue while( x < 10) { if (x > 5) break; else continue; x++; } // do/while do{ x++; x--; --x; ++x; }// comments while(1); switch(x) { case '0': break; case 'a': break; case '\t': break; case 1: case 2: case 3: break; case 5: { x--; x++; x *= 10; } break; case 6: switch(x) { case 1: case 2: case 3: break; case 4: { } break; default: break; } break; default: x++; break; } return 1; // This will cause an error. } // end of func void funcWithArg(int var1) { return; } void funcWithManyArg(int var1, int var2, int var3) { do{ var1++; var2--; if (var1 + var2 <= var3) return ; }while(1 > 2); while(var2 > var1) { int ddd = 100; continue; } int innerFunc(int var4, int var5) { var4 = var1 + var2 + var3 / var5; } innerFunc(1, 2); } int funcInt() { return ; // This will cause an error. } int funcVar(...) { funcVar(1, 2, 3); return 0; }
SharpC的分析结果如下:
SharpC.Grammar.Variable: Line: 7 Pos: 7 "globalChar" SharpC.Grammar.Statement: Line: 7 Pos: 7 "globalChar = 'A'" SharpC.Grammar.Variable: Line: 8 Pos: 8 "globalShort" SharpC.Grammar.Statement: Line: 8 Pos: 8 "globalShort = 333" SharpC.Grammar.Variable: Line: 9 Pos: 6 "globalInt" SharpC.Grammar.Statement: Line: 9 Pos: 6 "globalInt = 1" SharpC.Grammar.Variable: Line: 10 Pos: 8 "globalFloat" SharpC.Grammar.Statement: Line: 10 Pos: 8 "globalFloat = 1.2345" SharpC.Grammar.Variable: Line: 12 Pos: 8 "ptr" SharpC.Grammar.Statement: Line: 12 Pos: 8 "ptr = "abcdefg" "hijklmn"" SharpC.Grammar.Variable: Line: 19 Pos: 7 "x" SharpC.Grammar.Statement: Line: 19 Pos: 7 "x = 1" SharpC.Grammar.Statement: Line: 22 Pos: 3 ";" SharpC.Grammar.Variable: Line: 25 Pos: 7 " " SharpC.Grammar.Statement: Line: 25 Pos: 7 " y = " SharpC.Grammar.Statement: Line: 29 Pos: 3 "1 < 2;" SharpC.Grammar.Statement: Line: 30 Pos: 3 "1 <= 2;" SharpC.Grammar.Statement: Line: 31 Pos: 3 "2 > 1;" SharpC.Grammar.Statement: Line: 32 Pos: 3 "2 >= 1;" SharpC.Grammar.Statement: Line: 34 Pos: 3 "x += 1 // This is a comment ;" SharpC.Grammar.Statement: Line: 38 Pos: 3 "x = 10 - 3;" SharpC.Grammar.Statement: Line: 39 Pos: 3 "x += 1;" SharpC.Grammar.Statement: Line: 40 Pos: 3 "x -= 1;" SharpC.Grammar.Statement: Line: 41 Pos: 3 "x *= 1;" SharpC.Grammar.Statement: Line: 42 Pos: 3 "x /= 1;" SharpC.Grammar.Statement: Line: 43 Pos: 3 "x %= 1;" SharpC.Grammar.Statement: Line: 44 Pos: 3 "x &= 1;" SharpC.Grammar.Statement: Line: 45 Pos: 3 "x |= 1;" SharpC.Grammar.Statement: Line: 46 Pos: 3 "x ^= 1;" SharpC.Grammar.Statement: Line: 47 Pos: 3 "x <<= 1;" SharpC.Grammar.Statement: Line: 48 Pos: 3 "x >>= 1;" SharpC.Grammar.Statement: Line: 51 Pos: 3 "x = x++;" SharpC.Grammar.Statement: Line: 52 Pos: 3 "x = x--;" SharpC.Grammar.Statement: Line: 53 Pos: 3 "x = ++x;" SharpC.Grammar.Statement: Line: 54 Pos: 3 "x = --x;" SharpC.Grammar.Statement: Line: 59 Pos: 4 "x++;" SharpC.Grammar.ControlFlow.IfThen: Line: 58 Pos: 3 "if (x <= 1) " SharpC.Grammar.Statement: Line: 63 Pos: 4 "x--;" SharpC.Grammar.ControlFlow.IfThen: Line: 62 Pos: 3 "if (x <= 2) " SharpC.Grammar.Statement: Line: 65 Pos: 4 "x++;" SharpC.Grammar.ControlFlow.IfThen: Line: 62 Pos: 3 "if (x <= 2) x--; else " SharpC.Grammar.Statement: Line: 69 Pos: 4 "--x;" SharpC.Grammar.ControlFlow.IfThen: Line: 68 Pos: 3 "if (x <= 3) " SharpC.Grammar.Statement: Line: 72 Pos: 5 "x++;" SharpC.Grammar.ControlFlow.IfThen: Line: 71 Pos: 4 "if (x <= 4) " SharpC.Grammar.ControlFlow.IfThen: Line: 68 Pos: 3 "if (x <= 3) --x; else " SharpC.Grammar.Statement: Line: 75 Pos: 4 "x += 1;" SharpC.Grammar.ControlFlow.IfThen: Line: 74 Pos: 3 "if (x <= 5) " SharpC.Grammar.Statement: Line: 78 Pos: 5 "x += 2;" SharpC.Grammar.ControlFlow.IfThen: Line: 77 Pos: 4 "if (x <= 6) " SharpC.Grammar.ControlFlow.IfThen: Line: 74 Pos: 3 "if (x <= 5) x += 1; else " SharpC.Grammar.Statement: Line: 80 Pos: 5 "x += 3;" SharpC.Grammar.ControlFlow.IfThen: Line: 74 Pos: 3 "if (x <= 5) x += 1; else if (x <= 6) x += 2; else " SharpC.Grammar.Statement: Line: 85 Pos: 4 "x /= 10;" SharpC.Grammar.ControlFlow.IfThen: Line: 83 Pos: 3 "if (x <= 7) { x /= 10; }" SharpC.Grammar.Statement: Line: 89 Pos: 4 "x *= 10;" SharpC.Grammar.ControlFlow.IfThen: Line: 83 Pos: 3 "if (x <= 7) { x /= 10; } else { x *= 10; }" SharpC.Grammar.Statement: Line: 93 Pos: 4 "x = 0;" SharpC.Grammar.ControlFlow.IfThen: Line: 92 Pos: 3 "if (1 < 2) " SharpC.Grammar.Statement: Line: 96 Pos: 6 "x = 1;" SharpC.Grammar.ControlFlow.IfThen: Line: 95 Pos: 4 "if (3 < 4) " SharpC.Grammar.ControlFlow.IfThen: Line: 92 Pos: 3 "if (1 < 2) x = 0; else " SharpC.Grammar.Statement: Line: 98 Pos: 7 "x = 2;" SharpC.Grammar.ControlFlow.IfThen: Line: 92 Pos: 3 "if (1 < 2) x = 0; else if (3 < 4) x = 1; else " SharpC.Grammar.Variable: Line: 102 Pos: 11 "i" SharpC.Grammar.Statement: Line: 102 Pos: 11 "i = 0" SharpC.Grammar.Statement: Line: 103 Pos: 4 "x++;" SharpC.Grammar.ControlFlow.ForLoop: Line: 102 Pos: 3 "for(int i = 0; i < 100; i++) " SharpC.Grammar.Variable: Line: 106 Pos: 11 "i" SharpC.Grammar.Statement: Line: 106 Pos: 11 "i = 0" SharpC.Grammar.Statement: Line: 108 Pos: 4 "x++;" SharpC.Grammar.Statement: Line: 109 Pos: 4 "x--;" SharpC.Grammar.ControlFlow.ForLoop: Line: 106 Pos: 3 "for(int i = 0; i < 100; i++) {" SharpC.Grammar.Variable: Line: 113 Pos: 7 "i" SharpC.Grammar.Statement: Line: 113 Pos: 7 "i = 0" SharpC.Grammar.Statement: Line: 114 Pos: 7 "i = 1, x = 0;" SharpC.Grammar.Statement: Line: 116 Pos: 4 "x--;" SharpC.Grammar.Statement: Line: 117 Pos: 4 "x++;" SharpC.Grammar.ControlFlow.ForLoop: Line: 114 Pos: 3 "for(i = 1, x = 0; i < 100; i++) {" SharpC.Grammar.Variable: Line: 121 Pos: 11 "l" SharpC.Grammar.Statement: Line: 121 Pos: 11 "l = 0" SharpC.Grammar.Statement: Line: 122 Pos: 4 "x--;" SharpC.Grammar.ControlFlow.ForLoop: Line: 121 Pos: 3 "for(int l = 0; l < 100; l++, x--, x++, x--) " SharpC.Grammar.Variable: Line: 125 Pos: 11 "l" SharpC.Grammar.Statement: Line: 125 Pos: 11 "l = 0" SharpC.Grammar.ControlFlow.Break: Line: 128 Pos: 5 "break;" SharpC.Grammar.ControlFlow.IfThen: Line: 127 Pos: 4 "if (l > 100) " SharpC.Grammar.ControlFlow.Continue: Line: 131 Pos: 6 "continue" SharpC.Grammar.ControlFlow.IfThen: Line: 130 Pos: 5 "if (l > 50) " SharpC.Grammar.ControlFlow.IfThen: Line: 127 Pos: 4 "if (l > 100) break; else " SharpC.Grammar.ControlFlow.ForLoop: Line: 125 Pos: 3 "for(int l = 0; l < 100; l++) {" SharpC.Grammar.Statement: Line: 135 Pos: 16 "x++;" SharpC.Grammar.ControlFlow.WhileLoop: Line: 135 Pos: 3 "while(1 < 2) " SharpC.Grammar.ControlFlow.WhileLoop: Line: 135 Pos: 3 "while(1 < 2) " SharpC.Grammar.Statement: Line: 140 Pos: 4 "x++;" SharpC.Grammar.Statement: Line: 141 Pos: 4 "x;" SharpC.Grammar.ControlFlow.WhileLoop: Line: 138 Pos: 3 "while(x < 3) {" SharpC.Grammar.ControlFlow.WhileLoop: Line: 138 Pos: 3 "while(x < 3) {" SharpC.Grammar.ControlFlow.Break: Line: 148 Pos: 5 "break;" SharpC.Grammar.ControlFlow.IfThen: Line: 147 Pos: 4 "if (x > 5) " SharpC.Grammar.ControlFlow.Continue: Line: 150 Pos: 5 "continue" SharpC.Grammar.ControlFlow.IfThen: Line: 147 Pos: 4 "if (x > 5) break; else " SharpC.Grammar.Statement: Line: 152 Pos: 4 "x++;" SharpC.Grammar.ControlFlow.WhileLoop: Line: 145 Pos: 3 "while( x < 10) {" SharpC.Grammar.ControlFlow.WhileLoop: Line: 145 Pos: 3 "while( x < 10) {" SharpC.Grammar.Statement: Line: 157 Pos: 4 "x++;" SharpC.Grammar.Statement: Line: 158 Pos: 4 "x--;" SharpC.Grammar.Statement: Line: 159 Pos: 4 "--x;" SharpC.Grammar.Statement: Line: 160 Pos: 4 "++x;" SharpC.Grammar.ControlFlow.DoWhileLoop: Line: 156 Pos: 3 "do{" SharpC.Grammar.ControlFlow.Case: Line: 166 Pos: 4 "case '0':" SharpC.Grammar.ControlFlow.Break: Line: 166 Pos: 14 "break;" SharpC.Grammar.ControlFlow.Case: Line: 167 Pos: 4 "case 'a':" SharpC.Grammar.ControlFlow.Break: Line: 167 Pos: 14 "break;" SharpC.Grammar.ControlFlow.Case: Line: 168 Pos: 4 "case '\t':" SharpC.Grammar.ControlFlow.Break: Line: 168 Pos: 15 "break;" SharpC.Grammar.ControlFlow.Case: Line: 169 Pos: 4 "case 1:" SharpC.Grammar.ControlFlow.Case: Line: 170 Pos: 4 "case 2:" SharpC.Grammar.ControlFlow.Case: Line: 171 Pos: 4 "case 3:" SharpC.Grammar.ControlFlow.Break: Line: 171 Pos: 12 "break;" SharpC.Grammar.ControlFlow.Case: Line: 172 Pos: 4 "case 5:" SharpC.Grammar.Statement: Line: 174 Pos: 5 " x--" SharpC.Grammar.Statement: Line: 175 Pos: 5 " x++" SharpC.Grammar.Statement: Line: 176 Pos: 5 " x *= 10" SharpC.Grammar.ControlFlow.Break: Line: 178 Pos: 5 "break;" SharpC.Grammar.ControlFlow.Case: Line: 179 Pos: 4 "case 6:" SharpC.Grammar.ControlFlow.Case: Line: 182 Pos: 6 "case 1:" SharpC.Grammar.ControlFlow.Case: Line: 183 Pos: 6 "case 2:" SharpC.Grammar.ControlFlow.Case: Line: 184 Pos: 6 "case 3:" SharpC.Grammar.ControlFlow.Break: Line: 184 Pos: 14 "break;" SharpC.Grammar.ControlFlow.Case: Line: 185 Pos: 6 "case 4:" SharpC.Grammar.ControlFlow.Break: Line: 188 Pos: 7 "break;" SharpC.Grammar.ControlFlow.Break: Line: 189 Pos: 15 "break;" SharpC.Grammar.ControlFlow.Switch: Line: 180 Pos: 5 "switch(x) { case 1: case 2: case 3: break; case 4: { } break; default: break; }" SharpC.Grammar.ControlFlow.Break: Line: 191 Pos: 5 "break;" SharpC.Grammar.Statement: Line: 192 Pos: 13 "x++;" SharpC.Grammar.ControlFlow.Break: Line: 192 Pos: 18 "break;" SharpC.Grammar.ControlFlow.Switch: Line: 164 Pos: 3 "switch(x) { case '0': break; case 'a': break; case '\t': break; case 1: case 2: case 3: break; case 5: { x--; x++; x *= 10; } break; case 6: switch(x) { case 1: case 2: case 3: break; case 4: { } break; default: break; } break; default: x++; break; }" 1>>Syntax error: Line: 196 Pos: 3 "return 1;": return value type does not match the function type. SharpC.Grammar.ControlFlow.Return: Line: 196 Pos: 3 "return 1;" SharpC.Grammar.ControlFlow.Return: Line: 201 Pos: 3 "return;" SharpC.Grammar.Statement: Line: 207 Pos: 4 "var1++;" SharpC.Grammar.Statement: Line: 208 Pos: 4 "var2--;" SharpC.Grammar.ControlFlow.Return: Line: 211 Pos: 5 "return ;" SharpC.Grammar.ControlFlow.IfThen: Line: 210 Pos: 4 "if (var1 + var2 <= var3) " SharpC.Grammar.ControlFlow.DoWhileLoop: Line: 206 Pos: 3 "do{" 2>>Syntax error: Line: 214 Pos: 3 "while": ';' is expected. SharpC.Grammar.ControlFlow.DoWhileLoop: Line: 206 Pos: 3 "do{ var1++; var2--; if (var1 + var2 <= var3) return ; }while(1 > 2)" SharpC.Grammar.Statement: Line: 223 Pos: 4 "var4 = var1 + var2 + var3 / var5;" SharpC.Grammar.Statement: Line: 227 Pos: 3 "innerFunc(1, 2);" 3>>Syntax error: Line: 232 Pos: 3 "return ;": return value type does not match the function type. SharpC.Grammar.ControlFlow.Return: Line: 232 Pos: 3 "return ;" SharpC.Grammar.Statement: Line: 237 Pos: 3 "funcVar(1, 2, 3);" SharpC.Grammar.ControlFlow.Return: Line: 238 Pos: 3 "return 0;" Time consumption: 0.5753843 sec
打印分析生成的语法树以还原代码:
char * $var_char_ptr_6$ (const) refers to $var_char_ptr_6$ Data length:15 void * malloc(int size) void free(void * ptr) int input(char * title, char * message, char * defValue, char * format, char * errMsg, char * result) int confirm(char * title, char * msg) void prompt(char * title, char * msg) void print(...) char vararg(int argIdx) int varlen() char globalChar globalChar = 65 short globalShort globalShort = 333 int globalInt globalInt = 1 float globalFloat globalFloat = 1.2345 char * ptr ptr = $var_char_ptr_6$ void funcFwdDecl() void funcWithoutArg() { int x x = 1 { int y y = 3 } 1 < 2 1 <= 2 2 > 1 2 >= 1 x += 1 x = 10 - 3 x += 1 x += 1 x *= 1 x /= 1 x %= 1 x &= 1 x |= 1 x ^= 1 x <<= 1 x >>= 1 x = x++ x = x-- x = ++x x = --x if(x <= 1) { x++ } if(x <= 2) { x-- } else { x++ } if(x <= 3) { --x } else { if(x <= 4) { x++ } } if(x <= 5) { x += 1 } else { x += 3 } if(x <= 7) { x /= 10 } else { x *= 10 } if(1 < 2) { x = 0 } else { x = 2 } for( Initalizer: int i i = 0 Condition: i < 100 Iterator: i++ { x++ } for( Initalizer: int i i = 0 Condition: i < 100 Iterator: i++ { x++ x-- } int i i = 0 for( Initalizer: i = 1 Condition: i < 100 Iterator: i++ { x-- x++ } for( Initalizer: int l l = 0 Condition: l < 100 Iterator: l++ { x-- } for( Initalizer: int l l = 0 Condition: l < 100 Iterator: l++ { if(l > 100) { break; } else { if(l > 50) { continue; } } } while(1 < 2) { x++ } while(x < 3) { x++ x } while(x < 10) { if(x > 5) { break; } else { continue; } x++ } do { x++ x-- --x ++x } while(1) switch(x) { default: { x++ break; } case 48: { break; } case 97: { break; } case 9: { break; } case 1: { } case 2: { } case 3: { break; } case 5: { { x-- x++ x *= 10 } break; } case 6: { switch(x) { default: { break; } case 1: { } case 2: { } case 3: { break; } case 4: { { } break; } } break; } } return 1 } void funcWithArg(int var1) { return ; } void funcWithManyArg(int var1, int var2, int var3) { do { var1++ var2-- if(var1 + var2 <= var3) { return ; } } while(1 > 2) int innerFunc(int var4, int var5) { var4 = var1 + var2 + var3 / var5 } innerFunc(1,2,) } int funcInt() { return ; } int funcVar(...) { funcVar(1,2,3,) return 0 }
可以看到,结果大致与源代码相同。