"ast" --- Árvores de Sintaxe Abstrata
*************************************

**Código-fonte:** Lib/ast.py

======================================================================

O módulo "ast" ajuda os aplicativos Python a processar árvores da
gramática de sintaxe abstrata do Python. A sintaxe abstrata em si pode
mudar em cada lançamento do Python; este módulo ajuda a descobrir
programaticamente como é a gramática atual.

Uma árvore de sintaxe abstrata pode ser gerada passando
"ast.PyCF_ONLY_AST" como um sinalizador para a função embutida
"compile()", ou usando o auxiliar "parse()" fornecido neste módulo. O
resultado será uma árvore de objetos cujas classes herdam de
"ast.AST". Uma árvore de sintaxe abstrata pode ser compilada em um
objeto de código Python usando a função embutida "compile()".


Classes de nó
=============

class ast.AST

   Esta é a base de todas as classes de nós AST. As classes de nós
   reais são derivadas do arquivo "Parser/Python.asdl", o qual é
   reproduzido abaixo. Elas são definidas no módulo C "_ast" e
   reexportadas em "ast".

   Há uma classe definida para cada símbolo do lado esquerdo na
   gramática abstrata (por exemplo, "ast.stmt" ou "ast.expr"). Além
   disso, existe uma classe definida para cada construtor no lado
   direito; essas classes herdam das classes para as árvores do lado
   esquerdo. Por exemplo, "ast.BinOp" herda de "ast.expr". Para regras
   de produção com alternativas ("somas"), a classe do lado esquerdo é
   abstrata: apenas instâncias de nós construtores específicos são
   criadas.

   _fields

      Cada classe concreta possui um atributo "_fields" que fornece os
      nomes de todos os nós filhos.

      Cada instância de uma classe concreta tem um atributo para cada
      nó filho, do tipo definido na gramática. Por exemplo, as
      instâncias "ast.BinOp" possuem um atributo "left" do tipo
      "ast.expr".

      Se estes atributos estiverem marcados como opcionais na
      gramática (usando um ponto de interrogação), o valor pode ser
      "None". Se os atributos puderem ter valor zero ou mais (marcados
      com um asterisco), os valores serão representados como listas do
      Python. Todos os atributos possíveis devem estar presentes e ter
      valores válidos ao compilar uma AST com "compile()".

   lineno
   col_offset
   end_lineno
   end_col_offset

      As instâncias das subclasses "ast.expr" e "ast.stmt" possuem
      "lineno", "col_offset", "lineno" e "col_offset" . O "lineno" e
      "end_lineno" são o primeiro e o último número de linha do
      intervalo do texto de origem (indexado em 1, para que a primeira
      linha seja a linha 1) e o "col_offset" e "end_col_offset" são os
      deslocamentos de byte UTF-8 correspondentes do primeiro e do
      último tokens que geraram o nó. O deslocamento UTF-8 é
      registrado porque o analisador usa UTF-8 internamente.

      Observe que as posições finais não são exigidas pelo compilador
      e, portanto, são opcionais. O deslocamento final está *após* o
      último símbolo, por exemplo, é possível obter o segmento de
      origem de um nó de expressão de uma linha usando
      "source_line[node.col_offset : node.end_col_offset]".

   O construtor de uma classe "ast.T" analisa seus argumentos da
   seguinte forma:

   * Se houver argumentos posicionais, deve haver tantos quanto houver
     itens em "T._fields"; eles serão atribuídos como atributos desses
     nomes.

   * Se houver argumentos de palavra-chave, eles definirão os
     atributos dos mesmos nomes para os valores fornecidos.

   Por exemplo, para criar e popular um nó "ast.UnaryOp", você poderia
   usar

      node = ast.UnaryOp()
      node.op = ast.USub()
      node.operand = ast.Constant()
      node.operand.value = 5
      node.operand.lineno = 0
      node.operand.col_offset = 0
      node.lineno = 0
      node.col_offset = 0

   ou a forma mais compacta

      node = ast.UnaryOp(ast.USub(), ast.Constant(5, lineno=0, col_offset=0),
                         lineno=0, col_offset=0)

Alterado na versão 3.8: A classe "ast.Constant" é agora usada para
todas as constantes.

Obsoleto desde a versão 3.8: Classes antigas "ast.Num", "ast.Str",
"ast.Bytes", "ast.NameConstant" e "ast.Ellipsis" ainda estão
disponíveis, mas eles serão removidos em versões futuras do Python.
Enquanto isso, instanciá-los retornará uma instância de uma classe
diferente.


Gramática Abstrata
==================

A gramática abstrata está atualmente definida da seguinte forma:

   -- ASDL's 5 builtin types are:
   -- identifier, int, string, object, constant

   module Python
   {
       mod = Module(stmt* body, type_ignore *type_ignores)
           | Interactive(stmt* body)
           | Expression(expr body)
           | FunctionType(expr* argtypes, expr returns)

           -- not really an actual node but useful in Jython's typesystem.
           | Suite(stmt* body)

       stmt = FunctionDef(identifier name, arguments args,
                          stmt* body, expr* decorator_list, expr? returns,
                          string? type_comment)
             | AsyncFunctionDef(identifier name, arguments args,
                                stmt* body, expr* decorator_list, expr? returns,
                                string? type_comment)

             | ClassDef(identifier name,
                expr* bases,
                keyword* keywords,
                stmt* body,
                expr* decorator_list)
             | Return(expr? value)

             | Delete(expr* targets)
             | Assign(expr* targets, expr value, string? type_comment)
             | AugAssign(expr target, operator op, expr value)
             -- 'simple' indicates that we annotate simple name without parens
             | AnnAssign(expr target, expr annotation, expr? value, int simple)

             -- use 'orelse' because else is a keyword in target languages
             | For(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment)
             | AsyncFor(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment)
             | While(expr test, stmt* body, stmt* orelse)
             | If(expr test, stmt* body, stmt* orelse)
             | With(withitem* items, stmt* body, string? type_comment)
             | AsyncWith(withitem* items, stmt* body, string? type_comment)

             | Raise(expr? exc, expr? cause)
             | Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)
             | Assert(expr test, expr? msg)

             | Import(alias* names)
             | ImportFrom(identifier? module, alias* names, int? level)

             | Global(identifier* names)
             | Nonlocal(identifier* names)
             | Expr(expr value)
             | Pass | Break | Continue

             -- XXX Jython will be different
             -- col_offset is the byte offset in the utf8 string the parser uses
             attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)

             -- BoolOp() can use left & right?
       expr = BoolOp(boolop op, expr* values)
            | NamedExpr(expr target, expr value)
            | BinOp(expr left, operator op, expr right)
            | UnaryOp(unaryop op, expr operand)
            | Lambda(arguments args, expr body)
            | IfExp(expr test, expr body, expr orelse)
            | Dict(expr* keys, expr* values)
            | Set(expr* elts)
            | ListComp(expr elt, comprehension* generators)
            | SetComp(expr elt, comprehension* generators)
            | DictComp(expr key, expr value, comprehension* generators)
            | GeneratorExp(expr elt, comprehension* generators)
            -- the grammar constrains where yield expressions can occur
            | Await(expr value)
            | Yield(expr? value)
            | YieldFrom(expr value)
            -- need sequences for compare to distinguish between
            -- x < 4 < 3 and (x < 4) < 3
            | Compare(expr left, cmpop* ops, expr* comparators)
            | Call(expr func, expr* args, keyword* keywords)
            | FormattedValue(expr value, int? conversion, expr? format_spec)
            | JoinedStr(expr* values)
            | Constant(constant value, string? kind)

            -- the following expression can appear in assignment context
            | Attribute(expr value, identifier attr, expr_context ctx)
            | Subscript(expr value, slice slice, expr_context ctx)
            | Starred(expr value, expr_context ctx)
            | Name(identifier id, expr_context ctx)
            | List(expr* elts, expr_context ctx)
            | Tuple(expr* elts, expr_context ctx)

             -- col_offset is the byte offset in the utf8 string the parser uses
             attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)

       expr_context = Load | Store | Del | AugLoad | AugStore | Param

       slice = Slice(expr? lower, expr? upper, expr? step)
             | ExtSlice(slice* dims)
             | Index(expr value)

       boolop = And | Or

       operator = Add | Sub | Mult | MatMult | Div | Mod | Pow | LShift
                    | RShift | BitOr | BitXor | BitAnd | FloorDiv

       unaryop = Invert | Not | UAdd | USub

       cmpop = Eq | NotEq | Lt | LtE | Gt | GtE | Is | IsNot | In | NotIn

       comprehension = (expr target, expr iter, expr* ifs, int is_async)

       excepthandler = ExceptHandler(expr? type, identifier? name, stmt* body)
                       attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)

       arguments = (arg* posonlyargs, arg* args, arg? vararg, arg* kwonlyargs,
                    expr* kw_defaults, arg? kwarg, expr* defaults)

       arg = (identifier arg, expr? annotation, string? type_comment)
              attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)

       -- keyword arguments supplied to call (NULL identifier for **kwargs)
       keyword = (identifier? arg, expr value)

       -- import name with optional 'as' alias.
       alias = (identifier name, identifier? asname)

       withitem = (expr context_expr, expr? optional_vars)

       type_ignore = TypeIgnore(int lineno, string tag)
   }


Auxiliares de "ast"
===================

Além das classes de nós, o módulo "ast" define essas funções e classes
utilitárias para percorrer árvores de sintaxe abstrata:

ast.parse(source, filename='<unknown>', mode='exec', *, type_comments=False, feature_version=None)

   Analisa a fonte em um nó AST. Equivalente a "compile(source,
   filename, mode, ast.PyCF_ONLY_AST)".

   Se "type_comments=True" é fornecido, o analisador é modificado para
   verificar e retornar comentários do tipo, conforme especificado por
   **PEP 484** e **PEP 526**. Isso é equivalente a adicionar
   "ast.PyCF_TYPE_COMMENTS" aos sinalizadores passados para "compile()
   `. Isso relatará erros de sintaxe para comentários do tipo
   extraviado. Sem esse sinalizador, os comentários do tipo serão
   ignorados e o campo ``type_comment`()" nos nós AST selecionados
   sempre será "None". Além disso, os locais dos comentários "# type:
   ignore" serão retornados como o atributo "type_ignores" de "Module"
   (caso contrário, é sempre uma lista vazia).

   Além disso, se "mode" for "'func_type'", a sintaxe de entrada é
   modificada para corresponder a "comentários de tipo de assinatura"
   de **PEP 484**, por exemplo, "(str, int) -> List[str]".

   Além disso, definir "feature_version" como uma tupla "(maior,
   menor)" tentará analisar usando a gramática dessa versão do Python.
   Atualmente, "maior" deve ser igual a "3". Por exemplo, definir
   "feature_version=(3, 4)" permitirá o uso de "async" e "waitit" como
   nomes de variáveis. A versão mais baixa suportada é "(3, 4)"; a
   mais alta é "sys.version_info[0:2]".

   Aviso:

     É possível travar o interpretador Python com uma string
     suficientemente grande/complexa devido às limitações de
     profundidade da pilha no compilador de AST do Python.

   Alterado na versão 3.8: Adicionado "type_comments",
   "mode='func_type'" e "feature_version".

ast.literal_eval(node_or_string)

   Avalia com segurança um nó de expressão ou uma string contendo um
   literal Python ou exibição de contêiner. A string ou o nó fornecido
   pode consistir apenas nas seguintes estruturas literais de Python:
   strings, bytes, números, tuplas, listas, dicts, conjuntos,
   booleanos e "None".

   Isso pode ser usado para avaliar com segurança strings contendo
   valores Python de fontes não confiáveis sem a necessidade de
   analisar os valores por si próprio. Não é capaz de avaliar
   expressões arbitrariamente complexas, por exemplo, envolvendo
   operadores ou indexação.

   Aviso:

     É possível travar o interpretador Python com uma string
     suficientemente grande/complexa devido às limitações de
     profundidade da pilha no compilador de AST do Python.

   Alterado na versão 3.2: Agora permite bytes e literais de
   conjuntos.

ast.get_docstring(node, clean=True)

   Retorna a docstring do *node* dado (que deve ser um nó
   "FunctionDef", "AsyncFunctionDef", "ClassDef" ou "Module") ou
   "None" se não tiver uma docstring. Se *clean* for verdadeiro, limpa
   o recuo da docstring com "inspect.cleandoc()".

   Alterado na versão 3.5: Não há suporte a "AsyncFunctionDef".

ast.get_source_segment(source, node, *, padded=False)

   Obtém o segmento de código-fonte de *source* que gerou *node*. Se
   algumas informações de local ("lineno", "end_lineno", "col_offset"
   ou "end_col_offset") estiverem faltando, retorna "None".

   Se *padded* for "True", a primeira linha de uma instrução
   multilinha será preenchida com espaços para corresponder à sua
   posição original.

   Novo na versão 3.8.

ast.fix_missing_locations(node)

   Quando você compila uma árvore de nós com "compile()", o compilador
   espera atributos "lineno" e "col_offset" para cada nó que os
   suporta. Isso é tedioso para preencher nós gerados, portanto, esse
   auxiliar adiciona esses atributos recursivamente, onde ainda não
   estão definidos, definindo-os para os valores do nó pai. Ele
   funciona recursivamente a partir do *node*.

ast.increment_lineno(node, n=1)

   Incrementa o número da linhas e o número da linha final de cada nó
   na árvore começando em *node* em *n*. Isso é útil para "mover
   código" para um local diferente em um arquivo.

ast.copy_location(new_node, old_node)

   Copia o local de origem ("lineno", "col_offset", "end_lineno" e
   "end_col_offset") de *old_node* para *new_node* se possível e,
   então, retorna *new_node*.

ast.iter_fields(node)

   Produz uma tupla de "(fieldname, value)" para cada campo em
   "node._fields" que esteja presente em *node*.

ast.iter_child_nodes(node)

   Produz todos os nós filhos diretos de *node*, ou seja, todos os
   campos que são nós e todos os itens de campos que são listas de
   nós.

ast.walk(node)

   Produz recursivamente todos os nós descendentes na árvore começando
   em *node* (incluindo o próprio *node*), em nenhuma ordem
   especificada. Isso é útil se você quiser apenas modificar nós no
   lugar e não se importar com o contexto.

class ast.NodeVisitor

   Uma classe base de visitante de nó que percorre a árvore de sintaxe
   abstrata e chama uma função de visitante para cada nó encontrado.
   Esta função pode retornar um valor que é encaminhado pelo método
   "visit()".

   Esta classe deve ser uma subclasse, com a subclasse adicionando
   métodos visitantes.

   visit(node)

      Visita um nó. A implementação padrão chama o método chamado
      "self.visit_*nomedaclasse*" sendo *nomedaclasse* o nome da
      classe do nó, ou "generic_visit()" se aquele método não existir.

   generic_visit(node)

      Este visitante chama "visit()" em todos os filhos do nó.

      Observe que nós filhos de nós que possuem um método de visitante
      personalizado não serão visitados, a menos que o visitante chame
      "generic_visit()" ou os visite por conta própria.

   Não use o "NodeVisitor" se você quiser aplicar mudanças nos nós
   durante a travessia. Para isso existe um visitante especial
   ("NodeTransformer") que permite modificações.

   Obsoleto desde a versão 3.8: Os métodos "visit_Num()",
   "visit_Str()", "visit_Bytes()", "visit_NameConstant()" e
   "visit_Ellipsis()" estão agora descontinuados e não serão chamados
   em futuras versões do Python. Adicione um método "visit_Constant()"
   para lidar com nós de constantes.

class ast.NodeTransformer

   A subclasse "NodeVisitor" que percorre a árvore de sintaxe abstrata
   e permite a modificação de nós.

   O "NodeTransformer" percorrerá a AST e usará o valor de retorno dos
   métodos do visitante para substituir ou remover o nó antigo. Se o
   valor de retorno do método visitante for "None", o nó será removido
   de seu local, caso contrário, ele será substituído pelo valor de
   retorno. O valor de retorno pode ser o nó original, caso em que não
   há substituição.

   Aqui está um exemplo de transformador que rescreve todas as
   ocorrências de procuras por nome ("foo") para "data['foo']":

      class RewriteName(NodeTransformer):

          def visit_Name(self, node):
              return Subscript(
                  value=Name(id='data', ctx=Load()),
                  slice=Index(value=Constant(value=node.id)),
                  ctx=node.ctx
              )

   Tenha em mente que, se o nó em que você está operando tiver nós
   filhos, você deve transformar os nós filhos por conta própria ou
   chamar o método "generic_visit()" para o nó primeiro.

   Para nós que faziam parte de uma coleção de instruções (que se
   aplica a todos os nós de instrução), o visitante também pode
   retornar uma lista de nós em vez de apenas um único nó.

   Se "NodeTransformer" introduz novos nós (que não faziam parte da
   árvore original) sem fornecer informações de localização (como
   "lineno"), "fix_missing_locations()" deve ser chamado com o novo
   subárvore para recalcular as informações de localização:

      tree = ast.parse('foo', mode='eval')
      new_tree = fix_missing_locations(RewriteName().visit(tree))

   Normalmente você usa o transformador assim:

      node = YourTransformer().visit(node)

ast.dump(node, annotate_fields=True, include_attributes=False)

   Retorne um despejo formatado da árvore em *node*. Isso é útil
   principalmente para fins de depuração. Se *annotate_fields* for
   verdadeiro (por padrão), a sequência retornada mostrará os nomes e
   os valores para os campos. Se *annotate_fields* for falso, a
   sequência de resultados será mais compacta ao omitir nomes de
   campos não ambíguos. Atributos como números de linha e
   deslocamentos de coluna não são despejados por padrão. Se isso for
   desejado, *include_attributes* pode ser definido como verdadeiro.

Ver também:

  Green Tree Snakes, um recurso de documentação externo, possui bons
  detalhes sobre trabalhar com ASTs do Python.

  ASTTokens annotates Python ASTs with the positions of tokens and
  text in the source code that generated them. This is helpful for
  tools that make source code transformations.

  leoAst.py unifies the token-based and parse-tree-based views of
  python programs by inserting two-way links between tokens and ast
  nodes.

  LibCST parses code as a Concrete Syntax Tree that looks like an ast
  tree and keeps all formatting details. It's useful for building
  automated refactoring (codemod) applications and linters.

  Parso is a Python parser that supports error recovery and round-trip
  parsing for different Python versions (in multiple Python versions).
  Parso is also able to list multiple syntax errors in your python
  file.
