Baixe o app para aproveitar ainda mais
Prévia do material em texto
11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiUp… 1/46 COMPILADORESCOMPILADORES CONSTRUÇÃO DECONSTRUÇÃO DE COMPILADORESCOMPILADORES Au to r ( a ) : D r. J o ã o C a r l o s L o p e s Fe r n a n d e s R ev i s o r : Ed i l s o n J o s é R o d r i g u e s Tempo de leitura do conteúdo estimado em 1 hora e 5 minutos. 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiUp… 2/46 Introdução Olá, prezado(a) estudante! Neste material, estudaremos sobre a construção de compiladores utilizados em diversas técnicas baseadas em outros escopos, como exemplos: conversão no formato de arquivos diferentes, leitura e/ou interpretação de arquivos HTML, dentre outros. Todos os compiladores são baseados em algoritmos e nas estruturas dos dados a serem traduzidos e/ou compilados. As fases de uma compilação podem possuir diferentes estágios, mas sempre os resultados esperados são os mesmos: árvores sintáticas, tabelas de hash (sequência de bits gerada por um algoritmo de dispersão) e de pré-processamento, dentre outros. Existe uma busca constante na construção dos compiladores, a otimização dos códigos, os quais, por meio de novos paradigmas de programação, tentam diminuir o número de linhas nas novas linguagens e, assim, melhorar a performance de programas após compilação. Isso vem ao encontro de melhores e mais amigáveis interfaces para desenvolvedores, como os ambientes de desenvolvimento integrados (IDEs) e as linguagens mais funcionais com lógicas de programação distribuídas. Bons estudos! 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiUp… 3/46 Estudante, quando de�nimos um algoritmo genérico, percebemos que ele é uma descrição �nita dos processos de computação, que são escritos em linguagens algorítmicas nas quais cada sentença tem um signi�cado não ambíguo. Os algoritmos devem conseguir ser �nalizados em tempo �nito, ou seja, devem possuir paradas garantidas — caso contrário, entrariam num loop in�nito. Todos os procedimentos não terminam ao mesmo tempo. Dessa forma, algoritmos têm de resolver esse problema, e devem existir procedimentos para que um algoritmo possa chegar a uma resposta respeitando o tempo �nito — ou ele não terá uma resposta em nenhum momento. Um algoritmo sempre deve chegar a uma resposta (a�rmativa ou negativa) (AHO et al., 2008). Na construção de compiladores, deve-se decidir se o problema pode ser resolvido apenas com algoritmos ou se os procedimentos devem ser balizados e ajustados pela teoria da computação conhecida como Problema da Parada, ou seja, dado um programa P e um conjunto de dados d, responda sim se P(d) para e não caso contrário. Ferramentas para Construção de Compiladores 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiUp… 4/46 Veja o que Langlois e Santos (2018, p. 276) falam a respeito das várias ferramentas que fazem algoritmo: Existem diversas ferramentas que realizam o mesmo algoritmo, com pequenas variações no formato de entrada. O arquivo segue uma estrutura semelhante à utilizada pelas ferramentas lex e yacc, estando dividida em três seções separadas por uma linha que contém apenas a sequência %%. A primeira seção é reservada para declarações, podendo o código C/C++ ser incluído da mesma forma. Quando utilizados processadores de linguagem (programas que permitem ao computador “entender” os comandos de uma programação de alto nível fornecidos), temos duas maneiras para que isso seja possível: interpretadores e/ou tradutores. Veja, a seguir, mais sobre eles. 1. Interpretadores São programas que executam diretamente as instruções que provêm de programas construídos em linguagens chamadas “fonte”. 2. Tradutores São programas que aceitam a entrada de programas escritos em linguagens “fonte” e produzem, em sua saída, outra versão do programa escrito na linguagem “objeto”. Em alguns casos, a linguagem objeto é a própria linguagem de máquina entendida pelo computador (arquitetura CISC, RISC ou ARM). Sobre os programas “objeto”, é importante ressaltar que eles podem ser executados diretamente na máquina e que os tradutores são divididos em “montadores” e “compiladores”, que têm a capacidade de traduzir linguagens de baixo nível e alto nível, respectivamente. 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiUp… 5/46 Você sabia que na construção de compiladores há opções de pré- processadores que conseguem traduzir uma linguagem de alto nível para outra linguagem de alto nível? Pois é, todas essas funcionalidades estão alicerçadas em fundamentos matemáticos da teoria de processamento de linguagens, na teoria de autômatos e em linguagens formais. Sendo assim, o objetivo de um compilador é traduzir sequências de caracteres de um programa-fonte desenvolvido por um programador para instruções de máquina. Essa tarefa pode ser um pouco complexa quando há estruturas formadas com processos menores interconectados. Em um modelo mais simples de compilação, a “tradução” pode ser realizada com a interconexão seriada entre três blocos: léxico, sintático e gerador de código, conforme vemos na imagem a seguir. 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiUp… 6/46 Figura 2.1 - Conexão entre blocos e tabelas Fonte: Elaborada pelo autor. #PraCegoVer: a imagem apresenta uma seta, da esquerda para a direita, na horizontal, que termina em um retângulo com o texto “Bloco léxico”, que aponta para outro retângulo com o escrito “Bloco sintático”, que aponta para um retângulo com o escrito “Gerador de código”, que possui uma seta indicando para a direita. Abaixo, há um retângulo com a palavra “Tabelas”, que aponta para os três retângulos acima dela. Você percebe que na imagem vemos que os três blocos têm acesso às tabelas de informações do programa-fonte; dentre essas tabelas, por exemplo, existe a tabela de símbolos, na qual estão localizadas as informações sobre cada variável e/ou identi�cador utilizados no programa-fonte. No subtópico a seguir, apresentaremos os compiladores Lex e Yacc, atualmente muito utilizados por possuírem uma vasta bibliogra�a que pode ser consultada on-line. 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiUp… 7/46 Lex/Yacc (C) ou ANTLR (Java) O Lex/Yacc é difundido no campo da programação, pois sua utilização, na geração de compiladores, é extensa. Trata-se de ferramentas um pouco difíceis de serem utilizadas, principalmente no caso de programadores iniciantes. Vamos nos aprofundar um pouco mais sobre esses dois compiladores, na fundamentação a seguir. Fonte: Elaborada pelo autor. No Lex, as especi�cações de entrada são formadas por expressões regulares e comandos da linguagem de programação especí�ca. Seu funcionamento acontece quando o analisador é gerado e as expressão são reconhecidas; Lex 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiUp… 8/46 assim, os comandos são associados e executados. O trabalho, em princípio, �ca mais simples, mas interpolar as especi�cações com o código “objeto” pode fazer com que a leitura da primeira fase se torne um pouco mais difícil. Outro detalhe muito importante ao qual você precisa se atentar é a necessidade de con�gurar o Lex a �m de utilizar suas especi�cações e gerar um analisador para outra linguagem. Como o Lex é uma ferramenta bastante utilizada, é fácilencontrar documentação na internet, mas programadores devem estar familiarizados com ferramentas que utilizam linhas de comando. De forma básica, o Lex cria um �uxo de caracteres convertidos numa sequência de tokens, e os programas utilizados recebem o nome de lexers e/ou tokenizadores. Em sua saída, é um scanner orientado por tabela que orienta o que fazer caso um caractere de entrada esteja incorreto. A saída sempre “salva” um arquivo chamado lex.yy.c. — esse tem estrutura semelhante à descrita a seguir. {declarations} %% {rules} %% {subroutines} Todas as declarações são divididas em dois tipos, C e Lex, mas todas as importações e declarações globais sempre são realizadas em C. Fora isso, os arquivos Lex podem também possuir de�nições de expressões e símbolos regulares: .%{%}. Todas as regras estão descritas e seguidas de ações e devem �car na mesma linha, já as sub-rotinas contêm as funções descritas pelo programador. 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiUp… 9/46 Fonte: Elaborada pelo autor. A saída, ou resultado, do Yacc apresenta uma tabela de análise sintática denominada de LALR, as rotinas de controle, baseadas na tabela, e todas as ações semânticas, especi�cadas pelo programador no arquivo de entrada da linguagem. Este analisa o �uxo de tokens do arquivo Lex e realiza pela análise semântica. O Yacc traduz as determinadas gramáticas no contexto (CFG) para uma implementação C y.tab.c. Sendo assim, esse programa C, quando compilado, gera um analisador executável. Um detalhe importante é que os arquivos Yacc possuem estrutura semelhante aos arquivos Lex. {declarations} %% Yacc 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 10/46 {rules} %% {subroutines} Por isso, as declarações e sub-rotinas são as mesmas do Lex; o que é ligeiramente alterado são as regras. No caso do Yacc, as regras não são expressões regulares, pois são de�nidas gramaticalmente em CFG. De forma similar ao Lex, as regras possuem duas partes: produções e ações. Quando o Lex produz um código C para os analisadores léxicos e/ou scanner, usa padrões combinantes de strings na entrada e converte-os em tokens. Os tokens são representações numéricas das strings utilizadas para simpli�car o processamento. Conforme o Lex vai encontrando os identi�cadores na sequência da entrada, insere-os na tabela de símbolos. Essa tabela pode conter outras informações, como os tipos de dados (inteiro ou real) e a localização das variáveis na memória. O Yacc, como utiliza as regras gramaticais, consegue analisar os tokens do Lex e criar a árvore de sintaxe, a qual impõe a estrutura hierárquica dos tokens, ou seja, a precedência dos operadores e a associatividade entre eles. Na próxima fase, é gerado o código, que foi baseado na árvore de sintaxe. Alguns tipos de compiladores produzem diretamente o código de máquina. Veja, na �gura a seguir, como são apresentadas a produção e a ação do Lex/Yacc. 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 11/46 Figura 2.2 - Produção e ação Fonte: Niemann ([2018], p. 5). #PraCegoVer: a imagem apresenta a utilização do Lex/Yacc. Em sua extremidade esquerda superior, está escrita a palavra “bas.y”, que aponta para um retângulo na mesma linha com o texto “yacc”. Também na extremidade esquerda, na parte inferior da imagem, vem a palavra “bas.I”, alinhada verticalmente com a palavra “bas.y”; dela, sai uma seta, apontando para um retângulo com a palavra “lex”. Embaixo de cada um dos retângulos “yacc” e “lex”, existe uma seta vertical apontando para baixo com a palavra “y.tab.h”, ao centro. Do retângulo “yacc”, sai uma seta na horizontal, apontando para a palavra “y.tab.c”, que possui, em sua parte superior, a palavra “(yyparse)”. Do retângulo “lex”, sai uma seta na horizontal, apontando para a palavra “lex.yy.c”, que possui, em sua parte inferior, a palavra “(yylex)”. As duas palavras apontam, com uma seta, para um retângulo, com a palavra “CC”, que �ca na mesma linha da palavra “y.tab.h”. Do retângulo com a palavra “CC”, sai uma seta na horizontal, que aponta para a palavra “bas.exe”, que, por sua vez, aponta, para baixo e com uma seta, para a palavra “compiled output”. Nessa mesma coluna, na parte superior, existe a palavra “source”, que aponta, com uma seta, para a palavra “bas.exe”. 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 12/46 O arquivo y.tab.h é criado com a compilação do arquivo Yacc. Ele informa ao arquivo Lex todas as declarações de token válidas de�nidas no programa Yacc. Um analisador é feito para trabalhar em conjunto com as rotinas de análise léxica gerada pelo Lex, sintática e semântica, geradas pelo YACC, e produzir um resultado satisfatório para a lógica utilizada pelo programador. “Embora algumas ferramentas, como o gerador yacc, permitam indicar a prioridade e associatividade de um operador, na realidade o usuário indica a prioridade e a associatividade de todas as regras que usam esse símbolo” (LANGLOIS; SANTOS, 2018, p. 85). Fonte: Elaborada pelo autor. ANTLR 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 13/46 ANTLR, mesmo sendo mais lenta, pois um autômato de pilha mais lento que o processamento das gramáticas regulares, e o desempenho do compilador gerado não é tão prejudicado. Como uma alternativa, a gramática poderá ser dividida em dois arquivos, mas o processamento continua a ser LL(k). Estudante, a seguir, temos a sugestão de leitura de Branco Júnior e Tamae (2008) a respeito de etapas e fundamentos para a concepção de um compilador. Certamente, esse artigo servirá de apoio para que você se aproprie ainda mais do conteúdo. 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 14/46 Os símbolos de terminação poderão ser agrupados com as expressões regulares, mas a gramática utiliza o EBNF (Extended Backus-Naur Form) combinado com a possível construção de sub-regras e/ou repetições, conforme apresentamos na imagem a seguir. Figura 2.3 - Regras EBNF Fonte: Elaborada pelo autor. #PraCegoVer: a imagem apresenta as regras EBNF, que geram os códigos. Do lado esquerdo, existe a representação de uma folha com a borda esquerda dobrada e, dentro dessa folha, há o seguinte escrito em forma de coluna: “a: b|c|d ;”, “b: X Y Z ;”, “c: Z Z ;”, “d: X Z ;” — embaixo, está escrito “Regras EBNF”. Depois, vem uma seta na horizontal, apontando para outra folha, com borda esquerda dobrada, na qual se lê, em forma de coluna: “void a(), {, case (X), ..., }” — embaixo, está escrito “Código java / C++ / C#”. Sobre a seta que interliga as duas páginas, há a palavra “ANTLR”. No ANTLR, existe também a possibilidade de utilização de um terceiro arquivo para processamento da árvore simbólica, desde que ele seja gerado pelo analisador sintático. Para Barbosa et al. (2021, p. 121), “O ANTLR precisa do 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 15/46 arquivo de entrada com sintaxe similar ao Java, [...] Esse arquivo também é dividido em seções, mas, ao contrário do Yacc, as divisões são parecidas com funções Java”. O ANTLR é considerado uma ferramenta poderosa e �exível para a análise das principais linguagens formais, pois, nele, a gramática sendo limpa e concisa, o código resultante normalmente é bem e�ciente e estável. Com base nas consideraçõesa respeito desses programas, um detalhe importante: Lex, Yacc e ANTLR, mesmo possuindo algumas diferenças em suas con�gurações, têm a mesma função na compilação, ou seja, participam e auxiliam no processo. Conhecimento Teste seus Conhecimentos (Atividade não pontuada) O termo inglês “Compiler Compilers” é “utilizado para referenciarmos de forma genérica as ferramentas que auxiliam o desenvolvimento de compiladores, que são os geradores. Sendo a construção de compiladores um processo complexo, há diferentes geradores para cada fase do compilador”. FEDOZZI, R. Compiladores. Londrina: Editora e Distribuidora Educacional S.A., 2018. p. 57. 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 16/46 Assinale a alternativa que correspondente à relação entre aplicativo (ferramenta) e sua função: a) Lex; gerador de código alvo. b) JFlex; gerador de analisadores Java. c) JavaCC; gerador de analisadores semânticos para o Java. d) Yacc; gerador de analisador sintático. e) Jasmin; ferramenta completa para produção de compiladores. Estudante, no subtópico a seguir, você lerá sobre análise lexical. Em primeiro momento, pensará apenas na matéria de português, mas se trata também de um conceito da ciência da computação com vertentes semelhantes à análise aplicada à linguística. Análise Léxica 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 17/46 A análise lexical tem como função agrupar �uxos de letras e/ou sons em conjuntos que representam a sintaxe signi�cativa. Ela pode ser dividida em duas etapas: a primeira, chamada de escanear, é a simples busca para remoção de comentários e todos os espaços em branco; na segunda etapa, o analisador lexical divide o texto em lexemas, que são palavras e/ou parte de palavras base para expressão. Durante a varredura, ocorre a análise léxica: sequências de caracteres são organizadas como unidades signi�cativas denominadas marcas, que são como as palavras em uma linguagem natural como o inglês, por exemplo. Um sistema de varredura tem função similar à de um sistema para soletrar (LOUDEN, 2004, p. 22). Todas as análises léxicas sempre escrevem um parser (analisador) mais fácil de ser manipulado, ao invés de se acumularem e/ou renomearem seus caracteres individualmente. O parser não se preocupa com os símbolos — apenas se preocupa com as questões de sintática —, e isso levará à e�ciência da programação, mas não garante a e�ciência na hora da execução. Dessa forma, as tabelas de símbolos são “banco de dados” utilizados na compilação. Nelas, as informações são inseridas para a tabela de símbolos com o auxílio dos analisadores léxicos e sintáticos e serão usadas no gerador de código. Especificação dos Tokens Quando nos referimos a um token, na área de computação e compiladores, queremos dizer que ele é um segmento de texto e/ou símbolo que poderá ser manipulado por analisadores sintáticos, os quais forneceram um signi�cado ao 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 18/46 texto, ou seja, é um conjunto de caracteres que possuem signi�cado coletivo a ser utilizado no processo dos compiladores. O token também é conhecido como componente léxico que, numa cadeia de caracteres, possui signi�cado coerente para a linguagem de programação utilizada. Como exemplos, podemos ter palavras-chave (if, then, else, while, int, dentre outras) e identi�cadores, números, sinais e/ou vários caracteres (como “=” e “+”). Dessa forma, analisadores léxicos devem identi�car os diferentes tokens de diferentes linguagens e sempre devolver a analisadores sintáticos códigos correspondentes a cada token. Para que isso aconteça, é necessário algum mecanismo que permita aos autômatos �nitos fazerem isso. Normalmente, 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 19/46 para que isso aconteça, é feito com que o autômato possua vários pontos de saída, sendo um para cada token diferente. Reconhecimento dos Tokens Os tokens são símbolos léxicos que serão reconhecidos por padrão e podem ser divididos em dois grupos distintos, conforme infográ�co a seguir. #PraCegoVer: o infográ�co estático apresenta os “Tokens simples” e “Tokens argumentados”. Os “Tokens simples” são explicados da seguinte maneira: “não possuem nenhum valor associado, pois a classe associada a ele já o descreve”. Os “Exemplos” incluem “as palavras reservadas, os operadores e delimitadores de programação como: <if>, <them> <else>, <+,>. Os “Tokens argumentados” são explicados da seguinte maneira: “sempre possuem um valor associado e corresponde a elementos especí�cos das linguagens de programação utilizadas pelos programadores”. Os “Exemplos” incluem “os identi�cadores, as constantes numéricas, como: <id,7>, <numero, 20>, <literal, Olá Alunos>”. 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 20/46 Para Langlois e Santos (2018, p. 143), “essa rotina devolve zero quando chega ao �m da sequência de entrada, de modo que os valores restantes �cam disponíveis para a identi�cação dos tokens”. Os autores acrescentam quando dizem que “Nesta situação, todas as sequências de entrada que produzem tokens devolvem um número único para cada um de maneira que o loop permite reconhecer todos os tokens” (LANGLOIS; SANTOS, 2018, p. 143). Para as palavras reservadas pelas linguagens de programação, utiliza-se uma técnica diferente: sempre que o token de identi�cador for detectado, deve-se realizar uma busca na(s) tabela(s) por essa cadeia; caso ela for localizada, é retornado ao token equivalente, e, caso contrário, é retornada ao token sua própria identi�cação. 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 21/46 Na prática, o que é utilizado são os geradores de analisadores léxicos (poderosas ferramentas que produzem automaticamente os analisadores léxicos), normalmente, por uma especi�cação baseada em gramáticas regulares, expressões regulares ou autômatos �nitos. Conhecimento Teste seus Conhecimentos (Atividade não pontuada) Leia o trecho a seguir. “A função exata do analisador léxico é reconhecer os tokens associados às expressões regulares. Assim, por meio das expressões regulares de�nidas na gramática, o analisador léxico poderá identi�car o par (tipo do token, lexema)”. FEDOZZI, R. Compiladores. Londrina: Editora e Distribuidora Educacional S.A., 2018. p. 84. Analise as alternativas a seguir e escolha a única correta. a) Lexema, morfema e grafema são elementos da análise sintática de uma linguagem de programação. 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 22/46 b) Lexema é um tipo de padrão, e token é o nome dado ao lexema. c) Tipo de token é um padrão pertencente à linguagem, e o lexema é uma instância do token. d) Token e lexema são instâncias do mesmo objeto. e) Token é uma produção, e lexema é a semântica. No tópico, a seguir, veri�caremos como é realizada a análise léxica nos programas e quais são suas utilidades no processo de compilação. Estudante, para a implementação das análises léxicas, normalmente, utilizam- se as tabelas de transições de autômatos �nitos e algoritmos que fazem a Análise Léxica dos Programas 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 23/46 análise léxica para percorrer a sentença e consultar as tabelas.Outra forma que poderá ser utilizada é a de realizar a programação diretamente no autômato; para isso, será necessário saber o estado atual e o próximo símbolo de cada sentença, podendo-se, assim, avançar ao próximo estado, prosseguindo-se até terminar a sentença e/ou não ser mais possível realizar a transição de estados (MENEZES, 2011). No ramo da computação, a análise léxica, ou tokenização, é o caminho para transformar um agrupamento de caracteres em um arranjo de tokens (strings/palavras com um signi�cado designado e, portanto, distinto). Um programa que realiza a análise léxica pode ser conhecido como lexer, tokenizer ou scanner, apesar de o scanner ser também um termo para a etapa inicial de um lexer (BARBOSA et al., 2021, p. 57, grifo nosso). O analisador léxico sempre tem a função de identi�car os tokens nas linguagens de programação e enviá-los a analisadores sintáticos. Para que isso possa ser realizado, uma ótima opção é utilizar autômatos �nitos: eles permitem que tokens possuam muitos pontos para saída, o que auxilia bastante no processo de compilação. 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 24/46 Geração de Autômatos Finitos como Reconhecedores de Analisadores Léxicos O analisador léxico realiza a veri�cação dos programas quanto aos aspectos léxicos. Esses aspectos sempre são de�nidos por gramáticas regulares (tipo 3) e/ou outros mecanismos equivalentes, como expressões regulares e autômatos �nitos. A análise léxica, primeira fase do compilador, é responsável pela leitura de caractere por caractere de um arquivo texto de uma linguagem de programação e os traduz em tokens ou símbolos léxicos, utilizando expressões regulares, que podem ser representados por autômatos �nitos não determinísticos (AFND) (BARBOSA et al., 2021, p. 32). Os Autômatos Finitos Não Determinísticos (AFNDs) são compostos por um conjunto de “S” de estados (um desses estados, s0 ∈ S), que são denominados como estado inicial do autômato e um subconjunto “F ⊆ S”, que representa os estados �nais e/ou os estados de aceitação. Também existe um conjunto “T”, que indica as transições, e cada transição “t” está vinculada a um par de estados “s1 e s2”, sendo descrito com um símbolo, que será um caractere “c” do 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 25/46 alfabeto Σ, e/ou o símbolo ε, que indicará que acontecerá uma transição épsilon, que permitirá que o estado mude sem a necessidade de utilizar caracteres das cadeias de entrada. Uma transição de um estado “s” para um estado “t” no símbolo “c” é descrita como “s → c t”. Para melhor entendimento, considere a expressão regular a∗(a|b) e o AFND apresentado na �gura a seguir. Figura 2.4 - AFND da expressão regular a∗(a|b) Fonte: Barbosa et al. (2021, p. 33). #PraCegoVer: a imagem apresenta um círculo, à esquerda, com o número 2, o qual aponta para outro círculo, abaixo, na mesma coluna, que contém o número 1 e recebe uma seta de retorno; na seta que aponta para baixo, a letra “a”, e, na seta que aponta para cima, a letra “Ɛ”. O círculo, com o número 1, aponta para um círculo com outro círculo, onde, dentro, há o número 3; no centro dessa seta, está a letra “b”. O círculo 2 também aponta para o círculo 3, e tem, em sua seta, a letra “a”. Existe uma seta na horizontal, à direita, apontando para o círculo 1. 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 26/46 Note que o AFND possui três estados: o estado 1 é o estado inicial (marcado por uma seta apontando para ele de fora do autômato); o estado 3 é a aceitação. Existe uma transição (seta que conecta dois estados) épsilon (Ɛ) do estado 1 ao estado 2, transições no símbolo “a” do estado 2 aos estados 1 e 3 e uma transição no símbolo “b” do estado 1 ao estado 3. Referenciando-se ao AFND disponibilizado na �gura anterior (Figura 2.4), se possuirmos uma string aab, serão geradas as sequências de transições descritas na �gura a seguir (Figura 2.5). Ela é descrita da seguinte forma: do estado 1 ao estado 2, épsilon (Ɛ); do estado 2 ao estado 1, a; do estado 1 ao estado 2, épsilon (Ɛ); do estado 2 ao estado 1, a; do estado 1 ao estado 3, que é o estado de aceitação, b. 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 27/46 Figura 2.5 - Transições da string aab Fonte: Barbosa et al. (2021, p. 33). #PraCegoVer: a imagem apresenta 3 colunas, que possuem, da esquerda para a direita, os seguintes cabeçalhos, “De”, na coluna 1; “Para”, na coluna 2; “Transição”, na coluna 3. Na primeira linha, abaixo de “De”, vem o número 1; abaixo de “Para”, vem o número 2; em “Transação”, vem o símbolo Ɛ. Na linha abaixo, vem a seguinte sequência, abaixo de cada coluna: 2, 1, a. Abaixo, vêm 1, 2, Ɛ. Abaixo, vêm, 2, 1, a; na última linha do total de 5 linhas, vêm 1, 3, b. praticar 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 28/46 Vamos Praticar Os autômatos �nitos, ou máquinas de estados �nitos, são utilizados nos processos de criação de compiladores. Eles são os primeiros modelos computacionais que de�nem as linguagens por mecanismos de reconhecimento e podem ser considerados testadores aplicados a cada caractere das palavras. Comando da atividade prática: utilizaremos o simulador “Auger”, o qual é gratuito e simples de ser instalado. Segundo o site Evoluma (AUGER…, [2022], on-line), ele permite: • Criar autômatos �nitos de forma grá�ca (a partir do diagrama de estados); • Executar algoritmos de manipulação de autômatos �nitos; • Testar autômatos �nitos através do recurso de simulação de cadeias de entrada; • Utilizar expressões regulares e gramáticas regulares para gerar autômatos �nitos; • Gerar expressões regulares e gramáticas regulares a partir de autômatos �nitos; • Gerar programas em linguagem Java para testar os autômatos criados ou criar analisadores léxicos; • Criar diagramas de estados e utilizá-los como imagens em outros softwares. Para realizar a instalação, acesse o link http://www.evoluma.com/auger/arquivos/auger_31/Auger31.jar: o simulador será baixado automaticamente em seu computador. Por sua vez, o manual do programa está disponível em http://www.evoluma.com/auger/manual.html. Após ter realizado o download, clique duas vezes no arquivo “Auger31” (a tela apresentada na �gura a seguir será aberta). http://www.evoluma.com/auger/arquivos/auger_31/Auger31.jar http://www.evoluma.com/auger/manual.html 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 29/46 Figura - Tela do aplicativo Auger Fonte: Adaptado de Auger… ([2022], on-line). #PraCegoVer: a tela apresenta um quadrado azul; na extremidade superior, do lado esquerdo, está escrito “Auger – [sem nome]”; na linha abaixo, temos estas palavras, alinhadas, na forma horizontal, da esquerda para direita: Arquivo, Editar, Ferramentas, Visualizador, Algoritmos e Ajuda. Logo abaixo, cinco ícones, alinhados da esquerda para direita: o primeiro tem uma seta azul, inclinada para a esquerda; o próximo tem a letra “q” entre um círculo; o seguinte apresenta uma seta inclinada para esquerda com a letra “a” em cima; o próximo apresenta um “x”; o último, um desenho de três esferas pequenas interligadas. Entraremos como uma expressão regular, (a | b)*c. Clique em arquivo, importar e expressão regular; digite a expressão; clique em importar, conforme �gura a seguir. 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU…30/46 Figura - Inserção de expressão regular Fonte: Adaptado de Auger… ([2022], on-line). #PraCegoVer: a tela apresenta um quadrado azul, e, em sua extremidade superior, do lado esquerdo, está escrito “Auger – [sem nome]”; logo na linha abaixo, temos estas palavras, alinhadas de forma horizontal, da esquerda para direita: Arquivo, Editar, Ferramentas, Visualizador, Algoritmos e Ajuda. Logo abaixo, cinco ícones, alinhados da direita para esquerda: o primeiro tem uma seta azul inclinada para a direita; o próximo tem a letra “q” entre um círculo; o seguinte apresenta uma seta inclinada para a direita com a letra “a” em cima; o próximo apresenta um “x”; o último, um desenho de três esferas pequenas interligadas. Aparece, em Arquivo, importar e expressão regular, o retângulo branco que abriu, com o cabeçalho escrito “Importar expressão regular” e a opção “Importar”. Após clicar em importar, aparecerá a imagem da �gura a seguir. Clique em “OK”. 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 31/46 Figura - Resultado da importação Fonte: Adaptado de Auger… ([2022], on-line). #PraCegoVer: a tela apresenta um quadrado azul, e, em sua extremidade superior, do lado esquerdo, está escrito “Auger – [sem nome]”; logo na linha abaixo, temos estas palavras, alinhadas de forma horizontal, da esquerda para direita: Arquivo, Editar, Ferramentas, Visualizador, Algoritmos e Ajuda. Logo abaixo, cinco ícones, alinhados da esquerda para direita: o primeiro tem uma seta azul inclinada para a esquerda: o próximo tem a letra “q” entre um círculo; o seguinte apresenta uma seta inclinada para a esquerda com a letra “a” em cima; o próximo apresenta um “x”; o último, um desenho de três esferas pequenas interligadas. Na tela azul, aparecem vários circuitos com a letra “q” e um número; no meio da tela, dentro de um retângulo, a frase “Quantidade de estados criados: 24”. Num botão abaixo, está escrito “OK”. Agora, você deve realizar as seguintes funções e, ao �nal, explicar o resultado. Clique em algoritmos, eliminar e-transições e OK. Clique em algoritmos, eliminar estados inalcançáveis e OK. 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 32/46 Você receberá esta tela (�gura a seguir) como respostas: Figura - Resultado da operação 1 Fonte: Adaptado de Auger… ([2022], on-line). #PraCegoVer: a tela apresenta um quadrado azul, e, em sua extremidade superior, do lado esquerdo, está escrito “Auger – [sem nome]”; logo na linha abaixo, temos estas palavras, alinhadas de forma horizontal, da esquerda para direita: Arquivo, Editar, Ferramentas, Visualizador, Algoritmos e Ajuda. Logo abaixo, cinco ícones alinhados da esquerda para direita: o primeiro tem uma seta azul inclinada para a esquerda; o próximo tem a letra “q” entre um círculo; o seguinte apresenta uma seta inclinada para a esquerda, com a letra “a” em cima; o próximo apresenta um “x”; o último, um desenho de três esferas pequenas interligadas. Na tela azul, aparecem seis círculos com letra “q” e os números de 0 (zero) a 5 com setas os interligando. Agora, chegou a hora de você gerar o programa reconhecedor. Clique em “Algoritmos”, “Gerar programa”, “Reconhecer” e salve com o nome teste.java (�gura a seguir). 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 33/46 Figura - Resultado da operação 2 Fonte: Adaptado de Auger… ([2022], on-line). #PraCegoVer: a tela apresenta um quadrado azul, e, em sua extremidade superior, do lado esquerdo, está escrito: “Auger – [sem nome]”; logo na linha abaixo, temos estas palavras, alinhadas de forma horizontal, da esquerda para direita: Arquivo, Editar, Ferramentas, Visualizador, Algoritmos e Ajuda. Logo abaixo, cinco ícones alinhados da esquerda para direita: o primeiro tem uma seta azul inclinada para a esquerda; o próximo tem a letra “q” entre um círculo; o seguinte apresenta uma seta inclinada para a esquerda, com a letra “a” em cima; o próximo apresenta um “x”; o último, um desenho de três esferas pequenas interligadas. Na tela azul, aparecem seis círculos com letra “q” e os números de 0 (zero) a 5 com setas os interligando. A palavra “Algoritmos” está selecionada e aparecem, abaixo dela, as seguintes opções: AFND -> AFD. Abaixo, na mesma coluna, as palavras: Eliminar e-transações, Eliminar estados mortos, Eliminar estados inalcançáveis, Minimizar, Gerar programa reconhecedor e Testar autômato. Agora, edite com um editor de texto de sua preferência o arquivo teste.java e explique o pedaço de código que foi gerado. 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 34/46 ... } private void inicializaAutomato() { for (int i=0; i<alfabeto.length; i++) for (int j=0; j<estados.length; j++) matrizTransicao[i][j] = null; matrizTransicao[0][0] = "q3"; //<q0> ::= <q3> matrizTransicao[0][1] = "q2"; //<q1> ::= <q2> matrizTransicao[0][2] = "q3"; //<q2> ::= <q3> matrizTransicao[0][4] = "q3"; //<q4> ::= <q3> matrizTransicao[1][0] = "q5"; //<q0> ::= c<q5> matrizTransicao[1][2] = "q5"; //<q2> ::= c<q5> matrizTransicao[1][4] = "q5"; //<q4> ::= c<q5> matrizTransicao[2][0] = "q1"; //<q0> ::= a<q1> matrizTransicao[2][2] = "q1"; //<q2> ::= a<q1> matrizTransicao[2][4] = "q1"; //<q4> ::= a<q1> matrizTransicao[3][3] = "q4"; //<q3> ::= b<q4> }... 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 35/46 Material Complementar F I L M E Ameaça virtual. Ano: 2001. Comentário: um gênio da informática, que abriria uma empresa com um de seus amigos, recebe uma proposta de trabalho na empresa de seu ídolo, Gary Winston, e, mesmo �cando supercontente com a vaga, descobre que a empresa possuía sérios problemas com a lei antitruste americana. Esse �lme abre um debate essencial sobre o uso de softwares de código aberto (softwares livres) versus programas proprietários das grandes empresas e ainda mostra a realidade do chamado “monopólio virtual”. Para conhecer mais sobre o �lme, acesse o trailer: 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 36/46 TRA I LER L I V R O Compiladores: da teoria à prática. Autores: Pedro Reis Santos e Thibault Langlois. Editora: LTC. Capítulo: 2. Ano: 2018. ISBN: 978-85-216-3515-4. Comentário: os autômatos �nitos são constituídos por um conjunto de estados e por transições dirigidas e rotuladas entre esses estados. Os rótulos são símbolos da gramática ou ε. Um desses estados é chamado inicial, podendo ter um ou mais estados �nais. O autômato �nito, aliás, pode ser representado gra�camente ou por uma tabela. Disponível em: Minha Biblioteca. 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 37/46 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 38/46 Conclusão Caro(a) estudante, chegamos ao �nal deste material e, nele, vimos que as linguagens de programação têm a função de gerar instruções que se transformam em programas para que computadores realizem o processamento. Existe uma grande necessidadede facilitar a comunicação homem-máquina, e, por isso, programadores sempre buscam criar programas que sejam fáceis de usar, respeitando logicamente as funções a serem realizadas. Do ponto de vista da facilidade, compiladores têm a função de transformar a criação dos programados (códigos-fontes) num produto, o programa. No entanto algumas linguagens não permitem serem compiladas; dessa forma, a escolha pela linguagem a ser utilizadas versus sua utilização é um fator importante. Logicamente, pode-se utilizar interpretadores, mas, a depender do caso, a compilação será fundamental. Você percebeu que o processo de compilação necessita percorrer o texto do código- fonte apenas uma única vez para obter a compilação. Já a interpretação necessita percorrer várias vezes o código-fonte, ou seja, toda vez que esse for utilizado. Mesmo existindo diferentes notações na especi�cação para as linguagens, a Forma Normal de Backus (BNF), que é uma metalinguagem, vem sendo bastante utilizada, devido à sua facilidade de compreensão. Espero que você tenha se apropriado do conteúdo. 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 39/46 Referênc ias AHO, A. V. et al. Compiladores: princípios, técnicas e ferramentas. São Paulo: Pearson Addison-Wesley, 2008. (Disponível na Biblioteca Virtual). AMEAÇA virtual (2001). [S. l.: s. n.], 2014. 1 vídeo (4 min). Publicado pelo canal mortaiters. Disponível em: https://www.youtube.com/watch?v=uoBQo1NWrE8. Acesso em: 3 mar. 2022. AUGER - ambiente para construção e simulação de autômatos �nitos. Evoluma, [2022]. Disponível em: http://www.evoluma.com/auger/ Acesso em: 3 mar. 2022. BARBOSA, C. da S. et al. Compiladores. Porto Alegre: SAGAH, 2021. BRANCO JÚNIOR, G. A.; TAMAE, R. Y. Uma breve introdução ao estudo e implementação de compiladores. Revista Cientí�ca Eletrônica de Sistema de informações, [s. l.], ano V, n. 8, 6 p., fev. 2008. Disponível em: http://faef.revista.inf.br/imagens_arquivos/arquivos_destaque/RHXqIjJHvJQhhCK_2 013-5-28-11-13-48.pdf. Acesso em: 3 mar. 2022. FEDOZZI, R. Compiladores. Londrina: Editora e Distribuidora Educacional S.A., 2018. LANGLOIS, T.; SANTOS, P. R. Compiladores: da teoria à prática. Rio de Janeiro: LTC, 2018. (Disponível na Minha Biblioteca). https://www.youtube.com/watch?v=uoBQo1NWrE8 http://www.evoluma.com/auger/ http://faef.revista.inf.br/imagens_arquivos/arquivos_destaque/RHXqIjJHvJQhhCK_2013-5-28-11-13-48.pdf 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 40/46 LODEUN, K. C. Compiladores: princípios e práticas. São Paulo: Cengage Learning, 2004. MENEZES, P. F. B. Linguagens formais e autômatos. Porto Alegre, Grupo A, 2011. NIEMANN, T. A guide to LEX & YACC. e-papers: information online, [s. l.], 39 p., [2018]. Disponível em: https://arcb.csc.ncsu.edu/~mueller/codeopt/codeopt00/y_man.pdf. Acesso em: 3 mar. 2022. REBELO, M. N. Desenvolvimento de um protótipo de um gerador de analisador léxico. 2002. 71 f. Trabalho de Conclusão de Curso (Bacharelado em Ciências da Computação) — Universidade Regional de Blumenau, Blumenau, 2002. Disponível em: http://www.inf.furb.br/departamento/arquivos/tccs/monogra�as/2002- 2michelnogueirarebelovf.pdf. Acesso em: 3 mar. 2022. https://arcb.csc.ncsu.edu/~mueller/codeopt/codeopt00/y_man.pdf http://www.inf.furb.br/departamento/arquivos/tccs/monografias/2002-2michelnogueirarebelovf.pdf 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 41/46 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 42/46 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 43/46 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 44/46 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 45/46 11/06/2023, 19:19 E-book https://student.ulife.com.br/ContentPlayer/Index?lc=e6IUL5ncVpNnpafasMtHtw%3d%3d&l=1OdIzZ8xcachsr3pzfvcBA%3d%3d&cd=euiSKCRHJrkiU… 46/46
Compartilhar