果然还是SB了

编译原理的龙书和虎书,各看了两章之后,¥……&……*……@%¥

 

好吧,既然是码农,就要从基层做起,我尝试handwritten一下C或者C的极小子集的one-pass编译器先,等有了深切的体会再去研究那些高深的形式理论也不迟。于是,我花了几天搞了简单的词法分析,还费了一包子力,凭我那捉急的智商,凑出来一个像是语法树的东西,能解析四则运算表达式。书上说手写编译器用递归下降法最合适,我想了半天也不知道咋递归下降。。刚才看了看书上的简化手写语法分析器,一共才100行不到,我只好望书兴叹了,唉,底子完全不够硬啊,差得远啊。

 

写了几天hardcode的一点心得:

终于有点明白为什么书上要我们把文法的BNF产生式都列出来,然后再相应的为每个产生式写实现函数了,这其实是在算法解耦。 比如我们可以测试发现,下面的递归下降语法器是不支持unary operator的,比如3*-2。如果想加入这个运算规则,我们只需在文法中新加入一条规则,然后修缮文法,最后编码:在递归下降的层次中加入一个unary()函数,下层是factor(),上层是term(),完成。如此便可以通过加新的函数来扩展支持逻辑运算,比较运算。而如果像我那样hardcode的话。。。。。。。扩展的时候翔的感觉一下子就出来了。

而且考虑到类似这样的语法特性:

a = b = c = 1;

利用递归下降法也能完美简洁的解决啊!

 


为什么要编译原理?因为我手写的玩意已经越来越意大利面条了,每扩充一个feature真是牵一发而动全身,自己都完全不能确定有没有给其他地方引入bug,也许最后能编译一般的C代码文件了,但是我TM都不知道为什么它能运作,当要移植到其它平台或者想复用来做个其它语言的编译器时,只能傻眼了.这正是所谓的"靠人品编程".此乃码农的标志性特征:先把功能赶完,bug可不敢说没有有的话大不了加班修修补补呗...大神们做最基础的编译器时可不敢怀着这种大无畏精神...虽然我的意大利面条杯具了,但是不错的是认识到了编译原理的重要性..

 

 

贴上代码:

 

标准的递归下降语法器:

  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 }

 

 

最后,无意中看到了这哥们摆弄的玩意,貌似也比我好不到哪去。。。。。。哇哈哈哈,可悲的咱码农啊

http://blog.csdn.net/zhouzxi/article/details/7897301

posted @ 2013-08-30 23:48  mavaL  阅读(981)  评论(0编辑  收藏  举报