[英]Getting True or False value for elements in a list from a dictionary
假設我們有以下變量:
my_list = ["door_open", "AND", "dog_gone"],
my_dict ={"door_open" : "false", "dog_gone" : "true", "dog_asleep" : "true"})
(請注意,列表和字典可以更長或更短,並且仍然可以使用)。 我們希望能夠通過以下功能運行它:
def and_function(arg1, arg2):
if arg1=="true" and arg2=="true":
return "true"
else:
return "false"
我們如何編寫一個函數,該函數首先將檢查列表中的元素是“ true”還是“ false”,然后通過“ and_function”運行它。 這看起來應該是這樣的:
def interpret(my_list, my_dict):
#DO SOMETHING SO WE GET THE "true" OR "false" VALUE FOR ELEMENTS
.
.
.
if "AND" in my_list:
return and_function(ture_or_false, false_or_true)
"false"
這看起來像遞歸結構(因為操作數也可能是表達式)。 在這種情況下,編寫解析器是一個好主意。 但是,自己編寫解析器通常容易出錯且麻煩。 因此,我們不會自己編寫解析器,而是使用可以指定規格的工具,然后生成解析器本身。
這些工具之一是例如PLY 。 一個簡單的解析器(我將不實現完整的解析器,但思路應該很清楚),如下所示。
首先,我們需要實現一個分析令牌的詞法分析器:
# lexer.py
import ply.lex as lex
tokens = (
'AND',
'OR',
'IDENTIFIER',
)
t_AND = r'AND'
t_OR = r'OR'
def t_IDENTIFIER(t):
r'[a-z_]+'
return t
t_ignore = ' \t\r\n'
lexer = lex.lex()
上面的代碼將導致一個詞法分析器 (也稱為標記器 ;不是解析器)。 詞法分析器將字符串轉換為令牌列表。 這里有三個可能的標記: AND
, OR
和IDENTIFIER
。 AND
僅匹配'AND'
(大寫), OR
匹配“ OR”(大寫), IDENTIFIER
匹配任何由小寫字符和下划線組成的序列。
因此,如果我們解析一個字符串,則會得到:
>>> from lexer import lexer
>>> lexer.input('foo AND bar')
>>> lexer.token()
LexToken(IDENTIFIER,'foo',1,0)
>>> lexer.token()
LexToken(AND,'AND',1,4)
>>> lexer.token()
LexToken(IDENTIFIER,'bar',1,8)
>>> lexer.token()
>>>
現在,我們可以將令牌列表變成一個包含葉子(標識符)和索引節點 (操作數)的“樹”:
# parser.py
import ply.yacc as yacc
class Identifier:
def __init__(self, name):
self.name = name
def resolve(self, dictionary):
return dictionary[self.name]
class Node:
def __init__(self, left, right):
self.left = left
self.right = right
def resolve(self, dictionary):
return self.func(self.left.resolve(dictionary), self.right.resolve(dictionary))
def func(self, left, right):
return None
class AndNode(Node):
def func(self, left, right):
return left and right
class OrNode(Node):
def func(self, left, right):
return left or right
from lexer import tokens
def p_expression_or(p):
'expression : and_exp OR expression'
p[0] = OrNode(p[1], p[3])
def p_expression_or_no(p):
'expression : and_exp'
p[0] = p[1]
def p_expression_and(p):
'and_exp : ident AND and_exp'
p[0] = AndNode(p[1], p[3])
def p_expression_and_no(p):
'and_exp : ident'
p[0] = p[1]
def p_ident(p):
'ident : IDENTIFIER'
p[0] = Identifier(p[1])
parser = yacc.yacc()
在這里,我們指定了一組生產規則以及處理該生產規則的邏輯。 我們指定一個expression
為and_expr
后跟一個OR
然后是另一個expression
(第一個函數),或者只是一個and_expr
(第二個函數)。 因此,我們建立了語言的語法。 在函數中,我們以樹形方式構造了AndNode
, OrNode
和Identifier
對象。
現在我們可以將字符串解析為這樣的樹:
from parser import parser
tree = parser.parse('foo AND bar')
現在有一個像這樣的字典:
data = {'foo': True, 'bar': True}
我們可以調用tree
的.resolve(..)
方法,並獲取結果:
>>> tree.resolve({'foo': True, 'bar': True})
True
>>> tree.resolve({'foo': True, 'bar': False})
False
>>> tree.resolve({'foo': False, 'bar': False})
False
如果您閱讀該文檔,則將找到將括號和其他函數(一元運算符,二進制運算符,函數)等包括到詞法分析器,解析器中並對其進行評估的方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.