前端編譯原理 簡述-jison


最近幾年的項目技術難點都和編譯原理,抽象語法樹,代碼編輯器 有關系。現在時間有點空,先從基礎了解起來,讓有些交互和提示能夠更智能些。

編譯原理-Parser

    編譯原理 其實就是 讓計算機懂的 “437+734” 這樣的字符串編程 sum 437, 734 計算機懂得的機器碼。實際場景中可能是從一種高級語言編譯成一種低級語言。

      編譯過程份成2個步驟:

      1.詞法分析

        詞法分析就是 通過定義的正則表達式,把輸入的字符串變成一個個標記(token)。

        “437+734”    =>  NUM PLUS NUM

 

     2.語法分析

        根據定於的語法,把上邊的token通過移進/歸約自動機,一步步的移入,規約,變成抽象語法樹,最終產生結構。

        文法 E => NUM PLUS NUM  => sum(437, 734);

      這個編譯代碼的程序我們叫做解析器,分析器,Parser

解析器生成器 parser generator

     在實際情況中,有專門用來生成Parser的程序,解析器生成器。

     前端的js語法分析器生成器,還是瞞多的 https://tomassetti.me/parsing-in-javascript/,不同的語法生成器支持的文法也有差別。

JISON介紹     

    項目中用到的是jison庫,這個庫支持(lr0, slr, lr1, ll, lalr)文法。一般我們程序中使用的是lalr文法。

    可以通過debugger的方式去理解移入規約的過,和jison的使用。http://nolanlawson.github.io/jison-debugger/

     1.jison 文法格式 grammar

         使用起來很簡單,官網的文檔也比較詳細, http://zaa.ch/jison/docs/。定義jison文件,通過 node 命令 "jison  文件"生成Parser的js文件;

         jison是bison在js端的實現,但是也不是完全實現了相關的功能。

        從http://nolanlawson.github.io/jison-debugger/上就能看到下面的一些文法格式

/* 詞法文法 */
%lex

/* 選項設置 flex 最長匹配原則 case-insensitive 忽略大小寫 */
%options flex case-insensitive

%%

\s+                   /* skip whitespace */
[0-9]+("."[0-9]+)?\b  return 'NUMBER'
<<EOF>>               return 'EOF'

/lex

/*操作符優先級設置*/

%left '+' '-'
%left '*' '/'

/*語法開始的非終結符號*/

%start expressions

%% 
/* 詞法 */
expressions
    : e EOF
        {return $1;}
    ;

  試了下http://dinosaur.compilertools.net/bison/bison_10.html#SEC84,bison文檔上面的這個文法不支持,所以使用的時候自己要看着處理

    2.jison的輸出

       jison生成的Parser的輸出其實是文法自己定義的,可以是一個結果值,可以是ast樹,也可以是用戶自己在文法上面定義的結果

    3.Parser.js

      其實這個可以直接研究下源代碼,源代碼看起來雖然有些難度,主要是語法分析的邏輯,移入規則邏輯,標示符,終結符,非終結符號等等相關的定義,其他詞法的邏輯。

      和實際使用中的有的一些變量還是比較容易看懂,或者說debug一下大概就知道有哪些參數了。

     

     文法定義中的參數

     yy: 這個屬性是用戶自己定義的,在編譯期間共享,這樣也是代碼更加靈活。

      yytext: 當前觸發規約文法的文本(不是整個文法的文本,一般只有最后一個符號的文本)
      yyleng: yytext的長度
      yylineno: yytext所在的行號
      yystate: 當前規約的文法的標示
      $$:表示當前的文法規約后的值
      $n:  對應文法的對應部分的值
     
      對象提供的擴展
      this.parseError 錯誤處理方法
      this.yy 共享對象

    4.誤區

       在使用中,會有一些誤區存在,特別是移入規約的順序,可能和我們平時看代碼存在差異。比如說上面的例子。

   

       我們需要在RULE{expr}中的expr內容 有另外一種含義,

       但是實際情況的執行順序其實是先 expr規則規約,才是 RULE{expr}規則規約,所以在進行expr規約的時候並不知道它是在RULE{}里面的,所以我們通過Parser生成ast,再通過ast遍歷來解決這個問題可能會更好一些。

      

         


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM