Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/362.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Python和pyparsing解析Visual Basic函数的参数列表_Python_Vba_Pyparsing - Fatal编程技术网

使用Python和pyparsing解析Visual Basic函数的参数列表

使用Python和pyparsing解析Visual Basic函数的参数列表,python,vba,pyparsing,Python,Vba,Pyparsing,我正在尝试使用解析Visual Basic(VBA)函数声明,以便将它们转换为Python语法 通常的VBA函数头不是一个大问题,这对我来说很好。但我对论点列表有困难: Public Function MyFuncName(first As Integer, Second As String) As Integer 参数由一个逗号分隔的列表组成,列表中有0到多个部分,如: VarName VarName As VarType Optional VarName As VarType = Init

我正在尝试使用解析Visual Basic(VBA)函数声明,以便将它们转换为Python语法

通常的VBA函数头不是一个大问题,这对我来说很好。但我对论点列表有困难:

Public Function MyFuncName(first As Integer, Second As String) As Integer
参数由一个逗号分隔的列表组成,列表中有0到多个部分,如:

VarName
VarName As VarType
Optional VarName As VarType = InitValue
ByVal VarName As VarType
其中“Optional”、“ByVal”和“ByRef”以及类型声明都是完全可选的

我的想法是通过

allparams = Regex('[^)]*').setResultsName('params')
然后分别解析它们。这与单个参数匹配:

variablename = Word(alphas + '_', alphanums + '_')
typename = variablename.setResultsName('type')
default_value = Word(alphanums)
optional_term = oneOf('Optional', True)
byval_term = oneOf('ByRef ByVal', True)

paramsparser = Optional(optional_term) \
    +Optional(byval_term) \
    +variablename.setResultsName('pname', True) \
    +Optional('As' + typename) \
    +Optional('=' + default_value)
但是即使使用
delimitedList(paramsparser)
我也只能得到第一个

AssertionError: 'def test(one):\n\tpass' != 'def test(one, two):\n\tpass'
- def test(one):
+ def test(one, two):
?             +++++

你有什么想法吗?

我使用了你发布的代码,并将其包装在一个
分隔列表中,得到了两个参数:

paramsparser = Optional(optional_term) \
    +Optional(byval_term) \
    +variablename.setResultsName('pname', True) \
    +Optional('As' + typename) \
    +Optional('=' + default_value)

parser = "(" + delimitedList(paramsparser) + ")"

parser.runTests("""\
    (one, two)
    (ByRef one As Int = 1, Optional ByVal two As Char)
""")
印刷品:

(one, two)
['(', 'one', 'two', ')']
- pname: ['one', 'two']

(ByRef one As Int = 1, Optional ByVal two As Char)
['(', 'ByRef', 'one', 'As', 'Int', '=', '1', 'Optional', 'ByVal', 'two', 'As', 'Char', ')']
- pname: ['one', 'two']
- type: 'Char'
但由于每个参数有这么多字段,我建议为每个字段指定一个单独的结果名称,并在组中换行,以防止参数相互重叠。下面是我对解析器的修改(非常有帮助,您发布了不同可选声明字段的各种表单):

然后,我不再使用正则表达式获取参数,然后在单独的步骤中重新解析,而是将其包含在整个函数表达式定义中:

protection = oneOf("Public Private", asKeyword=True)
func_expr = (
    protection("protection")
    + FUNCTION
    + identifier("fname")
    + Group(LPAR + delimitedList(param_expr) + RPAR)("parameters")
    + Optional(AS + type_expr("return_type"))
)

tests = """
Public Function MyFuncName(first As Integer, Second As String) As Integer
"""
func_expr.runTests(tests)
印刷品:

Public Function MyFuncName(first As Integer, Second As String) As Integer
['Public', 'Function', 'MyFuncName', [['first', 'As', 'Integer'], ['Second', 'As', 'String']], 'As', 'Integer']
- fname: 'MyFuncName'
- parameters: [['first', 'As', 'Integer'], ['Second', 'As', 'String']]
  [0]:
    ['first', 'As', 'Integer']
    - pname: 'first'
    - ptype: 'Integer'
  [1]:
    ['Second', 'As', 'String']
    - pname: 'Second'
    - ptype: 'String'
- protection: 'Public'
- return_type: 'Integer'

ViperMonkey是pyparsing中的VBA解析器,你可能会从中得到一些想法。非常感谢,@PaulMcG,这非常有帮助,我学到了更多关于pyparsing的知识!我刚刚在param_expr中添加了一个
Optional()
,因此整个参数字符串都是可选的。我添加了
Sub
关键字,这是在VBA中没有结果的函数。
Public Function MyFuncName(first As Integer, Second As String) As Integer
['Public', 'Function', 'MyFuncName', [['first', 'As', 'Integer'], ['Second', 'As', 'String']], 'As', 'Integer']
- fname: 'MyFuncName'
- parameters: [['first', 'As', 'Integer'], ['Second', 'As', 'String']]
  [0]:
    ['first', 'As', 'Integer']
    - pname: 'first'
    - ptype: 'Integer'
  [1]:
    ['Second', 'As', 'String']
    - pname: 'Second'
    - ptype: 'String'
- protection: 'Public'
- return_type: 'Integer'