使用pyparsing實現布爾表達式計算

語言及語法定義

布爾表達式包含:邏輯表達式 and or not,關系表達式 >, >=, ==, <=, <

源碼位置:https://github.com/wangdxh/eopl3-in-python ? let 文件夾下面 pyand.py

簡單的布爾表達式如下:

我們使用“let ?變量定義 ?in ?布爾表達式 ” 這樣的語句來引入變量的定義,可以在布爾表達式中引用定義的變量,實例如下:

在《Oreilly-Getting-Started-with-Pyparsing》一書中,49頁有一個邏輯表達式的BNF定義,如下:

在這個定義中,定義了邏輯表達式的優先級 not > ?and > or 并且是一個遞歸的定義,Term的定義包含 可選的 not,然后是 單個單詞,字符串(quotedString),或者括號括起來的另一個表達式。這里and or not 兩邊并不是關系表達式,而是單詞,字符串,是書中的一個例子,后面我們會將其修改為關系表達式。

And表達式的定義為 Term 跟著 可選的 多個and Term。布爾表達式定義為 And 表達式加上 可選的 多個or And表達式。這樣解析的時候,a && b || c 出現||的時候,左右兩邊被解析為and表達式,&&的兩邊被解析為term表達式,優先級比較明確。

下圖是使用pyparsing語法定義的 表達式:

解析的時候,term 中包含的子表達式被包含在一個列表內,多個并列的and語句包含在一個列表內。

使用pyparsing解析如圖

and or not 邏輯表達式有優先級,和一元二元區分,and和or是二元,not是一元,pyparsing提供了一個簡單的操作符優先級的語法定義:如下

將Term修改為只有 單詞和字符串的定義,

多個操作符定義為列表,第一個元素為定義的邏輯符號,第二個元素說明是一元還是二元,第三個元素是說明操作符是left- or right-associative。使用操作符優先級定義比較簡潔,效果等同于上一段的pyparsing定義。省略了遞歸定義,和()操作符的定義。

下面是我們定義的關系表達式的語法,關系表達式中可以使用變量,數值,字符串,支持>,== <,>=, <=.(少了一個!=)

每個關系表達式封裝在一個子列表內。BoolTerm 可以是任何一個關系表達式。使用操作符優先級進行定義:

定義let表達式:原來 in 后面跟著的body,修改為boolexpr。變量定義中變量的值只能賦值為item,上面item定義為變量,數值,字符串,所以在擴展環境中的變量的值的時候,直接擴展,不需要對item進行解析計算了。

解釋執行

let的語句執行時,對于變量定義列表,varvalue的值都是直接的值,直接擴展到環境中去,然后返回boolexp的解析結果

布爾表達式,首先是以and 和 or 分割的list,not 或者 關系表達式都被封裝在更深一層的list內部,所以頂級有&& 或者 || 出現的時候,總是 一個或者多個 && || 組成的列表,在列表的1,3,5奇數位上總是 &&或||,0,2,4是 關系表達式,或者子布爾表達式。同一級的表達式如果出現多個||,則計算每一個的值,碰到第一個為真,就返回,表達式都執行沒有返回,就返回假。 多個&&時,碰到第一個為假就返回,多個表達式計算完成沒有返回,就返回真。

如果是not表達式,則exp的第一個字符是not !,直接返回 第二個元素的反值。not表達式解析為一個獨立的list,所以元素為2,后面跟著not的對象。

剩余的就是計算關系表達式的值了:關系表達式都是有3個元素的,所以解析出來的list結果,每一個list都是至少有2個元素的,所以下面直接通過索引判斷list的取值,并不會越界。

關系表達式的解釋:關系表達式都是二元的,所以取值的時候只要取出0,2,的值即可,1號位的元素肯定是字符串的關系符號。0和2號位,如果不是以“開頭的字符串說明它是一個變量,這里有個注意的地方,pyparsing解析出來的字符串,如果不設置setParseAction時,removeQuotes解析出來的結果是帶引號的,這里我們通過引號來區分其實字符串類型還是變量類型。變量和字符串的類型區分,后續會用其他方法進行區分。

真正解釋關系表達式的時候,是將每個關系表達式轉換成字符串,然后調用eval直接當成python語言進行計算。如果關系表達式中包含變量的時候,提前將其的值從環境中查找出來 apply_env。然后再組成字符串。

遺留問題:只通過解析出來的list元素值,不太好區分 變量 和 字符串 的定義。可以通過設置setResultsName別名來區分,但是效果不是很好。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,362評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,577評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,486評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,852評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,600評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,944評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,944評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,108評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,652評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,385評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,616評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,111評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,798評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,205評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,537評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,334評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,570評論 2 379

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,828評論 18 139
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,737評論 18 399
  • 徽笑曰:“元直欲去,自便去了,何又惹他出來嘔心血也?”司馬徽尋常的一句“笑言”,已經料定了此時還蟄伏在隆中的諸葛亮...
    掌上天下原創閱讀 345評論 0 0
  • 每一次的遇見 緣分總會施舍瘋狂 牽手 浪漫 清風曾伴隨楊柳飄蕩 每一次的告別 回憶總會給予難忘 漫步 流浪 陽光溫...
    只如初見無關風月閱讀 111評論 1 4