遞迴下降文法分析

來源:互聯網
上載者:User
用遞迴下降的文法分析器實現簡單的計算機:

看了這篇部落格之後,總算搞明白了以前編譯原理沒搞懂的ll文法的意義。下面用這種方法實現一個簡單的電腦器程式:

定義文法為了體現出遞迴下降法簡潔之處,計算運算式採用lisp語言的方式來書寫,這樣就能避免中綴運算式轉換成尾碼運算式,破壞了遞迴下降的格局。在lisp語言裡,會強制指出運算子優先順序:(1+2 * 5)*(3+4)在LISP會被寫成(*(+
1 (* 5 2)) (+ 3 4) )其BNF範式如下:Operator=”+”
Operator=”-“
Operator=”*”
Operator=”/”
Expression=<0,1,2,3,4,..,9>
Expression= “(” Operator Expression Expression “)”
Expression=“(”Expression “)”實現
#include <string>#include <memory>struct Expression{Expression() : result(), Error(), Start(NULL) {}float result;std::string Error;char*Start;};class Lexer{public:Lexer(const std::string& str);private:void SkipWhitespace();bool match(const char* text);char isOpreator();Expression GetExpression();Expression GetNumber();std::unique_ptr<char[]> buffer;size_tcur;size_tsize;};
#include "Parser.h"#include <iostream>#include <cctype>#include <cassert>Lexer::Lexer(const std::string& str):cur(),size(){size_t len = str.length();std::unique_ptr<char[]> ss(new char[len + 1]);memcpy(ss.get(),str.c_str(),len);ss[len] = 0;buffer = std::move(ss);size = len + 1;//std::cout << buffer.get() <<std::endl; //<<<<<<<<<debug : this line should be delete//SkipWhitespace();//Expression exp = GetExpression();if (exp.Error.empty()) {std::cout << exp.result <<std::endl; //<<<<<<<<<debug : this line should be delete} else {std::cout << "發生錯誤:" <<std::endl;std::cout << "位置: " << exp.Start <<std::endl;std::cout << "資訊: " << exp.Error <<std::endl;}}void Lexer::SkipWhitespace(){while (buffer[cur] == ' ' && cur != size) {++cur;}}bool Lexer::match(const char* text){size_t len = strlen(text);SkipWhitespace();if (strncmp(&buffer[cur],text,len) == 0) {cur += len;return true;}return false;}char Lexer::isOpreator(){if (match("+") || match("-") || match("*") || match("/")) {return buffer[cur - 1];//返回操作符}return 0;}Expression Lexer::GetExpression(){Expression ret = GetNumber(); //第一個字元是數字或者運算式if (!ret.Error.empty()) { //第一個不是數字,匹配括弧if (match("(")) { // (...)//匹配操作符char op = isOpreator();  //( op (exp) (exp) ) if (op > 0) {ret.Error = "";//擷取左參數Expression left = GetExpression();if (!left.Error.empty()) { //left出錯return left;}//擷取右邊的運算式Expression right = GetExpression();if (!right.Error.empty()) {return right;}switch (op) {case '+':ret.result = left.result + right.result;break;case '-':ret.result = left.result - right.result;break;case '*':ret.result = left.result * right.result;break;case '/':if (right.result == 0) {ret.Error = "被除數不能為0";ret.Start = static_cast<char*>(&buffer[cur]);} else {ret.result = left.result / right.result;}break;default:assert(false && "should never get here");break;}} else { //不是操作符 (expression)ret = GetExpression();if (!ret.Error.empty()) {return ret;}}if (!match(")")) {ret.Error = "此處缺少反括弧)";}} else {ret.Error = "此處出現未知字元";ret.Start = static_cast<char*>(&buffer[cur]);return ret;}}return ret;}Expression Lexer::GetNumber(){Expression ret;SkipWhitespace();bool getnum = false;bool negative = false;int point = 0;while (true) {char c = buffer[cur];if (isdigit(c)) {float ci = c - '0';if (point > 0) { //小數點後面for (int i = 0; i < point; ++i) {ci /= 10;}++point;ret.result = ret.result + ci;} else {ret.result = ret.result * 10 + ci;}//多個數字++cur;getnum = true;} else if (c == '-' && !getnum) { //第一位是負數negative = true;++cur;} else if (c == '.') { //小數點point = 1;++cur;} else {break;}}if (negative) {ret.result = - ret.result;}if (!getnum) {ret.Error = "這裡應該是數字";ret.Start = static_cast<char*>(&buffer[cur]);}return ret;}
#include <iostream>#include <string>#include "Parser.h"#pragma warning(disable:4996)using namespace std;int main(int argc,char* argv[]){freopen("input.txt","rt",stdin);freopen("output.txt","wt",stdout);std::string input;while (getline(std::cin,input)) {Lexer lex(input);}return 0;}

測試:

           (* (+ 1.003 2) (+ 3 -4) )(/ (+ 5 6) (- b3 5) )(+ 3 5 )  輸出:-3.003發生錯誤:位置: b3 5) )資訊: 此處出現未知字元8

改進

用遞迴下降來解析XML和JSON

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.