使用pyparsing實(shí)現(xiàn)布爾表達(dá)式計(jì)算

語言及語法定義

布爾表達(dá)式包含:邏輯表達(dá)式 and or not斋射,關(guān)系表達(dá)式 >, >=, ==, <=, <

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

簡單的布爾表達(dá)式如下:

我們使用“l(fā)et ?變量定義 ?in ?布爾表達(dá)式 ” 這樣的語句來引入變量的定義育勺,可以在布爾表達(dá)式中引用定義的變量,實(shí)例如下:

在《Oreilly-Getting-Started-with-Pyparsing》一書中罗岖,49頁有一個(gè)邏輯表達(dá)式的BNF定義涧至,如下:

在這個(gè)定義中,定義了邏輯表達(dá)式的優(yōu)先級(jí) not > ?and > or 并且是一個(gè)遞歸的定義桑包,Term的定義包含 可選的 not南蓬,然后是 單個(gè)單詞,字符串(quotedString)哑了,或者括號(hào)括起來的另一個(gè)表達(dá)式赘方。這里and or not 兩邊并不是關(guān)系表達(dá)式贩绕,而是單詞是钥,字符串性锭,是書中的一個(gè)例子逢勾,后面我們會(huì)將其修改為關(guān)系表達(dá)式。

And表達(dá)式的定義為 Term 跟著 可選的 多個(gè)and Term抗悍。布爾表達(dá)式定義為 And 表達(dá)式加上 可選的 多個(gè)or And表達(dá)式岸浑。這樣解析的時(shí)候泼返,a && b || c 出現(xiàn)||的時(shí)候,左右兩邊被解析為and表達(dá)式币叹,&&的兩邊被解析為term表達(dá)式润歉,優(yōu)先級(jí)比較明確。

下圖是使用pyparsing語法定義的 表達(dá)式:

解析的時(shí)候套硼,term 中包含的子表達(dá)式被包含在一個(gè)列表內(nèi)卡辰,多個(gè)并列的and語句包含在一個(gè)列表內(nèi)。

使用pyparsing解析如圖

and or not 邏輯表達(dá)式有優(yōu)先級(jí)邪意,和一元二元區(qū)分,and和or是二元反砌,not是一元雾鬼,pyparsing提供了一個(gè)簡單的操作符優(yōu)先級(jí)的語法定義:如下

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

多個(gè)操作符定義為列表宴树,第一個(gè)元素為定義的邏輯符號(hào)策菜,第二個(gè)元素說明是一元還是二元,第三個(gè)元素是說明操作符是left- or right-associative酒贬。使用操作符優(yōu)先級(jí)定義比較簡潔又憨,效果等同于上一段的pyparsing定義。省略了遞歸定義锭吨,和()操作符的定義蠢莺。

下面是我們定義的關(guān)系表達(dá)式的語法,關(guān)系表達(dá)式中可以使用變量零如,數(shù)值躏将,字符串,支持>,== <,>=, <=.(少了一個(gè)!=)

每個(gè)關(guān)系表達(dá)式封裝在一個(gè)子列表內(nèi)考蕾。BoolTerm 可以是任何一個(gè)關(guān)系表達(dá)式祸憋。使用操作符優(yōu)先級(jí)進(jìn)行定義:

定義let表達(dá)式:原來 in 后面跟著的body,修改為boolexpr肖卧。變量定義中變量的值只能賦值為item蚯窥,上面item定義為變量,數(shù)值塞帐,字符串拦赠,所以在擴(kuò)展環(huán)境中的變量的值的時(shí)候,直接擴(kuò)展壁榕,不需要對(duì)item進(jìn)行解析計(jì)算了矛紫。

解釋執(zhí)行

let的語句執(zhí)行時(shí),對(duì)于變量定義列表牌里,varvalue的值都是直接的值颊咬,直接擴(kuò)展到環(huán)境中去务甥,然后返回boolexp的解析結(jié)果

布爾表達(dá)式,首先是以and 和 or 分割的list喳篇,not 或者 關(guān)系表達(dá)式都被封裝在更深一層的list內(nèi)部敞临,所以頂級(jí)有&& 或者 || 出現(xiàn)的時(shí)候,總是 一個(gè)或者多個(gè) && || 組成的列表麸澜,在列表的1,3,5奇數(shù)位上總是 &&或||挺尿,0,2,4是 關(guān)系表達(dá)式,或者子布爾表達(dá)式炊邦。同一級(jí)的表達(dá)式如果出現(xiàn)多個(gè)||编矾,則計(jì)算每一個(gè)的值,碰到第一個(gè)為真馁害,就返回窄俏,表達(dá)式都執(zhí)行沒有返回,就返回假碘菜。 多個(gè)&&時(shí)凹蜈,碰到第一個(gè)為假就返回,多個(gè)表達(dá)式計(jì)算完成沒有返回忍啸,就返回真仰坦。

如果是not表達(dá)式,則exp的第一個(gè)字符是not 计雌!悄晃,直接返回 第二個(gè)元素的反值。not表達(dá)式解析為一個(gè)獨(dú)立的list白粉,所以元素為2传泊,后面跟著not的對(duì)象。

剩余的就是計(jì)算關(guān)系表達(dá)式的值了:關(guān)系表達(dá)式都是有3個(gè)元素的鸭巴,所以解析出來的list結(jié)果眷细,每一個(gè)list都是至少有2個(gè)元素的,所以下面直接通過索引判斷l(xiāng)ist的取值鹃祖,并不會(huì)越界溪椎。

關(guān)系表達(dá)式的解釋:關(guān)系表達(dá)式都是二元的,所以取值的時(shí)候只要取出0,2,的值即可恬口,1號(hào)位的元素肯定是字符串的關(guān)系符號(hào)校读。0和2號(hào)位,如果不是以“開頭的字符串說明它是一個(gè)變量祖能,這里有個(gè)注意的地方歉秫,pyparsing解析出來的字符串,如果不設(shè)置setParseAction時(shí)养铸,removeQuotes解析出來的結(jié)果是帶引號(hào)的雁芙,這里我們通過引號(hào)來區(qū)分其實(shí)字符串類型還是變量類型轧膘。變量和字符串的類型區(qū)分,后續(xù)會(huì)用其他方法進(jìn)行區(qū)分兔甘。

真正解釋關(guān)系表達(dá)式的時(shí)候谎碍,是將每個(gè)關(guān)系表達(dá)式轉(zhuǎn)換成字符串,然后調(diào)用eval直接當(dāng)成python語言進(jìn)行計(jì)算洞焙。如果關(guān)系表達(dá)式中包含變量的時(shí)候蟆淀,提前將其的值從環(huán)境中查找出來 apply_env。然后再組成字符串澡匪。

遺留問題:只通過解析出來的list元素值熔任,不太好區(qū)分 變量 和 字符串 的定義∠沈龋可以通過設(shè)置setResultsName別名來區(qū)分笋敞,但是效果不是很好。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末荠瘪,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子赛惩,更是在濱河造成了極大的恐慌哀墓,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件喷兼,死亡現(xiàn)場(chǎng)離奇詭異篮绰,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)季惯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門吠各,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人勉抓,你說我怎么就攤上這事贾漏。” “怎么了藕筋?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵纵散,是天一觀的道長。 經(jīng)常有香客問我隐圾,道長伍掀,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任暇藏,我火速辦了婚禮蜜笤,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘盐碱。我一直安慰自己把兔,他們只是感情好沪伙,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著垛贤,像睡著了一般焰坪。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上聘惦,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天某饰,我揣著相機(jī)與錄音,去河邊找鬼善绎。 笑死黔漂,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的禀酱。 我是一名探鬼主播炬守,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼剂跟!你這毒婦竟也來了减途?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤曹洽,失蹤者是張志新(化名)和其女友劉穎鳍置,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體送淆,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡税产,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了偷崩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片辟拷。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖阐斜,靈堂內(nèi)的尸體忽然破棺而出衫冻,到底是詐尸還是另有隱情,我是刑警寧澤智听,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布羽杰,位于F島的核電站,受9級(jí)特大地震影響到推,放射性物質(zhì)發(fā)生泄漏考赛。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一莉测、第九天 我趴在偏房一處隱蔽的房頂上張望颜骤。 院中可真熱鬧,春花似錦捣卤、人聲如沸忍抽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鸠项。三九已至干跛,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間祟绊,已是汗流浹背楼入。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留牧抽,地道東北人嘉熊。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像扬舒,于是被迫代替她去往敵國和親阐肤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理讲坎,服務(wù)發(fā)現(xiàn)孕惜,斷路器,智...
    卡卡羅2017閱讀 134,659評(píng)論 18 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法晨炕,類相關(guān)的語法诊赊,內(nèi)部類的語法,繼承相關(guān)的語法府瞄,異常的語法,線程的語...
    子非魚_t_閱讀 31,639評(píng)論 18 399
  • 徽笑曰:“元直欲去,自便去了丰榴,何又惹他出來嘔心血也货邓?”司馬徽尋常的一句“笑言”,已經(jīng)料定了此時(shí)還蟄伏在隆中的諸葛亮...
    掌上天下原創(chuàng)閱讀 332評(píng)論 0 0
  • 每一次的遇見 緣分總會(huì)施舍瘋狂 牽手 浪漫 清風(fēng)曾伴隨楊柳飄蕩 每一次的告別 回憶總會(huì)給予難忘 漫步 流浪 陽光溫...
    只如初見無關(guān)風(fēng)月閱讀 108評(píng)論 1 4