【问题标题】:pyparsing - how to lookahead for ambiguous grammar (timestamp with/without timezone parse)pyparsing - 如何提前查找不明确的语法(带有/不带时区解析的时间戳)
【发布时间】:2021-07-17 00:39:39
【问题描述】:

我正在尝试使用 pyparsing 来解析 SQL 方言中的一些时间戳类型。

在这个特定的 sql 方言中,我们有两种时间戳类型 - 带时区和不带时区。

没有时区的示例:TIMESTAMP WITHOUT TIME ZONETIMESTAMP(3)TIMESTAMPTIMESTAMP(3) WITHOUT TIME ZONE

带有时区的示例:TIMESTAMP WITH TIME ZONETIMESTAMP(9) WITH TIME ZONE。如您所见,唯一的区别是需要明确定义时区。

很遗憾,以下匹配不适用于 pyparsing:

(RPAR, LPAR, COMMA) = map(Suppress, "(),")
NUMS = Word(nums)

TIMESTAMP = CaselessKeyword("TIMESTAMP") + 
    Optional(RPAR + NUMS + LPAR) + 
    Optional(CaselessKeyword("WITHOUT TIME ZONE"))
TIMESTAMP_WITH_TIMEZONE = CaselessKeyword("TIMESTAMP") + 
    Optional(RPAR + NUMS + LPAR) + 
    CaselessKeyword("WITH TIME ZONE")

GRAMMAR = StringStart() + TIMESTAMP | TIMESTAMP_WITH_TIMEZONE + StringEnd()
GRAMMAR.parseString("TIMESTAMP WITHOUT TIMEZONE") # Works fine
GRAMMAR.parseString("TIMESTAMP WITH TIMEZONE") # fails

失败是:

  File "/.../lib/python3.8/site-packages/pyparsing.py", line 3814, in parseImpl
    raise ParseException(instring, loc, self.errmsg, self)
pyparsing.ParseException: Expected end of text, found 'W'  (at char 10), (line:1, col:11)

我认为错误可能是因为此语法需要 1 级前瞻来解决某事物是否为 TIMESTAMP WITH TIMESTAMPTIMESTAMP WITHOUT TIMESTAMP。当它无法匹配WITH TIMESTAMP 时,它使用TIMESTAMP 并结束(显然失败的原因不是字符串的结尾)。在这种情况下我该怎么办? pyparsing 是否有前瞻能力让我解决这个问题?

【问题讨论】:

    标签: python parsing lexer pyparsing


    【解决方案1】:

    您还需要在内部“|”周围使用括号选择:

    >>> expr = pp.Literal("a") + pp.Literal("b") | pp.Literal("c") + pp.Literal("d")
    >>> expr
    {{"a" "b"} | {"c" "d"}}
    

    应该是:

    GRAMMAR = StringStart() + (TIMESTAMP_WITH_TIMEZONE | TIMESTAMP) + StringEnd()
    

    【讨论】:

    • 啊,明白了。我的代码中有这个(为了问题的可读性而进行了简化)。谢谢你抓住这个!也感谢你制作了这么棒的图书馆 :)
    【解决方案2】:

    一个规则比另一个更具体,因为它不涉及 Optional 关键字。连词是有序的,因此我们必须将语法定义为:

    GRAMMAR = ... + TIMESTAMP_WITH_TIMEZONE | TIMESTAMP + ...
    

    相反。我试过 FollowedBy 但效果不太好。

    【讨论】:

      猜你喜欢
      • 2021-09-24
      • 1970-01-01
      • 2015-08-03
      • 2021-09-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-04
      • 2018-09-10
      相关资源
      最近更新 更多