【F#從入門到實(shí)戰(zhàn)】11. F#庫FParsec入門

      網(wǎng)友投稿 821 2025-04-01

      歡迎大家來到【F#從入門到實(shí)戰(zhàn)】,在這里我將分享關(guān)于F#編程語言的系列文章,帶大家一起去學(xué)習(xí)和成長,并探索函數(shù)編程語言F#這個(gè)有趣的世界。所有文章都會(huì)結(jié)合示例代碼和筆者的經(jīng)驗(yàn)進(jìn)行講解,真心想把十余年的IT經(jīng)驗(yàn)分享給大家,希望對(duì)您有所幫助,文章中也定有不足之處,請(qǐng)海涵!本系統(tǒng)文章將從F#基本語法入手,逐步通過自定義類型來實(shí)現(xiàn)數(shù)學(xué)表達(dá)式的各種常見解析操作,如對(duì)表達(dá)式進(jìn)行求值、化簡、展開、求導(dǎo)和求積分等。此系統(tǒng)博文也是了解和實(shí)現(xiàn)一個(gè)簡易的計(jì)算機(jī)代數(shù)系統(tǒng)的基礎(chǔ)。

      下面給出【F#從入門到實(shí)戰(zhàn)】系統(tǒng)專題文章的目錄:

      【F#從入門到實(shí)戰(zhàn)】01. F#語言快速入門

      【F#從入門到實(shí)戰(zhàn)】02. F#數(shù)組常見用法

      【F#從入門到實(shí)戰(zhàn)】03. F#自定義操作符

      【F#從入門到實(shí)戰(zhàn)】04. F#5.0新特征總結(jié)

      【F#從入門到實(shí)戰(zhàn)】05. F#表達(dá)式求值

      【F#從入門到實(shí)戰(zhàn)】06. F#表達(dá)式化簡

      【F#從入門到實(shí)戰(zhàn)】07. F#表達(dá)式展開

      【F#從入門到實(shí)戰(zhàn)】08. F#大整數(shù)階乘

      【F#從入門到實(shí)戰(zhàn)】09. F#表達(dá)式求導(dǎo)

      【F#從入門到實(shí)戰(zhàn)】10. F#表達(dá)式積分

      【F#從入門到實(shí)戰(zhàn)】11. F#庫FParsec入門

      【F#從入門到實(shí)戰(zhàn)】12. F#庫FParsec解析表達(dá)式

      【F#從入門到實(shí)戰(zhàn)】13. F#庫FParsec實(shí)現(xiàn)求導(dǎo)符號(hào)計(jì)算

      【F#從入門到實(shí)戰(zhàn)】14. F#實(shí)現(xiàn)分部積分法

      下面將正式開始本文的介紹:

      FParsec 是一個(gè)F#語言構(gòu)建的解析器組合庫,主要用于解析文本,并結(jié)構(gòu)化輸出,可以為形式語法實(shí)現(xiàn)遞歸下降文本解析器。根據(jù)官網(wǎng)的介紹,F(xiàn)Parsec庫的主要功能包括:

      支持上下文相關(guān)的無限前瞻文法

      自動(dòng)生成、高度可讀的錯(cuò)誤消息

      Unicode 支持

      對(duì)非常大的文件的有效支持

      一個(gè)可嵌入的、運(yùn)行時(shí)可配置的運(yùn)算符優(yōu)先級(jí)解析器組件

      一個(gè)簡單、高效且易于擴(kuò)展的 API

      針對(duì)性能進(jìn)行徹底優(yōu)化的實(shí)現(xiàn)

      全面的文檔

      一個(gè)寬松的開源許可證,源代碼和二進(jìn)制形式的 FParsec 庫是在簡化的 BSD 許可下分發(fā)

      官網(wǎng)為?http://www.quanttec.com/fparsec/ ,可以從官網(wǎng)查看具體的用法。FParsec 源代碼在 GitHub 上可以下載:github.com/stephan-tolksdorf/fparsec

      FParsec 庫的源代碼用 C# 和 F# 編寫的,包含兩個(gè)DLL庫:FParsec.dll和 FParsecCS.dll ,項(xiàng)目需要引用此DLL庫。下面給出一些示例,用來直觀的掌握如何使用這個(gè)解析器庫:

      首先,所有 FParsec 類型和模塊都在FParsec命名空間中聲明。該命名空間包含一些基本類和4個(gè) F# 模塊,即:

      Primitives:包含基本類型定義和解析器組合器

      CharParsers:包含字符、字符串和數(shù)字的解析器,以及將解析器應(yīng)用于輸入流的函數(shù)

      Error:包含用于創(chuàng)建、處理和格式化解析器錯(cuò)誤消息的類型和輔助函數(shù)

      StaticMapping:包含將靜態(tài)鍵值映射編譯為優(yōu)化函數(shù)的函數(shù)

      因此如果要使用open FParsec庫,則應(yīng)該首先引入此庫:

      open FParsec

      首先需要需要根據(jù)解析的對(duì)象,構(gòu)建合適的解析器Parser,當(dāng)然,F(xiàn)Parsec庫中的模塊如 FParsec.Primitives和FParsec.CharParsers模塊中包含了內(nèi)置的解析器,如解析float類型的解析器pfloat,其定義為:

      val pfloat: Parser

      如果要想調(diào)用此解析器,并返回結(jié)果(ParserResult<'Result,unit>),則需要run來進(jìn)行調(diào)用 ,其中的ParserResult定義為:

      type ParserResult<'Result,'UserState>= | Success of 'Result * 'UserState * Position | Failure of string * ParserError * 'UserState

      【F#從入門到實(shí)戰(zhàn)】11. F#庫FParsec入門

      解析器pfloat示例為:

      let f2 = run pfloat "1.25" printfn "%O" f2 //Success: 1.25

      當(dāng)然,為了方便的進(jìn)行測試運(yùn)行,可以構(gòu)建一個(gè)test函數(shù):

      let test p str = match run p str with | Success(value, _, _) -> printfn "OK: %A" value | Failure(err, _, _) -> printfn "Fail: %s" err

      用此test函數(shù)來運(yùn)行pfloat解析器示例,如下所示:

      //解析float類型 test pfloat "1.25" //OK: 1.25 test pfloat "1.25E" //Fail: Error ...

      其中對(duì)文本"1.25E"解析會(huì)出現(xiàn)如下錯(cuò)誤信息:

      Fail: Error in Ln: 1 Col: 6 1.25E ^ Note: The error occurred at the end of the input stream. Expecting: decimal digit

      如果這個(gè)數(shù)值字符中有空字符(如空格)會(huì)解析正確嗎?可以看下面的示例:

      //數(shù)值后面可以有空格字符 test pfloat "1.27 " //OK: 1.27 //數(shù)值前面不可以有空格字符 test pfloat " 1.28" //Fail: Error ..

      下面介紹一下如何從括號(hào)中提取數(shù)值,示例如下:

      //解析string類型,忽略空白 ' ', '\t', '\r' ', '\n' let pstr_ws s = pstring s .>> spaces let pfloat_ws = pfloat .>> spaces //()中間的解析出float let pfloatBetKK = pstr_ws "(" >>. pfloat_ws .>> pstr_ws ")" test pfloatBetKK "(2.6)" //OK: 2.6 test pfloatBetKK "(2.7 )" //OK: 2.7 test pfloatBetKK "( 2.8 ) " //OK: 2.8 test pfloatBetKK " ( 2.9 ) " //Fail: Error... 左括號(hào)有空格

      另外,還可以對(duì)特定括號(hào)中的字符按照分隔符進(jìn)行拆分并解析,具體示例如下:

      let parray = pstr_ws "[" >>. sepBy pfloat_ws (pstr_ws ";") .>> pstr_ws "]" //OK: [1.0; 2.0; 3.0] test parray @"[ 1 ; 2 ; 3 ] "

      有時(shí)候,我們解析字符時(shí),希望跳過特定字符,具體示例如下:

      //spaces >>. 左空白 .>> spaces 右空白 let pfloat_ws2 = spaces >>. pfloat .>> spaces let f s = (skipStringCI "" >>. pfloat_ws2) s test f " 1.0 " //OK:1.0

      上述示例,則跳過字符串,且忽略大小寫,從而提取出1.0

      最后,這個(gè)解析器還可以構(gòu)建更加復(fù)雜的邏輯,比如判斷變量命名是否合法:

      let identifier = let isIdentifierFirstChar c = isLetter c || c = '_' let isIdentifierChar c = isLetter c || isDigit c || c = '_' many1Satisfy2L isIdentifierFirstChar isIdentifierChar "identifier" .>> spaces // 忽略右空白 let id = spaces >>. identifier .>> spaces test id "_name" //OK: "_name" test id " _name "http://OK: "_name" (* Fail: Error in Ln: 1 Col: 1 1_name ^ Expecting: identifier *) test id "1_name "

      由上示例可知,_name是合法的變量名,而1_name以數(shù)字開頭,則不合法。

      面向?qū)ο缶幊?/a>

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:甘特圖項(xiàng)目進(jìn)度管理的要點(diǎn)
      下一篇:微軟淘汰Office 2010入門版:用戶體驗(yàn)糟糕(微軟淘汰ie瀏覽器)
      相關(guān)文章
      亚洲国产福利精品一区二区| 亚洲www在线观看| 亚洲无人区码一二三码区别图片 | 伊人亚洲综合青草青草久热| 亚洲XX00视频| 亚洲高清偷拍一区二区三区 | 亚洲αv在线精品糸列| 亚洲精品乱码久久久久久中文字幕| 亚洲片国产一区一级在线观看| 日韩色视频一区二区三区亚洲| 亚洲AV无码AV男人的天堂不卡| 亚洲国产aⅴ成人精品无吗| 亚洲人成网站在线在线观看| 亚洲乱亚洲乱妇24p| 亚洲国产成人久久精品软件| 亚洲A∨精品一区二区三区下载| 婷婷亚洲综合一区二区| 亚洲av区一区二区三| 亚洲欧洲中文日韩av乱码| 日韩一卡2卡3卡4卡新区亚洲| 亚洲午夜无码久久久久| 黑人精品videos亚洲人| 久久青草亚洲AV无码麻豆| 亚洲av无码国产精品夜色午夜| 亚洲AV永久无码精品成人| 亚洲AV成人一区二区三区AV| 老司机亚洲精品影院无码| 亚洲国产综合在线| 亚洲午夜理论片在线观看| 婷婷国产偷v国产偷v亚洲| 2048亚洲精品国产| 国产成人亚洲综合无码精品 | 亚洲人成色777777老人头| 亚洲a无码综合a国产av中文| 亚洲国产精品日韩专区AV| 亚洲尤码不卡AV麻豆| 亚洲Aⅴ无码专区在线观看q | 亚洲成A人片在线观看中文| 国产自偷亚洲精品页65页| 亚洲av中文无码乱人伦在线r▽ | 亚洲综合男人的天堂色婷婷|