簡易語言

          數字溝通

           

          用yecc(erlang)寫一個json解析器

            昨天寫了個json的解析器。其實yecc早看過了,只是那時對自己要求太高,想一下子寫個小語言。然后大腦就陷入混亂... 后來注意力轉移了。就不那么急著去開發(fā)些難道大的。今天回來一看,覺得都理解了,實踐一下,發(fā)現(xiàn)沒人寫json的,太好了。于是就在紙上寫了一下。晚上沒事都敲掉計算機里試試。果然很好用。廢話就不多說了,不專業(yè)的我在readme里面已經寫了不少廢話了。主要也不知道git有沒規(guī)范約束readme不能寫廢話。其實被google騙了一下,有人寫過json的erlang解析,每次我搜yrl,它就主動搜url文件。還要點一下堅持搜索才行??纯磆ttps://github.com/jchris/erlang-json-eep-parser/downloads這上面就是一個解析器,還好我們寫的不是太像,他寫的更精細一點。我寫的更容易使用上手。我寫的就到這下載吧https://github.com/yangyusong/erlang_json_parser。

            接著就是講講內容了,大學學過編譯原理就很容易理解這其中的內容。yrl文件就是erlang中的滿足LALR-1規(guī)范的解析生成器,相似于yacc。會有很多文章做解釋,這里不詳述。yrl文件或yacc中的.y這類文件就是給我們寫編譯規(guī)則用的,我們寫好一個推理機制,按照規(guī)范分解成4部分,放到這一個文件中,那么yecc就可以給我們生成一個符合這個推理規(guī)則的解析器,當然這里就是生成.erl的源文件給我們使用,其中會有parse作為默認方法提供給我們解析我們的字符串。

            yrl文件中一共有四部分,其實三部分分別用Nonterminals Terminals Rootsymbol關鍵字來標識,意義很明顯,非終結符,終結符,起始符(這個忘了怎么翻譯)。要解釋一下也行,一個更好的理解方式就是,非終結符可以在推理符號(->)的左邊和右邊,相當于函數作用,最終分析為終結符的組合。終結符只能在推理符號(->)的右邊。意義就是一個符號系統(tǒng)的基本集合。 Rootsymbol是其中一個非終結符,作為推理的起始點。用一棵解析樹來表示的話,Rootsymbol就是根節(jié)點。Nonterminals就是樹枝。Terminals就是樹葉。任何一個符合此推理規(guī)則的字符串都可以用這樣一棵解析樹表示出來(我就不畫了)。

            除了上面說的三部分就剩下最重要的部分了:推理規(guī)則。其實這四部分都是列表,只不過Rootsymbol這個表只有一個元素。規(guī)則列表有多條,通常每行一條規(guī)則,和erlang一樣用.結束一條規(guī)則。
          終結符用單引號引起,冒號后面是我們解析后的erlang表達式。$1,$2,$3這種相似正則表達式規(guī)則,也說一下吧,就是對冒號左邊的元素作為列表并從1計數。再搞不懂就發(fā)郵局問吧,呵呵。

            那么這樣的一個規(guī)則列表就很好建立了,其實這個過程還是有很多規(guī)則可以遵循的,其中這里遵循了左遞歸,終結字符先出現(xiàn)的規(guī)則優(yōu)先表達這兩條規(guī)則。更多,你還可以畫個有限狀態(tài)機,做一下分析,化解,做成閉包,某些運算還要考慮優(yōu)先級之類。當然這里這樣小的結構基本是最優(yōu)了,沒什么化解的必要。

          代碼附上
          Nonterminals list object kv_list v_list kv k v. % 7

          Terminals ',' ':' 'element' '[' ']' '{' '}'. % 7

          Rootsymbol object.

          object -> '{' '}' : {}.
          object -> '{' kv_list '}' : { '$2' }.


          kv_list -> kv ',' kv_list : '$1' , '$3'.
          kv_list -> kv : '$1'.

          kv -> k ':' v : {'$1', '$3'}.

          k -> 'element' : '$1'.

          v -> 'element' : '$1'.
          v -> list : '$1'.
          v -> object : '$1'.

          list -> '[' ']' : [].
          list -> '[' v_list ']' : [ '$2' ].

          v_list -> v ',' v_list : '$1' , '$3'.
          v_list -> v.

            其中object,list就是json中最基本的結構。kv_list就是剝離大括號后的鍵值對列表。v_list是剝離中括號的列表。

            再講講這個解析器的使用吧,json_parser就是yrl文件生成的解析器了,我們就用這個解析器來做解析。文件use_json_parser對json_parser的使用做了一個包裝,那就是parser/1函數了,我們給它傳入json字符串就返回解析后的erlang列表。例如我們輸入use_json_parser:parser("{a, b, c}").就會返回[{'{',1},
                                                  {atom,1,a},
                                                  {',',1},
                                                  {atom,1,b},
                                                  {',',1},
                                                  {atom,1,c},
                                                  {'}',1},
                                                  {'$end',999}]。
            這個文件還提供一個測試函數了unit_test_()。為了方便大家,我還是講講測試方法吧。在命令行輸入
          cd erlang_json_parser
          erl -pa ./ebin/ -eval "make:all([{d, 'EUNIT'},{outdir, \"./ebin/\"}, debug_info]) ,eunit:test(\"./ebin\",[]),init:stop()"

            參考更多的解析器制作,可以參考erlang官網提供的計算表達式解析,list解析。也可以從其他網站搜到html,xml等的解析,當然如果你看得多一點還會看到aleppo,erlydtl這類的工程。希望更多的人們投入到這些更有意思的開發(fā)中。下次再寫yecc,就不寫這么簡單的了。哈哈。不要期待在下一篇里出現(xiàn)哦。


          一種更好的態(tài)度,更好的學習、思維方式。它會是網絡極佳的生存方式,你喜歡就對。

          posted on 2011-12-30 23:28 yangyusong 閱讀(3470) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發(fā)表評論。


          網站導航:
           

          導航

          統(tǒng)計

          常用鏈接

          留言簿(3)

          隨筆分類

          隨筆檔案

          文章分類

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 壤塘县| 旌德县| 邯郸县| 桐庐县| 尼勒克县| 菏泽市| 军事| 延边| 文安县| 邯郸市| 玛沁县| 剑河县| 和平县| 漯河市| 无锡市| 丰原市| 禄丰县| 桓台县| 永宁县| 监利县| 景东| 崇阳县| 育儿| 高青县| 湟中县| 上栗县| 江口县| 长治县| 安义县| 龙里县| 泊头市| 阜宁县| 湖口县| 宁陵县| 凤翔县| 潞西市| 汨罗市| 兴国县| 玉环县| 镇赉县| 家居|