在python中将简单命令转换为AST

The*_*au5 0 python parsing abstract-syntax-tree pyparsing

我想在Python中使用一个函数将字符串命令转换为AST(抽象语法树).

该命令的语法如下:

commandName(3, "hello", 5.0, x::int)
Run Code Online (Sandbox Code Playgroud)

命令可以接受任意数量的逗号分隔值

  1. 整型
  2. 字符串
  3. 花车
  4. 类型

假设函数被调用convert_to_ast,那么

convert_to_ast('commandName(3, "hello", 5.0, x::int)')
Run Code Online (Sandbox Code Playgroud)

应该产生以下AST:

{ 
  'type': 'command',
  'name': 'commandName',
  'args': [{
    'type': 'int',
    'value': 3
  }, {
    'type': 'str',
    'value': 'Hello'
  }, {
    'type': 'float',
    'value': 5.0
  }, {
    'type': 'var',
    'kind': 'int',
    'name': 'x
  }]
Run Code Online (Sandbox Code Playgroud)

mgi*_*son 5

好像你可以只评估字符串,然后从那里挑选出类型:

>>> items = ast.literal_eval('(404.5, "Hello", 5)')
>>> [{'type': type(item).__name__, 'value': item} for item in items]
[{'type': 'float', 'value': 404.5}, {'type': 'str', 'value': 'Hello'}, {'type': 'int', 'value': 5}]
Run Code Online (Sandbox Code Playgroud)

当然,如果你想做更多有趣的事情,你可以直接访问AST:

>>> ast.dump(ast.parse('(404.5, "Hello", 5)'))
"Module(body=[Expr(value=Tuple(elts=[Num(n=404.5), Str(s='Hello'), Num(n=5)], ctx=Load()))])"
>>> ast.parse('(404.5, "Hello", 5)').body[0].value.elts
[<_ast.Num object at 0x107fa1250>, <_ast.Str object at 0x107fa1290>, <_ast.Num object at 0x107fa12d0>]
Run Code Online (Sandbox Code Playgroud)

对于比解析元组更常见的事情(正如你已经添加到问题中),我们仍然可以使用python的AST来解析它(只要你的语法有效的python).在这种情况下,我们将创建一个ast.NodeVisitor将提取我们访问我们关心的python AST的每个节点的信息.在这种情况下,我们关心的 Call,Num,StrName节点:

import ast

class Parser(ast.NodeVisitor):

    def __init__(self):
        self.calls = []
        self.current_command = None

    def visit_Call(self, node):
        name = node.func.id
        self.current_command = {
            'type': 'command',
            'name': name,
            'args': []
        }
        self.calls.append(self.current_command)
        for arg in node.args:
            self.visit(arg)
        self.current_command = None

    def visit_Num(self, node):
        if not self.current_command:
            return
        args = self.current_command['args']
        arg = {
            'type': type(node.n).__name__,
            'value': node.n
        }
        args.append(arg)

    def visit_Str(self, node):
        if not self.current_command:
            return
        args = self.current_command['args']
        arg = {
            'type': 'str',
            'value': node.s
        }
        args.append(arg)

    def visit_Name(self, node):
        if not self.current_command:
            return
        args = self.current_command['args']
        arg = {
            'type': 'type',
            'kind': node.id 
        }
        args.append(arg)


S = 'commandName(3, "hello", 5.0, int)'

tree = ast.parse(S)
p = Parser()
p.visit(tree)
print p.calls
Run Code Online (Sandbox Code Playgroud)