日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

LALR(1)语法分析生成器--xbytes

發布時間:2023/12/18 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LALR(1)语法分析生成器--xbytes 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

  0.概述:

  看了編譯器龍書和虎書后,自己手動寫了一個LALR(1)語法分析生成器,使用的語法文件格式和lemon的差不多。

  程序里面很多的算法也都是摘錄自虎書,龍書雖然講的很詳細,但是真正動手寫的時候還是虎書上面的算法給力點。程序相對來說比較簡單,沒有做任何優化,如果看過虎書和龍書,看懂代碼難度不大。代碼文件bytes.hpp和bytes.cpp中是主要的代碼,TEMPLATE.hxx和TEMPLATE.cxx是語法分析生成器的模板文件。首先直接用make進行編譯,然后進入到test目錄中,運行生成器程序文件,參數是語法說明文件。執行成功后會生成會文件PARSER.hxx和PARSER.cxx,這兩個文件就是你需要的語法分析器了。下面是個簡單的實例說明下。

  1.語法說明文件:

這里用一個簡單的計算器來說明語法說明文件的用法。下面是計算器的語法說明文件。

%include { #include <iostream> } %token { int } %syntax_error { std::cout << "Error: Syntax error.\n" << std::endl;} #left PLUS MINUS #left TIMES DIVprogram -> exp(A). { std::cout << "Result=" << A << std::endl; }exp(A) -> exp(B) MINUS exp(C). { A = B - C; std::cout << A << "=" << B << "-" << C << std::endl; } exp(A) -> exp(B) PLUS exp(C). { A = B + C; std::cout << A << "=" << B << "+" << C << std::endl; } exp(A) -> exp(B) TIMES exp(C). { A = B * C; std::cout << A << "=" << B << "*" << C << std::endl; } exp(A) -> exp(B) DIV exp(C). {if(C != 0){A = B / C;}else{std::cout << "Divide by zero." << std::endl;}std::cout << A << "=" << B << "/" << C << std::endl; }exp(A) -> INT(B). { A = B; std::cout << A << "=" << B << std::endl;}

終結符:終結符的名稱只能由大寫字母組成,在生成PARSER.hxx文件中會包括所有終結符的枚舉定義。詞法分析器的分析結果要和這里定義的枚舉值一致。

  非終結符:非終結符由小寫字母、下劃線組成,非終結符只存在于生成語法分析器的過程中。生成的語法分析器不會包括非終結符。

  %include:這個說明符指定了生成的語法分析程序中要包含的頭文件,這個指示符的格式是后面必須用大括號。如果有多個頭文件可以用回車。

  %token:這個是token結構的指示符,必須在大括號中指定,目前只支持內建的數據類型。

  %syntax_error:語法分析過程中出現錯誤時,需要執行的代碼。

  #left:左結合指示符。同時會指定優先級,越往后面的優先級越高。

  #right:右結合指示符。同left一樣會指定優先級。

  program:是語法開始指示符,語法說明文件必須指定program生成式,否則會報錯。

  BNF范式(產生式):每個產生式必須以非終結符開始,以 . 符號結束。產生式中的每個非終結符都可以起別名,方便在語義代碼中使用,別名必須緊跟在非終結符后面,而且要括在小括號中。需要注意的是xbytes不支持,一行多個產生式,因此每行只能寫一個產生式。

  語義代碼:每個產生式的后面可以在大括號中指定產生式的語義代碼。這個大括號要放到產生式最后的 . 點前面。語義代碼只要是C++或者C代碼就可以,沒有其他限制。

  語法說明文件名:因為我寫的語法分析生成器的名字叫xbytes,所以我把語法說明文件的后綴名指定為.x。比如上面計算器的語法說明文件名:calculate.x 。當然這個文件的后綴名是可以隨便起的,即使沒有也沒有關系。

  ACTION.txt:在生成語法分析器的同時,會生成一個名為ACTION.txt的文件。文件中以很友好的方式將語法分析器的動作表打印出來了。可以幫助用戶理解LALR(1)語法分析器的運作過程。

  備注:在xbytes.cpp代碼文件中,包含許多dump_開頭的函數。這些函數可以輸出很多生成分析器過程中的數據。包括Symbol集合、規則集合、First集、Follow集、狀態集和動作表等。

  2.語法分析器使用方式:

在根目錄下直接輸入 make 。編譯xbytes,生成的可執行程序會被移入test目錄中,進入test目錄,然后執行./x calculate.x 就可以生成,簡單計算器的語法分析程序了。使用這個程序的方式是自己寫一個main.cpp文件,文件內容如下:

#include "PARSER.hxx" #include <iostream>int main() {xbytes::parser p;//5 * 3 + 6 / 2 - 8p.eat(INT, 5);p.eat(TIMES, 0);p.eat(INT, 3);p.eat(PLUS, 0);p.eat(INT, 6);p.eat(DIV, 0);p.eat(INT, 2);p.eat(MINUS, 0);p.eat(INT, 8);p.eat(0, 0);return 0; }

使用方式很簡單,首先要自己寫個詞法分析器,來進行詞法分析,然后將詞法分析得到的token一個個的喂給parser就可以了。parser::eat函數的第一個參數是token的類型,第二個參數是token的值。讀取結束后,最后寫入0,就是結束分析。

3.運行結果:

這里計算的是算式?5 * 3 + 6 / 2 - 8 的值。打印的是規約的過程,具體要打印的信息可以自己在語法說明文件的語義代碼中自己定制。

[kiven@localhost test]$ ./XP 5=5 3=3 15=5*3 6=6 2=2 3=6/2 18=15+3 8=8 10=18-8 Result=10

4.代碼:

目前的代碼我只在CentOS下面測試過,其他平臺沒有經過測試。代碼地址:https://github.com/kiven-li/xbytes

  5.展望:

  目前程序也僅僅只是能夠生成語法分析器,但是性能不是很好,實用性也不是很高。后續要優化下程序性能,token要支持自定義結構。

轉載于:https://www.cnblogs.com/kiven-code/p/4477587.html

總結

以上是生活随笔為你收集整理的LALR(1)语法分析生成器--xbytes的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。