Python的pyparsing:实现语法来解析逻辑AND表达式

Python的pyparsing:实现语法来解析逻辑AND表达式,第1张

概述我试图解析和评估表达式,给我作为文件的输入,形式:var[3] = 0 and var[2] = 1 var[0] = 1 and var[2] = 0 and var[3] = 1 ... (实际上我也允许“多位访问”(即var [X:Y])但是现在让我们忽略它...)其中var是整数,[]表示位访问.例如,对于var = 0x9,上面的第一个表达式应该被

我试图解析和评估表达式,给我作为文件的输入,形式:

var[3] = 0 and var[2] = 1var[0] = 1 and var[2] = 0 and var[3] = 1...

(实际上我也允许“多位访问”(即var [X:Y])但是现在让我们忽略它…)
其中var是整数,[]表示位访问.
例如,对于var = 0x9,上面的第一个表达式应该被计算为False,而第二个表达式应该被计算为True,因为0x9 = b1001.
和=是我允许的唯一二元运算符,对于=运算符,左 *** 作数总是var [X],右 *** 作数总是一个数字.
我试着环顾四周,发现这可以通过Python的pyparsing来实现,但是在尝试实现它时遇到了一些困难.
这是我到目前为止所尝试的,大致基于this example(这是here提供的众多示例之一):

#!/usr/bin/env pythonfrom pyparsing import Word,Alphas,nums,infixNotation,opAssocclass BoolAnd():    def __init__(self,pattern):        self.args = pattern[0][0::2]    def __bool__(self):        return all(bool(a) for a in self.args)    __nonzero__ = __bool__class BoolEqual():    def __init__(self,pattern):        self.bit_offset = int(pattern[0][1])        self.value = int(pattern[0][-1])    def __bool__(self):        return True if (0xf >> self.bit_offset) & 0x1 == self.value else False # for Now,let's assume var == 0xf    __nonzero__ = __bool__variable_name   = 'var'bit_access      = variable_name + '[' + Word(nums) + ']'multibit_access = variable_name + '[' + Word(nums) + ':' + Word(nums) + ']'value = Word(nums)operand = bit_access | multibit_access | valueExpression = infixNotation(operand,[    ('=',2,opAssoc.left,BoolEqual),('AND',BoolAnd),])p = Expression.parseString('var[3] = 1 AND var[1] = 0',True)print 'SUCCESS' if bool(p) else 'FAIL'

我有三个需要帮助的问题.

>对于var [X:Y] = Z形式的多位访问,我该如何强制执行:
一个. X> ÿ
湾Z< 2 ^ {X - Y 1}
我假设这不能由语法本身强制执行(例如,对于形式var [X] = Y的单位访问,我可以通过语法强制执行Y将为0或1,这将导致如果Y!= 0/1,表达式.parseString()失败,异常.
>最重要的是:为什么它总是打印SUCCESS?我究竟做错了什么?
对于输入var [3] = 1 AND var [1] = 0,它应该是打印失败(你可以在我的例子中看到我硬编码var为0xf,所以var [3] = 1是True但是var [1] = 0为假).
>这让我想到了第三个问题:var不是BoolEqual的类成员,也不是全局的…有没有办法以某种方式将它发送到BoolEqual的__init__函数?最佳答案在解决问题之前,我建议对语法进行一些小的改动,主要是包含结果名称.添加这些名称将使您的结果代码更加清晰和健壮.我还使用了pyparsing_common命名空间类中最近的pyparsing版本中添加的一些表达式:

from pyparsing import pyparsing_commonvariable_name   = pyparsing_common.IDentifIEr.copy()integer = pyparsing_common.integer.copy()bit_access      = variable_name('name') + '[' + integer('bit') + ']'multibit_access = variable_name('name') + '[' + integer('start_bit') + ':' + integer('end_bit') + ']'

第1a部分:在“var [X:Y]”中强制执行有效值

这种工作最好使用解析 *** 作和条件来完成.解析 *** 作是解析时回调,您可以将其附加到您的pyparsing表达式,以修改,增强,过滤结果或在验证规则失败时引发异常.使用以下方法附加这些:

expr.addParseAction(parse_action_fn)

并且parse_action_fn可以具有以下任何签名:

def parse_action_fn(parse_string,parse_location,matched_tokens):def parse_action_fn(parse_location,matched_tokens):def parse_action_fn(matched_tokens):def parse_action_fn():

(详见https://pythonhosted.org/pyparsing/pyparsing.ParserElement-class.html#addParseActio)n)

解析 *** 作可以返回None,返回新标记,修改给定标记或引发异常.

如果所有解析 *** 作都根据输入标记评估某些条件,则可以将其写为返回True或False的简单函数,如果返回False,则pyparsing将引发异常.在您的情况下,您的第一个验证规则可以实现为:

def valIDate_multibit(tokens):    return tokens.end_bit > tokens.start_bitmultibit_access.addCondition(valIDate_multibit,message="start bit must be less than end bit",fatal=True)

或者甚至只是作为Python lambda函数:

multibit_access.addCondition(lambda t: t.end_bit > t.start_bit,fatal=True)

现在你可以尝试这个:

multibit_access.parseString("var[3:0]")

你会得到这个例外:

pyparsing.ParseFatalException: start bit must be less than end bit (at char 0),(line:1,col:1)

第1b部分:在“var [X:Y] = Z”中强制执行有效值

您的第二个验证规则不仅处理var位范围,还处理它与之比较的值.这将需要附加到完整BoolEqual的解析 *** 作.我们可以把它放在BoolEqual的__init__方法中,但我更喜欢在可能的情况下分离独立的函数.由于我们将通过附加到infixNotation级别来添加我们的验证,并且infixNotation仅接受解析 *** 作,因此我们需要将您的第二个验证规则编写为引发异常的解析 *** 作. (我们还将使用最近才在pyparsing 2.2.0中发布的新功能,在infixNotation中的某个级别附加多个解析 *** 作.)

以下是我们希望执行的验证:

>如果是单位表达式,则值必须为0或1
>如果多位表达式var [X:Y],则值必须<< 2 **(Y-X 1)

def valIDate_equality_args(tokens):    tokens = tokens[0]    z = tokens[-1]    if 'bit' in tokens:        if z not in (0,1):            raise ParseFatalException("invalID equality value - must be 0 or 1")    else:        x = tokens.start_bit        y = tokens.end_bit        if not z < 2**(y - x + 1):            raise ParseFatalException("invalID equality value")

我们使用以下命令将此解析 *** 作附加到infixNotation:

Expression = infixNotation(operand,(valIDate_equality_args,BoolEqual)),])

第3部分:支持除0xf之外的其他var名称和值

要处理各种名称的变量,可以向BoolEqual添加类级别的dict:

class BoolEqual():    var_names = {}

并提前设定:

BoolEqual.var_names['var'] = 0xf

然后将__bool__方法实现为:

return(self.var_names [self.var_name]>> self.bit_offset)& 0x1 == self.value

(这需要扩展到支持多位,但总体思路是一样的.) 总结

以上是内存溢出为你收集整理的Python的pyparsing:实现语法来解析逻辑AND表达式全部内容,希望文章能够帮你解决Python的pyparsing:实现语法来解析逻辑AND表达式所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1206174.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-04
下一篇 2022-06-04

发表评论

登录后才能评论

评论列表(0条)

保存