PeixeiroData

[1] Python Internals - Tokens

· Cezar Peixeiro

ℹ️ Referências:

1. O que são tokens?

Ao executar qualquer código em Python o interpretador deverá entender o que cada um dos caracteres digitados significa e como devem ser manipulados. O Python realiza esta tarefa quebrando o código em tokens em cada um dos espaços ou ao identificar um caractere com função pré-definida. Vou utilizar como exemplo o código:

1#test_tokens.py
2x = 1 + 2
3print(x)

O pacote tokenize

O python possui uma biblioteca built-in chama tokenize que nos ajuda a entender como a linguagem identifica os tokens. Podemos utilizá-la através da linha de comando e ver seu resultado:

 1$ python3 -m tokenize test_tokens.py 
 2    0,0-0,0:            ENCODING       'utf-8'        
 3    1,0-1,1:            NAME           'x'            
 4    1,2-1,3:            OP             '='            
 5    1,4-1,5:            NUMBER         '1'            
 6    1,6-1,7:            OP             '+'            
 7    1,8-1,9:            NUMBER         '2'            
 8    1,9-1,10:           NEWLINE        '\n'           
 9    2,0-2,5:            NAME           'print'        
10    2,5-2,6:            OP             '('            
11    2,6-2,7:            NAME           'x'            
12    2,7-2,8:            OP             ')'            
13    2,8-2,9:            NEWLINE        ''             
14    3,0-3,0:            ENDMARKER      ''           

Na linha (2) o python declara o encoding que está utilizando para realizar a tokenização (UTF-8 é o padrão). Os pares no início das linhas fazem referência a coordenadas (linha,coluna) de início e fim daquele token e ao lado de cada um está sua categoria dentro do que chamamos de gramática do Python (NAME, OP, NUMBER, …)

A Gramática do Python

Como o python sabe que x é um NAME, mas ),( ou = são do tipo OP?
Os operadores estão declarados em /Grammar/Tokens no repositório da linguagem. Lá é encontrado um mapeamento entre nomes e o token ao qual se refere. Exemplo:

GREATER                 '>'
EQUAL                   '='
DOT                     '.'
PERCENT                 '%'
LBRACE                  '{'
RBRACE                  '}'
EQEQUAL                 '=='
NOTEQUAL                '!='
LESSEQUAL               '<='
GREATEREQUAL            '>='

Caso alguma alteração seja realizada neste arquivo as referências dos tokens, deverão ser reconstruídas através da execução do comando make regen-token. Este comando deve ser executado na raíz do repositório para que encontre o comando neste Makefile.

Atualização: ./configure deve ser executado antes do comando make.


Apêndice (A): Dissecando o comando make regen-token

(Referente a este Makefile)

Este comando faz referência a este trecho do arquivo:

 1.PHONY: regen-token
 2regen-token:
 3	# Regenerate Doc/library/token-list.inc from Grammar/Tokens
 4	# using Tools/build/generate_token.py
 5	$(PYTHON_FOR_REGEN) $(srcdir)/Tools/build/generate_token.py rst \
 6		$(srcdir)/Grammar/Tokens \
 7		$(srcdir)/Doc/library/token-list.inc \
 8		$(srcdir)/Doc/library/token.rst
 9	# Regenerate Include/internal/pycore_token.h from Grammar/Tokens
10	# using Tools/build/generate_token.py
11	$(PYTHON_FOR_REGEN) $(srcdir)/Tools/build/generate_token.py h \
12		$(srcdir)/Grammar/Tokens \
13		$(srcdir)/Include/internal/pycore_token.h
14	# Regenerate Parser/token.c from Grammar/Tokens
15	# using Tools/build/generate_token.py
16	$(PYTHON_FOR_REGEN) $(srcdir)/Tools/build/generate_token.py c \
17		$(srcdir)/Grammar/Tokens \
18		$(srcdir)/Parser/token.c
19	# Regenerate Lib/token.py from Grammar/Tokens
20	# using Tools/build/generate_token.py
21	$(PYTHON_FOR_REGEN) $(srcdir)/Tools/build/generate_token.py py \
22		$(srcdir)/Grammar/Tokens \
23		$(srcdir)/Lib/token.py

#tokenizer #python-internals #python3 #python