【问题标题】:Trying to parse old syntax in Python尝试在 Python 中解析旧语法
【发布时间】:2021-03-31 07:00:22
【问题描述】:

我们有一个旧应用程序需要迁移到 AWS 中的新框架。在旧的应用程序中,我们曾经有一些基于表达式的语法,用于识别客户端的权限、到期日期等。

我正在尝试将旧语法转换为以逗号分隔的新语法。

我正在尝试使用pyparsing 库来实现这一点,但我觉得我在这里碰壁了。到目前为止,下面的代码给了我list 旧代码的细分,但是当旧代码中有嵌套循环时,我无法解析它。

旧代码

If (LAST_RUN_DATE>=dat('JUL 01, 90'))
    If (pos(con('*',SUB_CODE,'*'),'*ABC*DEF*ASD*WQR*')>=1)
        Calculate Client as 1
    End If
End If

Python 转换

in_string = '''If (LAST_RUN_DATE>=dat('JUL 01, 90'))
    If (pos(con('*',SUB_CODE,'*'),'*ABC*DEF*ASD*WQR*')>=1)
        Calculate Client as 1
    End If
End If'''

from pyparsing import *

#- define basic punctuation and data types
LBRACE,RBRACE,LPAREN,RPAREN,SEMI = map(Suppress,"{}();")

IF = Keyword("If")
END_IF = Keyword("End If")
after_if  = Regex(r'(.*?)\n')

_if = Forward()
#- _if << Group(IF + Group(after_if))
_if << Group(Group(ZeroOrMore(IF)) + Group(ZeroOrMore(after_if)) + Group(ZeroOrMore(END_IF)))

#- parse the sample text
result = _if.parseString(in_string)

#- print out the tokens as a nice indented list using pprint
from pprint import pprint
pprint(result.asList())

### Output
[[['If'],
  ["(LAST_RUN_DATE>=dat('JUL 01, 90'))\n",
   "If (pos(con('*',SUB_CODE,'*'),'*ABC*DEF*ASD*WQR*')>=1)\n",
   'Calculate Client as 1\n',
   'End If\n'],
  ['End If']]]

我已经参考了这个,也期待与这个类似的输出。 Link

【问题讨论】:

    标签: python parsing pyparsing


    【解决方案1】:

    使用 Forward 绝对是在正确的轨道上。你要去的地方是你试图在 ZeroOrMore 中实现的地方,这是 Forward 的递归将为你做的事情。

    替换:

    _if << Group(Group(ZeroOrMore(IF)) + Group(ZeroOrMore(after_if)) + Group(ZeroOrMore(END_IF)))
    

    与:

    _if << Group(IF + after_if + Group(ZeroOrMore(_if | after_if)) + END_IF)
    

    您还必须注意不要将 END_IF 视为 after_if。这样就可以了:

    after_if  = ~END_IF + Regex(r'(.*?)\n')
    

    通过这些更改,我得到:

    [['If',
      "(LAST_RUN_DATE>=dat('JUL 01, 90'))\n",
      [['If',
        "(pos(con('*',SUB_CODE,'*'),'*ABC*DEF*ASD*WQR*')>=1)\n",
        ['Calculate Client as 1\n'],
        'End If']],
      'End If']]
    

    您还可以考虑对after_if 与非if 语句(目前都被视为after_ifs)进行更明确的说明:

    condition = originalTextFor(nestedExpr("(", ")"))
    _if << Group(IF + condition + Group(ZeroOrMore(_if | after_if)) + END_IF)
    

    如果您的语法允许 if 条件跨越换行符。

    另外,请查看 Yelp! 的 undebt 项目以转换代码(基于 pyparsing)。

    【讨论】:

      猜你喜欢
      • 2015-05-26
      • 2016-05-05
      • 2014-12-05
      • 1970-01-01
      • 2019-11-26
      • 1970-01-01
      • 1970-01-01
      • 2011-01-11
      • 1970-01-01
      相关资源
      最近更新 更多