前端編譯原理 簡述-jison

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

編譯原理-Parser

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

      編譯過程份成2個步驟:前端

      1.詞法分析java

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

        「437+734」    =>  NUM PLUS NUMreact

 

     2.語法分析git

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

        文法 E => NUM PLUS NUM  => sum(437, 734);正則表達式

      這個編譯代碼的程序咱們叫作解析器,分析器,Parserexpress

解析器生成器 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遍從來解決這個問題可能會更好一些。

相關文章
相關標籤/搜索