python - pyPEG - 由 `flag()` 函数识别的数据被 `compose()` 函数错误地返回

标签 python python-3.x peg pypeg

我处于需要解析旧格式的情况。我想做的是编写一个解析器来识别格式并将其转换为更易于使用的对象。

我设法解析了输入,问题是当我想将它转换回字符串时。总结一下:当我将 parse() 的结果作为参数传递给我的 compose() 方法时,它没有返回正确的字符串。

这是一个输出和源代码。关于 Hook ,我是初学者,我有什么误解吗?请注意,我的初始字符串中有 (126000-147600,3);,而在组合字符串中,它前面带有 -

输出:

********************************************************************************
-t gmt+1 -n GB_EN -p '39600-61200,0; (126000-147600,3); -(212400-234000,5); 298800; (320400); 385200-406800,0; 471600-493200,0; 558000-579600,0'
********************************************************************************
gmt+1 GB_EN
********************************************************************************
[{'end': '61200', 'interval': '0', 'start': '39600'},
 {'end': '147600', 'interval': '3', 'start': '126000'},
 {'end': '234000', 'interval': '5', 'inverted': True, 'start': '212400'},
 {'start': '298800'},
 {'start': '320400'},
 {'end': '406800', 'interval': '0', 'start': '385200'},
 {'end': '493200', 'interval': '0', 'start': '471600'},
 {'end': '579600', 'interval': '0', 'start': '558000'}]
-t gmt+1 -n GB_EN -p '39600-61200,0; -(126000-147600,3); -(212400-234000,5); 298800; -(320400); 385200-406800,0; 471600-493200,0; 558000-579600,0'

Python 源代码:

from pypeg2 import *

from pprint import pprint

Timezone = re.compile(r"(?i)gmt[\+\-]\d")
TimeValue = re.compile(r"[\d]+")

class ObjectSerializerMixin(object):

    def get_as_object(self):
        obj = {}

        for attr in ['start', 'end', 'interval', 'inverted']:
            if getattr(self, attr, None):
                obj[attr] = getattr(self, attr)

        return obj

class TimeFixed(str, ObjectSerializerMixin):
    grammar = attr('start', TimeValue)

class TimePeriod(Namespace, ObjectSerializerMixin):
    grammar = attr('start', TimeValue), '-', attr('end', TimeValue), ',', attr('interval', TimeValue)

class TimePeriodWrapped(Namespace, ObjectSerializerMixin):
    grammar = flag("inverted", '-'), "(", attr('start', TimeValue), '-', attr('end', TimeValue), ',', attr('interval', TimeValue), ")"

class TimeFixedWrapped(Namespace, ObjectSerializerMixin):
    grammar = flag("inverted", '-'), "(", attr('start', TimeValue), ")"


class TimeList(List):
    grammar = csl([TimePeriod, TimeFixed, TimePeriodWrapped, TimeFixedWrapped], separator=";")

    def __str__(self):
        for a in self:
            print(a.get_as_object())
        return ''

class AlertExpression(List):
    grammar = '-t', blank, attr('timezone', Timezone), blank, '-n', blank, attr('locale'), blank, "-p", optional(blank),  "'", attr('timelist', TimeList), "'"

    def get_time_objects(self):
        for item in self.timelist:
            yield item.get_as_object()

    def __str__(self):
        return '{} {}'.format(self.timezone, self.locale)


if __name__ == '__main__':

    s="""-t gmt+1 -n GB_EN -p '39600-61200,0; (126000-147600,3); -(212400-234000,5); 298800; (320400); 385200-406800,0; 471600-493200,0; 558000-579600,0'"""

    p = parse(s, AlertExpression)

    print("*"*80)
    print(s)
    print("*"*80)
    print(p)
    print("*"*80)
    pprint(list(p.get_time_objects()))

    print(compose(p))

最佳答案

我很确定这是 pypeg2

中的错误

您可以使用 pypeg2 示例的简化版本来验证这一点 given here但使用与您正在使用的值相似的值:

>>>from pypeg2 import *
>>> class AddNegation:
...     grammar = flag("inverted",'-'), blank, "(1000-5000,3)"
...
>>> t = AddNegation()
>>> t.inverted = False
>>> compose(t)
'- (1000-5000,3)'
>>> t.inverted = True
>>> compose(t)
'- (1000-5000,3)'

这用一个最小的例子证明了标志变量(inverted)的值对合成没有影响。正如您自己发现的那样,您的parse 正在按您希望的方式工作。

我快速浏览了代码和 this is where the compose is .该模块全部写在一个 __init__.py 文件中,这个函数是递归的。据我所知,问题是当标志为 False 时,- 对象仍作为 str 传递到 compose(在递归的底层)输入并简单地添加到组成的字符串中 here .

更新 将 bug 隔离到 this line (1406),它错误地解压了 flag 属性并将字符串 '-' 发送回 compose() 并将其附加到具有类型的属性的任何值 bool

部分解决方法是用 text.append(self.compose(thing, g)) 替换该行,类似于上面的子句(因此 Attribute 类型被处理与它们从元组中解压缩后通常的情况相同),但您随后点击 this bug其中可选属性(标志只是 Attribute 类型的一种特殊情况)在对象中缺失时未正确组合。

作为那个的解决方法,您可以转到同一文件的第 1350 行并替换

        if grammar.subtype == "Flag":
            if getattr(thing, grammar.name):
                result = self.compose(thing, grammar.thing, attr_of=thing)
            else:
                result = terminal_indent()

        if grammar.subtype == "Flag":
            try:
                if getattr(thing, grammar.name):
                    result = self.compose(thing, grammar.thing, attr_of=thing)
                else:
                    result = terminal_indent()
            except AttributeError:
                #if attribute error missing, insert nothing
                result = terminal_indent()

我不确定这是一个完全可靠的修复程序,但它是一个能让你继续前进的解决方法

输出

将这两个解决方法/修复应用于 pypeg2 模块文件后,您从 print(compose(p)) 获得的输出是

-t gmt+1 -n GB_EN -p '39600-61200,0; (126000-147600,3); -(212400-234000,5); 298800; (320400); 385200-406800,0; 471600-493200,0; 558000-579600,0'

根据需要,您可以继续使用 pypeg2 模块。

关于python - pyPEG - 由 `flag()` 函数识别的数据被 `compose()` 函数错误地返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31187774/

相关文章:

python - 我对 Project Euler 71 的逻辑有什么问题?

python - 如何处理 PEG 语法中的负数?

python - pip 忽略 setup.py 中的dependency_links

python - 当我尝试移动 Pygame 时,玩家回到初始位置

Python:如何将多个 Sprite 合并为一个并保存图像?

python - 解析一个或多个具有有用错误的表达式

python - 解析表达式语法中的转义字符串

python - 在 scipy 中整合多维积分

python - 使用 CR/LF 对使用正则表达式拒绝匹配

python-3.x - 我怎样才能在Python中测试wald?