试图解析 Python 中的旧语法
Trying to parse old syntax in Python
我们有一个旧应用程序需要迁移到 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
使用 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)。
我们有一个旧应用程序需要迁移到 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
使用 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)。