[1] Python Internals - Tokens
ℹ️ Referências:
- Repositório do código-fonte do Python
- Palestra - Desmistificando o Python Internals - Mergulhando no CPython implementando um operador (Inglês)
- Internals of CPython - Louie Lu
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