编译原理的龙书和虎书,各看了两章以后,¥……&……*……@%¥node
好吧,既然是码农,就要从基层作起,我尝试handwritten一下C或者C的极小子集的one-pass编译器先,等有了深切的体会再去研究那些高深的形式理论也不迟。因而,我花了几天搞了简单的词法分析,还费了一包子力,凭我那捉急的智商,凑出来一个像是语法树的东西,能解析四则运算表达式。书上说手写编译器用递归降低法最合适,我想了半天也不知道咋递归降低。。刚才看了看书上的简化手写语法分析器,一共才100行不到,我只好望书兴叹了,唉,底子彻底不够硬啊,差得远啊。git
写了几天hardcode的一点心得:算法
终于有点明白为何书上要咱们把文法的BNF产生式都列出来,而后再相应的为每一个产生式写实现函数了,这实际上是在算法解耦。 好比咱们能够测试发现,下面的递归降低语法器是不支持unary operator的,好比3*-2。若是想加入这个运算规则,咱们只需在文法中新加入一条规则,而后修缮文法,最后编码:在递归降低的层次中加入一个unary()函数,下层是factor(),上层是term(),完成。如此即可以经过加新的函数来扩展支持逻辑运算,比较运算。而若是像我那样hardcode的话。。。。。。。扩展的时候翔的感受一会儿就出来了。编程
并且考虑到相似这样的语法特性:函数
a = b = c = 1;测试
利用递归降低法也能完美简洁的解决啊!编码
为何要编译原理?由于我手写的玩意已经愈来愈意大利面条了,每扩充一个feature真是牵一发而动全身,本身都彻底不能肯定有没有给其余地方引入bug,也许最后能编译通常的C代码文件了,可是我TM都不知道为何它能运做,当要移植到其它平台或者想复用来作个其它语言的编译器时,只能傻眼了.这正是所谓的"靠人品编程".此乃码农的标志性特征:先把功能赶完,bug可不敢说没有有的话大不了加班修修补补呗...大神们作最基础的编译器时可不敢怀着这种大无畏精神...虽然个人意大利面条杯具了,可是不错的是认识到了编译原理的重要性..lua
贴上代码:spa
标准的递归降低语法器:.net
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 char token; /*全局标志变量*/ 5 6 /*递归调用的函数原型*/ 7 int exp( void ); 8 int term( void ); 9 int factor( void ); 10 11 void error( void ) /*报告出错信息的函数*/ 12 { 13 fprintf( stderr, "错误\n"); 14 exit( 1 ); 15 } 16 17 void match( char expectedToken ) /*对当前的标志进行匹配*/ 18 { 19 if( token == expectedToken ) token = getchar(); /*匹配成功,获取下一个标志*/ 20 else error(); /*匹配不成功,报告错误*/ 21 } 22 void Message(void) 23 { 24 printf("================================================================\n"); 25 printf("* 递归实现的四则运算表达式求值程序 *\n"); 26 printf("****************************************************************\n"); 27 printf("使用方法:请从键盘上直接输入表达式,以回车键结束.如45*(12-2)[回车]\n"); 28 printf("*****************************************************************\n\n"); 29 } 30 main() 31 { 32 int result; /*运算的结果*/ 33 Message(); 34 printf(" >> 请输入表达式: "); 35 token = getchar(); /*载入第一个符号*/ 36 37 result = exp(); /*进行计算*/ 38 if( token == '\n' ) /* 是否一行结束 */ 39 printf( " >> 表达式的计算结果为 : %d\n", result ); 40 else error(); /* 出现了例外的字符 */ 41 puts("\n\n 请按任意键退出 ...\n"); 42 getch(); 43 return 0; 44 } 45 46 int exp( void ) 47 { 48 int temp = term(); /*计算比加减运算优先级别高的部分*/ 49 while(( token == '+' ) || ( token == '-' )) 50 switch( token ) { 51 case '+': match('+'); /*加法*/ 52 temp += term(); 53 break; 54 case '-': match('-'); 55 temp -= term(); /*减法*/ 56 break; 57 } 58 return temp; 59 } 60 61 int term( void ) 62 { 63 int div; /*除数*/ 64 int temp = factor(); /*计算比乘除运算优先级别高的部分*/ 65 while(( token == '*' ) || ( token == '/' )) 66 switch( token ) { 67 case '*': match('*'); /*乘法*/ 68 temp *= factor(); 69 break; 70 case '/': match('/'); /*除法*/ 71 div = factor(); 72 if( div == 0 ) /*须要判断除数是否为0*/ 73 { 74 fprintf( stderr, "除数为0.\n" ); 75 exit(1); 76 } 77 temp /= div; 78 break; 79 } 80 return temp; 81 } 82 83 int factor( void ) 84 { 85 int temp; 86 if( token == '(' ) /*带有括号的运算*/ 87 { 88 match( '(' ); 89 temp = exp(); 90 match(')'); 91 } 92 else if ( isdigit( token )) /*实际的数字*/ 93 { 94 ungetc( token, stdin ); /*将读入的字符退还给输入流*/ 95 scanf( "%d", &temp ); /*读出数字*/ 96 token = getchar(); /*读出当前的标志*/ 97 } 98 else error(); /*不是括号也不是数字*/ 99 return temp; 100 }
我那翔通常的代码:
1 #include "StdAfx.h" 2 #include "SyntaxTree.h" 3 #include "Compiler.h" 4 5 eTokenType SyntaxTree::lastTokenType = eTokenType_Invalid; 6 7 int SyntaxTreeOpNode::Evaluate() 8 { 9 if (!strcmp(op, "+")) 10 { 11 return lchild->Evaluate() + rchild->Evaluate(); 12 } 13 else if (!strcmp(op, "-")) 14 { 15 return lchild->Evaluate() - rchild->Evaluate(); 16 } 17 else if (!strcmp(op, "*")) 18 { 19 return lchild->Evaluate() * rchild->Evaluate(); 20 } 21 else if (!strcmp(op, "/")) 22 { 23 return lchild->Evaluate() / rchild->Evaluate(); 24 } 25 else 26 { 27 //TODO: refactoring for no ugly if-else 28 assert(0); 29 return 0; 30 } 31 } 32 33 bool SyntaxTreeOpNode::IsThisOpPriorityHigher( const char* s ) 34 { 35 return cl.opPriorityMap[op] >= cl.opPriorityMap[s]; 36 } 37 38 int SyntaxTreeLeafNode::Evaluate() 39 { 40 return value; 41 } 42 43 int SyntaxTreeRootNode::Evaluate() 44 { 45 assert(rchild && "WTF!? This is not my tree!"); 46 return rchild->Evaluate(); 47 } 48 49 SyntaxTree::SyntaxTree() 50 :root(nullptr) 51 { 52 } 53 54 SyntaxTree::~SyntaxTree() 55 { 56 ResetTree(); 57 } 58 59 bool SyntaxTree::ConstructTree(int len) 60 { 61 const char* expstart = cl.sentence + cl.sentence_curpos; 62 assert(expstart[0] != 0); 63 char op[MAX_IDENT_LEN]; 64 eTokenType type; 65 SyntaxTreeNode* curNode = root; 66 std::vector<int> vecNums; 67 std::vector<SyntaxTreeOpNode*> vecFlatNodes; 68 69 //1.首先构建运算符的树结构 70 while (cl.sentence_curpos < len) 71 { 72 type = cl.ScanWord(op); 73 if (type == eTokenType_Operator) 74 { 75 auto iter = cl.opPriorityMap.find(op); 76 assert(iter != cl.opPriorityMap.end() && "Invalid op!"); 77 SyntaxTreeOpNode* node = new SyntaxTreeOpNode; 78 strcpy_s(node->op, ARRAYSIZE(node->op), op); 79 80 //unary op process 81 bool bUnary = op[1]==0 && (op[0]=='+' || op[0]=='-'); 82 if (lastTokenType==eTokenType_Operator || lastTokenType==eTokenType_LBracket && bUnary) 83 { 84 vecNums.push_back(0); 85 curNode->rchild = node; 86 node->parent = curNode; 87 } 88 else if (curNode->IsThisOpPriorityHigher(op)) 89 { 90 assert(node->parent == nullptr); 91 curNode->parent = node; 92 node->lchild = curNode; 93 //下降root高度 94 root->rchild = node; 95 node->parent = root; 96 } 97 else 98 { 99 curNode->rchild = node; 100 node->parent = curNode; 101 } 102 curNode = node; 103 vecFlatNodes.push_back(node); 104 } 105 else if (type == eTokenType_ConstantNumber) 106 { 107 vecNums.push_back(atoi(op)); 108 } 109 else if (type == eTokenType_LBracket) 110 { 111 int substr_len = len - 1; 112 //must find a matching r-bracket! 113 bool bFind = false; 114 while (substr_len >= cl.sentence_curpos) 115 { 116 if(cl.sentence[substr_len] == ')') 117 { 118 bFind = true; 119 break; 120 } 121 --substr_len; 122 } 123 if (bFind) 124 { 125 //对于括号,咱们利用递归来求值... 126 SyntaxTree tmpTree; 127 tmpTree.ResetTree(); 128 if(tmpTree.ConstructTree(substr_len)) 129 vecNums.push_back(tmpTree.Evaluate()); 130 else 131 return false; 132 133 assert(cl.sentence[cl.sentence_curpos] == ')' && "Can't be true!..."); 134 ++cl.sentence_curpos; 135 } 136 else 137 { 138 LOG_ERR(eErr_NotMatchBracket); 139 return false; 140 } 141 type = eTokenType_ConstantNumber; 142 } 143 else 144 { 145 LOG_ERR(eErr_InvalidExpression); 146 return false; 147 } 148 lastTokenType = type; 149 } 150 151 //2.而后为每一个运算符插入叶节点 152 if (root->rchild == nullptr) 153 { 154 LOG_ERR(eErr_InvalidExpression); 155 return false; 156 } 157 158 size_t leaf = 0, totalLeaf = vecNums.size(); 159 for (size_t i=0; i<vecFlatNodes.size(); ++i) 160 { 161 SyntaxTreeOpNode* node = vecFlatNodes[i]; 162 if (!node->lchild) 163 { 164 if (leaf < totalLeaf) 165 { 166 SyntaxTreeLeafNode* leafNode = new SyntaxTreeLeafNode; 167 leafNode->value = vecNums[leaf]; 168 node->lchild = leafNode; 169 leafNode->parent = node; 170 ++leaf; 171 } 172 else 173 { 174 LOG_ERR(eErr_InvalidExpression); 175 return false; 176 } 177 } 178 if (!node->rchild) 179 { 180 if (leaf < totalLeaf) 181 { 182 SyntaxTreeLeafNode* leafNode = new SyntaxTreeLeafNode; 183 leafNode->value = vecNums[leaf]; 184 node->rchild = leafNode; 185 leafNode->parent = node; 186 ++leaf; 187 } 188 else 189 { 190 LOG_ERR(eErr_InvalidExpression); 191 return false; 192 } 193 } 194 } 195 196 return true; 197 } 198 199 void SyntaxTree::ResetTree() 200 { 201 SAFE_DELETE(root); 202 root = new SyntaxTreeRootNode; 203 } 204 205 int SyntaxTree::Evaluate() 206 { 207 return root->Evaluate(); 208 }
最后,无心中看到了这哥们摆弄的玩意,貌似也比我好不到哪去。。。。。。哇哈哈哈,可悲的咱码农啊