00:00:00
o Olá pessoal nesta terceira aula da
00:00:03
disciplina de compiladores nós vamos dar
00:00:06
início ao estudo de cada uma das etapas
00:00:08
do processo de compilação nessa aula nós
00:00:11
vamos falar sobre análise léxica e vamos
00:00:14
fazer uma introdução ao tema é os
00:00:16
objetivos da aula de hoje são conhecer
00:00:19
as funções que são executadas pelo
00:00:21
analisador léxico Vamos definir alguns
00:00:24
conceitos importantes e vamos
00:00:26
diferenciar os também que são os
00:00:27
conceitos de letras tema padrão e toquem
00:00:30
e vamos falar um pouquinho sobre as
00:00:32
técnicas para a leitura dos caracteres
00:00:34
que é uma das funções da análise léxica
00:00:36
bem O meu já Adiantei o analisador
00:00:41
léxico ele tem quatro funções principais
00:00:44
a primeira dela é a leitura dos
00:00:47
caracteres do código fonte então
00:00:49
analisador léxico ele vai ler caractere
00:00:51
por caractere do código digitado pelo
00:00:54
usuário e nessa leitura ele vai fazer a
00:00:56
remoção de todos aqueles caracteres que
00:00:59
não são relé
00:01:00
e para a geração do código alvo dentro
00:01:03
desses caracteres estão todos os espaços
00:01:06
em branco tabulações e também nos
00:01:08
comentários que estão dentro do
00:01:10
código-fonte depois de fazer essa
00:01:13
leitura na verdade não é depois é
00:01:15
enquanto ele faz essa leitura ele vai
00:01:18
agrupar esses caracteres em lexemas e
00:01:21
vai classificar esses lexemas em tokens
00:01:25
no próximo slide Nós já vamos definir um
00:01:27
pouquinho melhor esses conceitos
00:01:30
enquanto ele faz o agrupamento dos
00:01:33
caracteres nos looks Semas EA sua
00:01:35
consequente classificação o analisador
00:01:38
léxico tem a função de detectar erros e
00:01:41
quando ele detecta um erro ele também
00:01:44
relaciona é o erro encontrado com a
00:01:47
posição deste erro no programa A quando
00:01:50
vem aquela mensagem é Faltou um ponto e,
00:01:53
na linha 10 por exemplo então a
00:01:56
identificação que foi na linha dessa é o
00:01:58
analisador léxico que faz
00:02:00
e depois que ele faz esse processo de
00:02:02
agrupamento dos caracteres no leque ser
00:02:04
mãe a classificação ele gera uma lista
00:02:07
de tokens esse estoques como nós vamos
00:02:10
ver são os símbolos que vão ser
00:02:11
processados pelas demais etapas do
00:02:14
compilador alguns livros em português
00:02:17
traduzem a palavra tokens como marcas
00:02:20
então vocês vão poder dependendo a
00:02:21
bibliografia encontrar aí a lista de
00:02:24
marcas e outros livros mesmo em
00:02:25
português e mantém a palavra tokens em
00:02:28
inglês e uma a última função do
00:02:31
analisador léxico que também acontece em
00:02:33
paralelo a todo esse processo aqui é a
00:02:36
manipulação da tabela de símbolos que
00:02:38
também nós veremos nas próximas aulas
00:02:41
bom Como é que o analisador léxico ele
00:02:44
se relaciona com as outras etapas ou de
00:02:47
que maneira eu posso sincronizar o
00:02:50
analisador léxico com as outras etapas
00:02:52
Existem duas abordagens uma mais simples
00:02:56
Até de ser feita é que o analisador
00:02:59
léxico
00:03:00
é todo seu trabalho ou seja ele lê todo
00:03:04
o código-fonte c para todo o código
00:03:06
fonte em inglês Semas classifica em
00:03:08
torrens e depois disso Pronto ele passa
00:03:11
essa lista completa para análise
00:03:14
sintática que é a segunda etapa do
00:03:16
compilador só porque essa abordagem ela
00:03:19
não é interessante por questões de
00:03:21
eficiência por exemplo existem alguns
00:03:25
erros que o analisador léxico não
00:03:27
consegue detectar eles vão ser
00:03:28
detectados posteriormente na análise
00:03:31
sintática ou na análise semântica um
00:03:34
erro bem típico de análise sintática é
00:03:37
quando a gente abre um parênteses e
00:03:39
esquece de fechar esses parênteses vamos
00:03:43
imaginar que estamos fazendo um programa
00:03:44
em Java temos lá a função pública
00:03:47
estética e int void mento do cabeçalho
00:03:50
da nossa função principal nós abrimos o
00:03:54
parênteses ali da função Man e
00:03:55
esquecemos de fechar e depois nós
00:03:58
digitamos um código ali com 100
00:04:00
uma das linhas de código se nós fizermos
00:04:03
essa abordagem do analisador léxico
00:04:05
fazer toda a tarefa primeiro o que que
00:04:08
ele vai fazer ele vai ler todas as 200
00:04:10
linhas de código né Por exemplo vai
00:04:13
separar em lexemas vai classificar em
00:04:15
tokens depois de tudo isso pronto ele
00:04:18
passa para analisador sintático e na
00:04:20
primeira linha o analisador sintático já
00:04:22
acha que tem um erro e vai interromper o
00:04:24
processo de compilação aí o que vai
00:04:27
acontecer o analisador léxico perdeu
00:04:29
muito tempo analisando o restante do
00:04:31
código e depois ele vai ter que refazer
00:04:33
todo esse processo novamente quando o
00:04:36
usuário corrigir o erro e mandar
00:04:38
compilar o programa novamente então
00:04:41
abordagem mais usada é essa que está
00:04:42
representada aqui na figura o centro do
00:04:46
compilador não é o quem orquestra As
00:04:48
atividades do compilador é o analisador
00:04:51
sintático E aí quando analisador
00:04:54
sintático precisa de um token ele chama
00:04:56
uma função aqui na figura representada
00:04:59
como get next
00:05:00
ou seja se chama um objeto analisador
00:05:03
sintático que vai fazer a leitura vai
00:05:06
fazer o reconhecimento a classificação
00:05:08
do torre e devolvem o devolve o token
00:05:11
para o analisador sintático naquele
00:05:13
exemplo que Eu mencionei o analisador
00:05:16
sintático ali do Java vamos supor que a
00:05:19
gente esteja pensando só na função
00:05:21
principal então ela vai começar com a
00:05:23
palavra Publique então nós a dor
00:05:25
sintáticos sabe que precisa do pubg ele
00:05:28
vai pedir para analisador léxico ver
00:05:30
quem é o próximo toquem O analisador
00:05:32
léxico vai retornar vamos supor que o
00:05:34
usuário programou corretamente que é o
00:05:36
primeiro tô ruim digitado pelo usuário
00:05:38
foi Publique OK tá correto aí o
00:05:41
analisador léxico sabe que a próxima
00:05:43
palavra tem que vir estética ele pede o
00:05:45
próximo toque no analisador léxico
00:05:47
retorna estética e assim sucessivamente
00:05:50
até que ele reconhece Public static void
00:05:54
Man E aí o analisador léxico sabe que
00:05:57
tem que ter um abre parentes então ele
00:05:59
vai ver o
00:06:00
eu abrir um parêntese viram ali
00:06:03
parâmetros opcionais né Não importa se
00:06:05
ele se usuário coloca esses parâmetros
00:06:07
ou não E aí o analisador sintático diz
00:06:10
que precisa fechar o parênteses Antes de
00:06:13
abrir a chave que vai dar o que vai ser
00:06:15
o corpo da nossa função e aí ele pede
00:06:19
para o analisador léxico quem é o
00:06:20
próximo token ao invés de viram fecha
00:06:23
parentes e se eu estou supondo por
00:06:25
exemplo que o usuário esqueceu de pôr o)
00:06:28
vai vir OAB Chaves e aí o analisador
00:06:30
léxico vai dizer Opa aqui tem um erro
00:06:33
ele esqueceu de fechar os parênteses E
00:06:36
aí o processo de compilação vai ser
00:06:38
interrompido e sente o o o analisador
00:06:40
léxico tem aquele ter lido até que ter
00:06:43
analisado Todas aquelas 200 linhas ele
00:06:46
já para na primeira linha e com isso a
00:06:48
gente ganha bastante tempo e aí como eu
00:06:51
comentei antes existe uma estrutura de
00:06:54
dados que eu já falei lá nas primeiras
00:06:56
aulas que a tabela de símbolos Ela não é
00:06:58
uma etapa do processo de compilação
00:07:00
é mas é uma estrutura que vai permear
00:07:03
todo o processo de compilação o
00:07:05
analisador léxico vai estar salvando e
00:07:07
recuperando informações na tabela de
00:07:08
símbolos o analisador sintático também e
00:07:11
as etapas como análise semântica e todas
00:07:14
as outras etapas que vem depois
00:07:16
posteriormente nós vamos ver exatamente
00:07:18
Que tipo de informação é armazenada aqui
00:07:21
na tabela de símbolos
00:07:23
é bom como eu falei ali é sobre
00:07:26
flexenema padrão e toquem é importante
00:07:30
que a gente defina esses conceitos aí
00:07:32
porque eles vão ser bastante citados ao
00:07:34
longo da disciplina o que que é um
00:07:36
lexema é uma sequência de caracteres do
00:07:40
programa fonte por exemplo a palavra
00:07:42
Indy que serve para declarar uma
00:07:45
variável inteira tô usando aqui Exemplo
00:07:47
né Java ser linguagens nessa linha então
00:07:50
índia um lexema a variável soma que eu
00:07:53
posso criar no nosso programa é um
00:07:55
lexema um (é um lexema um operador de
00:08:00
adição então cada símbolo que eu posso
00:08:03
colocar na verdade não é cada caracter é
00:08:07
cada conjunto de caracteres que formam o
00:08:10
símbolo válido eu posso chamar de lexema
00:08:13
alguns desses são carácter único como eu
00:08:16
falei um (é o lexema um operador demais
00:08:19
é um lexema e outros eu vou ter um
00:08:22
conjunto de caracteres como
00:08:23
a soma que é um like se chama só eu não
00:08:27
tenho caracteres separados
00:08:30
e quando a gente lê um leque sistema nós
00:08:33
temos que Identificar qual é o padrão
00:08:35
que e sílex e mas segue então o padrão
00:08:39
ele vai ser uma descrição da forma que
00:08:42
os leitos temas podem assumir então a
00:08:45
palavra soma ela é uma palavra é um
00:08:48
lexema formado por caracteres
00:08:51
alfanuméricos começa com a letra e e
00:08:55
termina com letras ou soma um por
00:08:57
exemplo envolve letras e números então
00:09:00
nós temos que descrever né através
00:09:03
desses padrões de que maneira eu posso
00:09:07
escrever os lexemas dentro do meu
00:09:10
programa é um padrão é como se fosse as
00:09:12
regras do que é aceito e o que não é
00:09:14
aceito como que a gente faz isso é por
00:09:17
meio de linguagens formais e vai ser o
00:09:19
objeto das nossas aulas daqui para
00:09:21
frente
00:09:22
Oi e o token o token é o resultado da
00:09:25
classificação quando eu tenho um lexema
00:09:28
se selecção a segue um padrão válido eu
00:09:31
vou classificá-lo como sendo um
00:09:33
pouquinho que segue aquele padrão em
00:09:36
geral o Toquinho ele é formado por um
00:09:38
par eu tenho o nome do toque e para
00:09:41
alguns Totens nem todos eu tenho um
00:09:44
atributo E aí esse atributo quem ele o
00:09:47
nome do toque indica os lexemas que
00:09:50
pertencem aquele padrão e o atributo vai
00:09:52
trazer algumas informações a mais Então
00:09:55
vamos voltar no exemplo se eu tenho uma
00:09:58
palavra if no programa em Java Eu tenho
00:10:02
um lexema if e sílex semana ele segue o
00:10:05
padrão que é formado pela letra i e pela
00:10:08
letra F lá no nosso analisador vai ter
00:10:11
uma regra que diz que quando eu tiver um
00:10:12
like seiva formado pela letra i pela
00:10:14
letra F ele forma o token do tipo
00:10:17
palavra reservada if é a palavra
00:10:21
reservada que representa
00:10:22
a pressão se eu tenho lá uma variável
00:10:25
soma aí eu tenho lexemas ola eu tenho um
00:10:29
padrão que diz que palavras formadas por
00:10:32
várias letras elas são identificadores
00:10:35
certo identificadores representam o nome
00:10:38
de variáveis nome de objetos classes
00:10:41
métodos e as funções e assim por diante
00:10:44
E aí pode surgir a dúvida Tá mas do IF
00:10:48
também é formado por um conjunto de
00:10:49
caracteres um conjunto de letras Por que
00:10:51
que ele não é um identificador existe um
00:10:55
conjunto de palavras reservadas dentro
00:10:58
da linguagem e aí quando a gente
00:11:00
Reconhece esse conjunto uma palavra que
00:11:03
é um conjunto de letras a gente verifica
00:11:05
se ela pertence aquele conjunto de
00:11:08
palavras reservadas ela é uma palavra
00:11:10
reservada senão ela é encaixada como um
00:11:13
identificador então no caso do iph o
00:11:16
token é o wi-fi no caso da soma o token
00:11:19
é o identificador
00:11:22
nós temos alguns exemplos de Tocantins
00:11:24
então primeiro se eu tenho um lexema if
00:11:28
certo o token gerado é o wi-fi aqui nós
00:11:32
estamos fazendo uma descrição ainda
00:11:34
informal então eu tô dizendo que se eu
00:11:37
tenho caracter e ixi eu formo Talking
00:11:39
with o mesmo Cruel sequer uma palavra
00:11:42
reservada eu tenho Leite ser maelsi
00:11:45
informalmente eu estou definido que se
00:11:47
eu tenho uma sequência de letras e Ls e
00:11:50
eu formo um cara um pouquinho tipo Élcio
00:11:53
vamos supor que no programa encontre
00:11:56
menor igual ou exclamação igual o
00:11:59
diferente isso aqui quer dizer que eu
00:12:02
tenho um pouquinho do tipo comparação eu
00:12:05
não vou ter um toque para maior igual
00:12:06
menor igual ou diferente e aqui eu tenho
00:12:10
uma descrição formal que me disse se eu
00:12:12
achar o menor o maior ou menor igual ou
00:12:15
maior igual ou igual igual ou diferente
00:12:17
tudo isso é uma comparação aqui eu tenho
00:12:21
algumas
00:12:22
as variáveis piscor de 2 e aí na
00:12:26
descrição informal Qual é uma letra
00:12:29
seguida por letras ou dígitos sempre que
00:12:31
eu tiver qualquer sequência de
00:12:34
caracteres qualquer lexema que siga esse
00:12:37
padrão e não seja uma palavra reservada
00:12:39
ele vai ser enquadrado como um
00:12:41
identificador temos as constantes
00:12:44
numéricas que podem ser números inteiros
00:12:46
números em ponto flutuante exponencial
00:12:48
classificadas como Number e temos aqui
00:12:51
os literais que são as constantes do
00:12:54
tipo string entre "então que eu tenho um
00:12:56
texto entre aspas E aí vai dizer
00:12:58
qualquer caracter diferente de AD" né
00:13:02
que esteja é entre "vai ser o nosso
00:13:06
literal é uma que eles têm um exemplo do
00:13:09
que é o lexema que são os textos que
00:13:11
estão no programa o padrão que é a
00:13:14
descrição de que forma esses links temos
00:13:18
podem ter a diferença que por enquanto
00:13:20
nós ainda estamos descrevendo isso
00:13:22
é normalmente e na implementação do
00:13:24
compilador nós vamos descrever usando o
00:13:26
método formal e Aqui nós temos o token
00:13:29
que a classificação de cada um desses
00:13:32
toquinhos aqui de cada um esses lexemas
00:13:34
desculpem bom atributos eles podem ser
00:13:39
adicionados aos tokens quando mais de um
00:13:42
lexema ele casa com o mesmo padrão
00:13:44
exemplo número a gente viu aqui no slide
00:13:48
anterior que qualquer número vai ser
00:13:51
classificado como Number Quando a gente
00:13:53
chegar na análise sintática a gente vai
00:13:55
entender que essa esse agrupamento ele é
00:13:58
muito bom ele facilita a construção do
00:14:00
analisador sintático entretanto na hora
00:14:03
de gerar o código faz diferença se eu tô
00:14:05
salvando se eu tô somando por exemplo
00:14:08
3.14 eu tô somando 10 certo então não
00:14:11
posso simplesmente dizer que é um número
00:14:13
eu tenho que saber que número é esse aí
00:14:15
neste caso é nós vamos ter como um
00:14:18
atributo do toque não do toque Number o
00:14:21
número
00:14:22
é aquele torre que foi classificado
00:14:24
quando nós temos identificadores mesma
00:14:28
coisa temos 3 variáveis diferentes lá na
00:14:31
lista de Torres mas ou simplesmente
00:14:33
dizer que isso aqui são identificadores
00:14:36
mas faz muita diferença se numa forma eu
00:14:39
tô fazendo pi vezes 10 e ao invés de de
00:14:43
multiplicar o pi na hora de gerar o
00:14:45
código multiplico a variável B dois
00:14:47
então tem que saber exatamente cada uma
00:14:50
das variáveis que estão é posicionadas
00:14:53
na nossa lista de torrens aí para isso
00:14:55
nós usamos a tabela de símbolos sempre
00:14:59
que a gente acha um identificador a
00:15:01
gente salvo identificador na tabela de
00:15:03
símbolos e lá na lista de tokens eu
00:15:06
coloco como um atributo de se toquem
00:15:09
identificador a posição na tabela de
00:15:12
símbolos em que o identificador foi
00:15:15
armazenado a mesma coisa para liberar
00:15:17
esses e operadores agrupado mesma coisa
00:15:20
o exemplo de ano A
00:15:22
e na hora que eu vou fazer análise
00:15:23
sintática para mim não importa se eu
00:15:26
tenho uma operador de maior um operador
00:15:28
de menor o que importa é que eu tenho um
00:15:29
operador de comparação mas na hora que
00:15:32
eu vou gerar o código e isso é
00:15:33
importante então por isso na lista de
00:15:35
tokens a gente coloca que eu tô quem é
00:15:37
uma comparação para facilitar a análise
00:15:39
sintática e outras etapas e colocamos
00:15:42
como atributo Qual é realmente o
00:15:44
operador para na hora que nós formos
00:15:46
gerar o nosso código na próxima aula Nós
00:15:50
vamos pegar um pequeno código em Java
00:15:52
vamos fazer a geração da lista de
00:15:53
torrent da tabela de símbolos dele aí eu
00:15:56
acredito que esses essas explicações que
00:15:59
eu estou dando a fiquei um pouquinho
00:16:01
mais claras
00:16:03
Olá boa quais são os tipos de tokens
00:16:06
comuns na maioria das linguagens de
00:16:08
programação um Token para cada
00:16:10
palavra-chave como devo do IF se eu
00:16:14
tenho uma sequência e f geram Tolkien if
00:16:17
se eu tenho uma sequência Ford F o r de
00:16:20
geram Topic for eu tenho tokens para os
00:16:23
operadores que podem ser individuais ou
00:16:26
em classes é no exemplo da comparação se
00:16:32
eu tô coloca um sinal de maior um sinal
00:16:35
de menor na hora da análise sintática
00:16:37
não faz diferença então eu posso agrupar
00:16:39
todo mundo numa classe só e coloco por
00:16:42
um atributo Qual é o símbolo para hora
00:16:44
de gerar código mas outros operadores
00:16:47
isso não é possível como por exemplo os
00:16:49
operadores aritméticos por quê Porque eu
00:16:52
tenho precedências diferentes se eu
00:16:55
tenho operador de soma e subtração para
00:16:58
mim não faz diferença eu posso inverter
00:17:00
um pelo outro que eu não vou mudar a
00:17:02
ordem de
00:17:03
e para minha expressão agora se eu tenho
00:17:05
operador de soma e nenhum de
00:17:07
multiplicação eu não posso fazer essa
00:17:10
troca direto porque isso muda a forma ou
00:17:13
a ordem que os cálculos são feitos é por
00:17:16
isso que alguns operadores comos
00:17:18
aritméticos eles não são agrupados se eu
00:17:21
tenho um lexema mais eu Gero um toque em
00:17:24
que corresponde a adição se eu tenho
00:17:26
lexema o sinalzinho de menos eu Gero um
00:17:28
toque em que representa a subtração um
00:17:31
toque em um único para todos os
00:17:33
identificadores tudo que é toque tudo
00:17:35
que é identificador vai para ver se
00:17:37
todos comum e de como eu já mencionei
00:17:39
nomes de variáveis nomes de funções
00:17:42
métodos parâmetros tudo aquilo que a
00:17:44
gente pode o programador tem liberdade
00:17:46
para dar nome dentro do código viram
00:17:49
identificador e Esse identificador é
00:17:51
salvo na tabela de símbolos Totens para
00:17:54
classes de constantes nós já vimos no
00:17:56
slide anterior que eu tenho toc Number
00:17:58
número token literal para os textos
00:18:01
entre "e
00:18:03
a pontuação é um toquinho para cada
00:18:06
símbolo se eu tenho (do lexema (no
00:18:09
caracter eu tenho toc abre parentes se
00:18:12
eu tenho um símbolo de abre Chaves no
00:18:15
sistema de ar Chaves eu Gero um toque em
00:18:17
diabo e Chaves então resumindo cada
00:18:19
símbolo diferente gera um pouquinho
00:18:21
diferente
00:18:23
tá bom tenta essas definições e já
00:18:27
entendendo que o papel da analisador
00:18:29
léxico é ler os caracteres e separaram
00:18:32
os lexemas e dizer a qual tipo de
00:18:35
Tolkien ele pertence nós vamos começar
00:18:37
agora a ver cada uma dessas etapas nessa
00:18:41
aula de hoje nós vamos falar apenas da
00:18:42
leitura dos caracteres o reconhecimento
00:18:45
fica para as aulas seguintes a leitura
00:18:48
de caracteres ela é uma etapa
00:18:50
fundamental na construção do compilador
00:18:52
porque ela é a única etapa que vai
00:18:55
analisar o nosso código caractere por
00:18:57
caractere Então vamos imaginar aí
00:18:59
programas com milhares milhões de linhas
00:19:02
são milhões de caracteres que precisam
00:19:04
ser analisados por isso que aceitar pela
00:19:07
demanda bastante tempo em função disso e
00:19:09
deve ser otimizada ao máximo uma das
00:19:13
dificuldades dessa etapa é que em
00:19:16
algumas situações a gente precisa ler um
00:19:19
caracter para frente para saber que o
00:19:22
like semana anterior
00:19:23
o topo anterior terminou aqui eu trago
00:19:27
dois exemplos vamos supor que nós já
00:19:29
Lemos lá do código-fonte as letras soma1
00:19:34
quando eu li o ar eu ainda não sei que a
00:19:37
variável soma está pronta eu vou ter que
00:19:39
ler alguma coisa para frente que pode
00:19:41
ser um espaço em branco pode ser um
00:19:43
igual que vai me dizer que a soma
00:19:45
terminou porque de repente o nome da
00:19:47
variável Não é soma é soma idade Aí eu
00:19:52
vou ler um caractere Então esse ir na
00:19:55
verdade continua fazendo parte no tokens
00:19:57
toma então é esse processo de ler na
00:19:59
frente ele acaba complicando um
00:20:01
pouquinho Outro exemplo é o sinal de
00:20:03
maior quando eu ligo o sinal de maior eu
00:20:06
ainda não sei se eu tenho operador de
00:20:08
maior ou se eu vou ter o maior igual eu
00:20:10
preciso ler o o caracter da frente para
00:20:13
diferenciar isso a ele
00:20:15
e para possibilitar essa leitura do
00:20:18
caracter a frente e também para
00:20:20
ganharmos tempo né para otimizarmos
00:20:23
obviamente a leitura não é feita
00:20:25
carácter a carácter do arquivo são
00:20:28
usados buffers E aí um bloco de código é
00:20:31
lido do arquivo que tá salvo o programa
00:20:34
que está sendo compilado passado para
00:20:36
esse buffer e ele é analisado Aqui nós
00:20:40
temos duas abordagens diferentes A
00:20:42
primeira é a leitura em linhas na
00:20:45
leitura em linha nós pegamos uma linha
00:20:47
do programa jogamos por um buffer um
00:20:49
vetor e fizemos o processamento dessa
00:20:51
linha qual é a vantagem disso ela é uma
00:20:55
tema implementação simples porque eu sei
00:20:59
que quando eu cheguei no final da linha
00:21:00
eu tenho todos os tokens que estavam
00:21:03
naquela linhas terminados eu não começo
00:21:05
um pouquinho uma linha e termino na
00:21:08
outra na pelo menos na grande maioria
00:21:09
das linguagens e Isso facilita bastante
00:21:12
o processo de implementação da
00:21:15
como é que uma linha normalmente é um
00:21:18
bloco pequeno de código não sei lá vou
00:21:20
ter 50 60 80 caracteres Assim menos 100
00:21:24
no máximo numa linha Então eu ligo
00:21:26
poucos caracteres por vez e aí
00:21:28
naturalmente eu tenho que ir ao disco e
00:21:30
voltar várias vezes na leitura isso
00:21:32
acaba não sendo tão utilizada uma outra
00:21:36
abordagem é fazer uma leitura em blocos
00:21:38
de tamanho fixo então o sistema
00:21:40
operacional ele já tem um processo que
00:21:43
ele vai do lado diz que ele consegue ler
00:21:45
um bloco inteiro vamos imaginar um bloco
00:21:47
de 4K bytes 4 mil bytes aí aí eu posso
00:21:51
fazer esse processo de ler os quatro mil
00:21:53
bytes e jogar no buffer a vantagem disso
00:21:56
é que eu otimismo o meu processo que eu
00:21:59
faço menos e interações com o disco que
00:22:01
é uma das etapas que eu tenho um de lei
00:22:03
que eu tenho uma demora maior O problema
00:22:06
é que eu não sei lá no final no 4.096 né
00:22:10
no último byte Será que terminou um
00:22:13
Tolkien certinho um lexema certinho
00:22:15
e já que eu não tenho uma quebra nesse
00:22:18
lexema E aí obviamente para gente ter
00:22:21
esse ganho de desempenho complica um
00:22:23
pouquinho processo de implementação aqui
00:22:26
eu trago dois exemplos para ilustrar
00:22:28
isso para vocês vamos imaginar que nós
00:22:30
temos um código que diz soma igual a
00:22:34
espaço em branco mais espaço em branco
00:22:37
b; se nós usarmos a abordagem por vinhas
00:22:41
na hora que nós vamos ler o código aí
00:22:44
ele vai ler a linha toda nós temos
00:22:46
geralmente um ponteiro que fica marcando
00:22:48
o início do lexema e um ponteiro que vai
00:22:51
adiante até chegar no fim Aqui nós temos
00:22:54
aquele exemplo que eu comentei quando
00:22:56
chega no ar ele não sabe que a variável
00:22:59
soma acabou Ele vai avançar por igual e
00:23:02
aí sim a hora que ele meu igual ele vai
00:23:05
ver que é o sol acabou aí ele volta uma
00:23:10
posição E aí eu tenho aqui o meu leque
00:23:13
sistema soma quando ele reconhece o
00:23:15
leque
00:23:15
e o ponteiro início vai aqui para o ao
00:23:18
início e o fim e aí ele começa aqui
00:23:20
novamente quando ele leu a ele não sabe
00:23:23
que é uma variável a eu poderia ter uma
00:23:25
variável aqui A B C D E aí o Finn vai
00:23:28
para o branco reconhece outra o branco
00:23:30
então quer dizer que acabou a volta para
00:23:32
cá e reconhece o símbolo a isso aqui é
00:23:36
diferente do ponto e, Pior que ele meu;
00:23:38
ele sabe que o ponto-e-vírgula um
00:23:39
símbolo único então ele não precisa
00:23:41
avançar para o fim então percebam que a
00:23:45
abordagem por linha ela é fácil de ser
00:23:48
implementada usando essa lógica que eu
00:23:49
comentei porque quando ele leu o
00:23:51
ponto-e-vírgula e lê aqui o a quebra de
00:23:54
linha o Barra n quer dizer que eu não
00:23:56
tenho nenhum toque iniciado todos os
00:23:59
meus Torres já foram reconhecidos agora
00:24:01
vou me imaginar a leitura por blocos de
00:24:03
tamanho fixo naturalmente se a gente usa
00:24:07
essa abordagem os nossos blocos terão
00:24:08
tamanhos bastante grandes mas é que eu
00:24:11
estou supondo um bloco de 3 bytes apenas
00:24:13
três caracteres apenas só para
00:24:15
o problema porque esse problema poderia
00:24:18
acontecer no final de um bloco
00:24:19
independente do seu tamanho vamos
00:24:22
imaginar que nós lemos 3 bikes estão
00:24:24
temos o início aqui ele deu o s o o iweb
00:24:27
o nosso Buffet tem esse tamanho como ele
00:24:31
ainda não reconheceu aqui o que que vai
00:24:33
acontecer ele vai ler o próximo
00:24:35
caractere vai ler aos próximos
00:24:37
caracteres como é que tá lendo de 3 em 3
00:24:39
que é o tamanho do bloco ele vai
00:24:41
substituir o s ou m pelo a igual a que
00:24:45
são os três caracteres que vem depois E
00:24:48
aí o nosso analisador vai ter um
00:24:50
problema porque ele começou um toque ele
00:24:53
perdeu esses dados antes de ter
00:24:55
reconhecido aquele toque volto a frisar
00:24:59
a mas aqui o teu buffer é pequenininho
00:25:01
só tem 3 bikes o nosso grupo e pode ter
00:25:04
quatro mil Quantos bytes quiser esse
00:25:07
mesmo problema vai acontecer lá no final
00:25:09
certo então essa abordagem aqui ela é
00:25:13
complicado e não dá para ser feito dessa
00:25:15
forma tão
00:25:15
é isso daqui a existe a ideia de pares
00:25:19
de buffers continuando na nossa
00:25:21
suposição que o nosso Burger aqui tem 3
00:25:23
bikes ao invés de eu ter um buffer de 3
00:25:26
likes eu vou ter um buffer um par de
00:25:29
buffers de 3 bytes E aí que que acontece
00:25:32
eu leio e salvo os três primeiros aqui
00:25:36
como ele não reconheceu ainda eu leio a
00:25:40
segunda parte e coloco nesse buffer de
00:25:42
cá e aí ele vai continuar avançando a
00:25:47
hora que ele chega aqui ele reconhece e
00:25:49
salva o soma e vai continuar a análise
00:25:53
daquele quando ele termina de reconhecer
00:25:56
esse essa parte do buffer ele vai fazer
00:25:59
o que ele apaga essa parte aqui e coloca
00:26:02
mais três caracteres aqui então percebam
00:26:05
que a diferença é que eu nunca Limpo o
00:26:07
buffer todo sempre o que eu tô
00:26:10
processando continua e eu só trago as
00:26:12
informações novas na outra metade do
00:26:14
buffer
00:26:15
a minha primeira mantenho aqui e aí
00:26:18
atualizo 3 bytes aqui essa solução é
00:26:23
isenta de erros não mas é pouco provável
00:26:26
que eles aconteçam quando que
00:26:28
aconteceria um erro aqui quando eu tenho
00:26:30
11 um like sistema certo que o tamanho
00:26:35
dele é maior que os dois buffers juntos
00:26:38
então nosso caso como nós Uber tem três
00:26:41
se eu tiver uma variável com mais de 6
00:26:43
caractéres Aí sim vai dar problema
00:26:45
porque eu vou colocar o sono aqui os
00:26:48
outros três caracteres aqui supondo que
00:26:50
seja soma idade s a m e d a como ainda
00:26:55
não reconheceu eu vou ter que apagar
00:26:56
essa primeira parte para pôr o d e e o
00:26:59
restante aí vai dar problema mas
00:27:02
lembre-se que eu comentei os blocos em
00:27:04
geral são grandes então se eu tenho um
00:27:06
bloco de quatro trabalhos 4/1996
00:27:09
caracteres quer dizer que só que eu
00:27:11
tenho identificador de mais de 4.096
00:27:14
caracteres
00:27:15
o problema nesse buffer certo aquele
00:27:18
problema que acontecia aqui em cima
00:27:20
simplesmente por eu ter chego no final
00:27:22
esse problema não acontece mais essa
00:27:25
técnica bastante utilizada no final da
00:27:29
aula ali Eu sempre deixo uma
00:27:30
bibliografia recomendada daqueles livros
00:27:33
o livro do Arco que é o primeiro é o
00:27:35
único que explica esta técnica os outros
00:27:37
dois eles não não abordam ficam mais
00:27:39
nessa parte aqui da leitura por linhas
00:27:41
que é mais simples muito bem agora já
00:27:45
Lemos seja por linha ou seja por bloco e
00:27:49
nós vimos que ao mesmo tempo que nós
00:27:51
vamos fazendo a leitura Mas temos que
00:27:53
classificar Mas como que é feita essa
00:27:55
separação dos leitos semanas e essa
00:27:57
classificação em Tocantins
00:28:00
é através de autômatos finitos
00:28:02
determinísticos que nós vimos lá na
00:28:05
disciplina de teoria da Computação nas
00:28:08
próximas aulas Então nós vamos ver como
00:28:11
que acontece essa geração da lista de
00:28:13
tokens para vocês entenderem exatamente
00:28:15
o que que vira cada look cima como é
00:28:17
representado como inserido na tabela de
00:28:20
símbolos e Por enquanto ainda de uma
00:28:22
maneira informal e daqui mais umas duas
00:28:24
aulas aí nós vamos começar a entender
00:28:26
como realmente o analisador léxico a
00:28:28
implementado a partir da construção dos
00:28:31
autômatos finitos determinísticos e aqui
00:28:34
para finalizar eu deixo o material
00:28:36
complementar os três livros da
00:28:38
bibliografia da disciplina com a
00:28:40
indicação das seções onde vocês podem
00:28:42
obter maiores informações sobre essa
00:28:44
parte introdutória da análise léxica até
00:28:47
a próxima pessoal