果真仍是SB了

編譯原理的龍書和虎書,各看了兩章以後,¥……&……*……@%¥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 }

 

 

最後,無心中看到了這哥們擺弄的玩意,貌似也比我好不到哪去。。。。。。哇哈哈哈,可悲的咱碼農啊

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

相關文章
相關標籤/搜索