A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

CES-41 COMPILADORES Capítulo III Diagramas de Transições.

Apresentações semelhantes


Apresentação em tema: "CES-41 COMPILADORES Capítulo III Diagramas de Transições."— Transcrição da apresentação:

1 CES-41 COMPILADORES Capítulo III Diagramas de Transições

2 Capítulo III – Diagramas de Transições 3.1 – Considerações iniciais 3.2 – Uma linguagem ilustrativa: Mini-Pascal 3.3 – Análise léxica por diagramas de transições 3.4 – Análise sintática por diagramas de transições 3.5 – Tabela de símbolos em diagramas de transições 3.6 – Testes semânticos em diagramas de transições 3.7 – Geração de código intermediário

3 3.1 – Considerações Iniciais Diagramas de transições: usados na construção do front- end de um compilador Diagramas de transições: usados na construção do front- end de um compilador Forma didática de concepção de um front-end Forma didática de concepção de um front-end Há outros métodos mais eficientes, porém menos didáticos Há outros métodos mais eficientes, porém menos didáticos A seguir, análises léxica, sintática e semântica e geração de código intermediário por diagramas de transições A seguir, análises léxica, sintática e semântica e geração de código intermediário por diagramas de transições Diagrama de transições léxicas é um autômato finito determinístico Diagrama de transições léxicas é um autômato finito determinístico

4 Exemplo: Diagrama de transições para reconhecer constantes numéricas em Fortran d é um dígito genérico

5 Arcos de qualquer vértice para o vértice Erro não são mostrados, mas existem Arcos de qualquer vértice para o vértice Erro não são mostrados, mas existem d é um dígito genérico

6 Estado não final Estado final

7 São reconhecidas constantes como: 13, +13, -13, 13., 1.25,.25, -.25, , 13E-15, 13.E-15, E+72,.75E5 São reconhecidas constantes como: 13, +13, -13, 13., 1.25,.25, -.25, , 13E-15, 13.E-15, E+72,.75E5 d é um dígito genérico

8 Para as transições sintáticas usa-se vários diagramas de transições; um para cada não-terminal Para as transições sintáticas usa-se vários diagramas de transições; um para cada não-terminal Existem linguagens para as quais é difícil ou até impossível a utilização de diagramas de transições sintáticas Existem linguagens para as quais é difícil ou até impossível a utilização de diagramas de transições sintáticas Para ilustrar será utilizada a linguagem Mini-Pascal extraída de Pascal, apresentada logo a seguir Para ilustrar será utilizada a linguagem Mini-Pascal extraída de Pascal, apresentada logo a seguir

9 3.2 – Uma linguagem ilustrativa: Mini-Pascal – Gramática do Mini-Pascal A gramática do Mini-Pascal não é recursiva à esquerda, mas apresenta a ambiguidade dos comandos condicionais A gramática do Mini-Pascal não é recursiva à esquerda, mas apresenta a ambiguidade dos comandos condicionais Não tem subprogramas, nem variáveis indexadas e seu único comando repetitivo é o while Não tem subprogramas, nem variáveis indexadas e seu único comando repetitivo é o while Não-terminais estão em itálico Não-terminais estão em itálico Terminais são átomos obtidos do analisador léxico; são apresentados com LETRAS MAIÚSCULAS, ou com os caracteres que os identificam Terminais são átomos obtidos do analisador léxico; são apresentados com LETRAS MAIÚSCULAS, ou com os caracteres que os identificam

10 Produções da gramática: Produções da gramática: Prog PROGRAM ID ; Decls CmdComp. Decls ε VAR ListDecl ListDecl DeclTip DeclTip ListDecl DeclTip ListId : Tip ; ListId ID ID, ListId Tip INTEGER BOOLEAN CmdComp BEGIN ListCmd END ListCmd Cmd Cmd ; ListCmd Cmd CmdIf CmdWhile CmdRead CmdWrite CmdAtrib CmdComp

11 Produções da gramática (continuação 1) : Produções da gramática (continuação 1) : CmdIf IF Expr THEN Cmd | IF Expr THEN Cmd ELSE Cmd CmdWhile WHILE Expr DO Cmd CmdRead READ ( ListId ) CmdWrite WRITE ( ListW ) ListW ElemW ElemW, ListW ElemW Expr CADEIA CmdAtrib ID := Expr

12 Produções da gramática (continuação 2) : Produções da gramática (continuação 2) : Expr ExprSimpl ExprSimpl OPREL ExprSimpl ExprSimpl Term Term OPAD ExprSimpl Term Fat Fat OPMULT Term Fat ID CTE ( Expr ) TRUE FALSE OPNEG Fat OPNEG Fat

13 3.2.2 – Especificações léxicas Cada átomo tem pelo menos um atributo chamado tipo Cada átomo tem pelo menos um atributo chamado tipo Conforme o tipo do átomo, ele poderá ter outros atributos Conforme o tipo do átomo, ele poderá ter outros atributos Se o átomo é uma palavra reservada, seu tipo é a própria palavra reservada e não há outros atributos Se o átomo é uma palavra reservada, seu tipo é a própria palavra reservada e não há outros atributos Tabela de palavras reservadas: Tabela de palavras reservadas:

14 3.2.2 – Especificações léxicas Átomo identificador: seu tipo é ID e seu outro atributo é a cadeia de seus caracteres; sua sintaxe é Átomo identificador: seu tipo é ID e seu outro atributo é a cadeia de seus caracteres; sua sintaxe é letra ( letra | dígito )* Caracteres de identificadores que excederem o número de 16 são ignorados Caracteres de identificadores que excederem o número de 16 são ignorados Constantes inteiras: seu tipo é CTE e seu outro atributo é o seu valor inteiro; esse valor tem de caber em 2 bytes Constantes inteiras: seu tipo é CTE e seu outro atributo é o seu valor inteiro; esse valor tem de caber em 2 bytes Cadeias de caracteres: vêm entre apóstrofos ( ); têm como tipo, CADEIA, e, como outro atributo, a cadeia de seus caracteres sem os apóstrofos Cadeias de caracteres: vêm entre apóstrofos ( ); têm como tipo, CADEIA, e, como outro atributo, a cadeia de seus caracteres sem os apóstrofos

15 Tabela dos tipos e atributos dos operadores: Tabela dos tipos e atributos dos operadores: OPAD : operador aditivo OPMULT : operador multiplicativo OPNEG : operador negador OPREL : operador relacional

16 Tabela dos tipos dos separadores (não possuem outros atributos): Tabela dos tipos dos separadores (não possuem outros atributos): Os programas em Mini-Pascal não têm comentários Os programas em Mini-Pascal não têm comentários Espaços em branco entre átomos são opcionais, com a exceção das palavras reservadas Espaços em branco entre átomos são opcionais, com a exceção das palavras reservadas Essas não podem estar concatenadas com outras e com identificadores e constantes inteiras Essas não podem estar concatenadas com outras e com identificadores e constantes inteiras

17 3.3 – Análise Léxica por Diagramas de Transições – Objetivos da análise léxica Os caracteres do programa são grupados em átomos Os caracteres do programa são grupados em átomos Os átomos têm sua validade verificada Os átomos têm sua validade verificada Os átomos válidos são classificados e recebem seus atributos Os átomos válidos são classificados e recebem seus atributos

18 Exemplo: Programa para o cálculo do fatorial de um numero lido: PROGRAM fatorial; VAR n, fat, i: INTEGER; BEGIN READ (n); fat := 1; i := 1; WHILE i <= n DO BEGIN fat := fat * i; i := i + 1 END; WRITE (O fatorial de, n, eh, fat) END. Tabela de átomos e seus atributos

19

20 3.3.2 – Diagrama de transições A estrutura de um analisador léxico pode ser montada sobre um diagrama de transições de estados A estrutura de um analisador léxico pode ser montada sobre um diagrama de transições de estados O diagrama é uma só entidade, mas, por razões didáticas, está apresentado em várias figuras O diagrama é uma só entidade, mas, por razões didáticas, está apresentado em várias figuras Uma figura para cada transição que parte do estado inicial Uma figura para cada transição que parte do estado inicial Supõe-se que, no estado inicial, o analisador já tenha em mãos um caractere Supõe-se que, no estado inicial, o analisador já tenha em mãos um caractere

21 a) Uma letra é o primeiro caractere Em cada transição: Em cada transição: Caractere(s) responsável(eis) Caractere(s) responsável(eis) Ações antes da transição Ações antes da transição

22 Forma Cadeia: introduz caractere numa cadeia Forma Cadeia: introduz caractere numa cadeia Pega Caractere: lê novo caractere do programa; retorna \0 para end- of-file Pega Caractere: lê novo caractere do programa; retorna \0 para end- of-file Class Cadeia: classifica cadeia formada Class Cadeia: classifica cadeia formada Forma Átomo: forma novo átomo com o tipo obtido da classificação; se for ID, o atributo será a cadeia formada Forma Átomo: forma novo átomo com o tipo obtido da classificação; se for ID, o atributo será a cadeia formada Possíveis átomos: Palavra reservada OPMULT - AND OPAD - OR OPNEG - NOT ID - cadeia

23 b) Um dígito é o primeiro caractere Forma número: obtém o número inteiro correspondente à cadeia formada Forma número: obtém o número inteiro correspondente à cadeia formada Forma Átomo: forma novo átomo com o número formado e com o tipo CTE Forma Átomo: forma novo átomo com o número formado e com o tipo CTE Átomo formado: CTE - número inteiro

24 c) Um apóstrofo é o primeiro caractere Se o fecha-apóstrofo for esquecido, o resto do programa será guardado em cadeia Se o fecha-apóstrofo for esquecido, o resto do programa será guardado em cadeia Átomo formado: CADEIA - cadeia

25 d) Um dos caracteres + - * / ~ = é o primeiro Class Caractere: classifica caractere lido Class Caractere: classifica caractere lido Possíveis átomos: OPMULT - VEZES OPMULT - DIV OPAD - MAISOPAD - MENOS OPNEG - NEGOPREL - IGUAL

26 e) O caractere < é o primeiro Possíveis átomos: OPREL - MENIG OPREL - DIFER OPREL - MENOR

27 f) O caractere > é o primeiro Possíveis átomos: OPREL - MAIG OPREL - MAIOR

28 g) O caractere : é o primeiro Possíveis átomos: ATRIB DPONTS

29 h) Um dos caracteres ;., ( ) é o primeiro Possíveis átomos: PVIRG PONTO VIRG ABPAR FPAR

30 i) Um dos caracteres \0,, \n, \t, \r, ou qualquer outro é o primeiro Possíveis átomos: FINAL INVAL Átomo de tipo FINAL: artificial

31 3.3.3 – Implementação de um diagrama de transições léxicas Primeiramente, será apresentada uma função main para gerenciar a classificação de todos os átomos de um programa em Mini-Pascal Primeiramente, será apresentada uma função main para gerenciar a classificação de todos os átomos de um programa em Mini-Pascal Essa função tem a simples finalidade de testar o analisador léxico Essa função tem a simples finalidade de testar o analisador léxico Ela não será usada quando esse analisador estiver integrado ao analisador sintático Ela não será usada quando esse analisador estiver integrado ao analisador sintático

32 void main () { printf ("A N A L I S E L E X I C A\n\n"); printf ("Nome do arquivo: "); fflush (stdin); gets (nomearq); program = fopen (nomearq, "r"); result = fopen ("atomosmp", "w"); carac = NovoCarac (); while (carac) { NovoAtomo (); ImprimeAtomo (); } printf ("\nAnalise do arquivo '%s' encerrada", nomearq); printf ("\n\nVer atomos no arquivo 'atomosmp'"); getch (); } Variáveis globais: nome nomearq; FILE *program, *result; char carac; atomo atom;char *cadeia; typedef struct atomo atomo; struct atomo { int tipo; atribatomo atrib; }; typedef union atribatomo atribatomo; union atribatomo { char *cadeia; long valor; int atr; char carac; }; NovoAtomo: coloca em atom o tipo e o atributo do próximo átomo do programa; é o centro do analisador léxico NovoCarac: retorna o próximo caractere lido do programa; retorna \0 caso seja encontrado end-of-file

33 A função NovoAtomo: Coloca na estrutura atom o tipo e o atributo do próximo átomo encontrado Coloca na estrutura atom o tipo e o atributo do próximo átomo encontrado Implementa o caminhamento pelo diagrama de transições léxicas Implementa o caminhamento pelo diagrama de transições léxicas A seguir o esquema geral de NovoAtomo A seguir o esquema geral de NovoAtomo

34 void NovoAtomo () { int estado = 1; if (atom.tipo == ID || atom.tipo == CADEIA) free (atom.atrib.cadeia); cadeia = malloc(MAXCADEIA*sizeof(char)); *cadeia = 0; while (estado != 3) switch (estado) { case 1: ; break; case 2: ; break; case 4: ; break; case 5: ; break; case 6: ; break; case 7: ; break; case 8: ; break; } free (cadeia); } Caso o átomo anterior tenha como atributo uma cadeia, ela deve ser desalocada Preparação para uma eventual formação de cadeia Depois de formado o átomo, a cadeia é desalocada Aqui ocorrem as transições de estados e o preparo do átomo

35 Transições a partir do Estado 1

36 case 1: switch (carac) { case '\'': ; estado = 5; break; case '+': case '-': case '*': case '/': case '~': case '=': case ';': case '.': case ',': case '(': case ')': ; estado = 3; break; case '<': ; estado = 6; break; case '>': ; estado = 7; break; case ':': ; estado = 8; break; case '\0': ; estado = 3; break; default: if (isalpha (carac)) { ; estado = 2;} else if (isdigit (carac)) { ; estado = 4;} else if ((isspace(carac) || iscntrl(carac)) && (carac != 0)) { ; estado = 1; } else { ; estado = 3; } }break;

37 case 1: switch (carac) { default: if (isalpha (carac)) { FormaCadeia (); carac = NovoCarac(); estado = 2;} else if (isdigit (carac)) { FormaCadeia (); carac = NovoCarac(); estado = 4;}

38 case 1: switch (carac) { case '\'': carac = NovoCarac( ); estado = 5; break;

39 case 1: switch (carac) { case '+': case '-': case '*': case '/': case '~': case '=': case ';': case '.': case ',': case '(': case ')': atom = Classifica (); carac = NovoCarac(); estado = 3; break;

40 case 1: switch (carac) { case '<': carac = NovoCarac(); estado = 6; break; case '>': carac = NovoCarac(); estado = 7; break; case ':': carac = NovoCarac(); estado = 8; break;

41 case 1: switch (carac) { case '\0': atom.tipo = FINAL; estado = 3; break; default: if else if ((isspace(carac) || iscntrl(carac)) && (carac != 0)) { carac = NovoCarac(); estado = 1;} else {atom.tipo = INVAL; atom.atrib.carac = carac; carac = NovoCarac(); estado = 3; } carac = NovoCarac(); estado = 3; }

42 case 2: if (isalnum (carac)) { FormaCadeia (); carac = NovoCarac(); estado = 2;} else { atom = ClassificaCadeia (); estado = 3;} break; case 4: if (isdigit (carac)) { FormaCadeia (); carac = NovoCarac();estado = 4;} else {atom = FormaNumero (); estado = 3;} break;

43 case 6: if (carac == '=') { atom.tipo = OPREL; atom.atrib.atr = MENIG; carac = NovoCarac();} else if (carac == '>'){ atom.tipo = OPREL; atom.atrib.atr = DIFER; carac = NovoCarac();} else { atom.tipo = OPREL; atom.atrib.atr = MENOR; } estado = 3; break; Outros estados ficam como exercícios

44 Funções auxiliares: void FormaCadeia (void): void FormaCadeia (void): Armazena o novo caractere lido no final da variável cadeia Armazena o novo caractere lido no final da variável cadeia É chamada para formar a cadeia de um identificador, palavra reservada, número ou constante cadeia de caracteres, ou um dos operadores and, or ou not É chamada para formar a cadeia de um identificador, palavra reservada, número ou constante cadeia de caracteres, ou um dos operadores and, or ou not atomo ClassificaCadeia (void): atomo ClassificaCadeia (void): Classifica uma cadeia de caracteres Classifica uma cadeia de caracteres Possíveis classes: Possíveis classes: IdentificadorIdentificador palavra reservadapalavra reservada operadores and, or e not;operadores and, or e not; Retorna o átomo formado (tipo e atributo) Retorna o átomo formado (tipo e atributo)

45 Funções auxiliares: atomo FormaNumero (void): atomo FormaNumero (void): Converte uma cadeia de dígitos decimais em seu valor numérico Converte uma cadeia de dígitos decimais em seu valor numérico Retorna o átomo formado (tipo e atributo) Retorna o átomo formado (tipo e atributo) atomo Classifica (void): atomo Classifica (void): Classifica átomos formados por apenas um caractere, exceto os inválidos Classifica átomos formados por apenas um caractere, exceto os inválidos Retorna o átomo formado (tipo e atributo se for o caso) Retorna o átomo formado (tipo e atributo se for o caso) int PalavraReserv (void): int PalavraReserv (void): Verifica se uma cadeia é uma palavra reservada Verifica se uma cadeia é uma palavra reservada Retorna seu tipo, em caso positivo Retorna seu tipo, em caso positivo

46 Definição de constantes simbólicas para as palavras reservadas, para os outros tipos de átomos e para os atributos dos operadores (#defines): Definição de constantes simbólicas para as palavras reservadas, para os outros tipos de átomos e para os atributos dos operadores (#defines):

47 3.4 – Análise Sintática por Diagramas de Transições – Objetivos da análise sintática Verificar a estrutura sintática de um programa Verificar a estrutura sintática de um programa Servir de esqueleto para: Servir de esqueleto para: Construção da tabela de símbolos Construção da tabela de símbolos Análise semântica Análise semântica Geração do código intermediário Geração do código intermediário Exemplo: árvore sintática do programa do fatorial (várias figuras) Exemplo: árvore sintática do programa do fatorial (várias figuras)

48

49

50

51

52

53

54 3.4.2 – Diagramas de transições Análise sintática por diagramas de transições é um método top-down preditor: Análise sintática por diagramas de transições é um método top-down preditor: - Top-down: Partindo do símbolo inicial, através de derivações diretas, vai simulando a construção do programa analisado - Preditor: Um só átomo é suficiente para decidir qual produção usar para fazer uma derivação direta

55 Características de um método preditor: Características de um método preditor: - Os átomos são analisados um por um, do início para o final do programa - Para decidir qual produção usar numa derivação direta, não é necessário checar um átomo já analisado - Não é necessário olhar para algum átomo que vai aparecer mais adiante - A gramática não pode ser recursiva à esquerda - A gramática deve estar fatorada à esquerda (assunto a ser estudado no capítulo sobre análise sintática)

56 A gramática do Mini-Pascal admite análise sintática preditora, tal como o método dos diagramas de transições A gramática do Mini-Pascal admite análise sintática preditora, tal como o método dos diagramas de transições Muitas gramáticas não admitem métodos preditores Muitas gramáticas não admitem métodos preditores Requerem a análise de átomos futuros e/ou passados Requerem a análise de átomos futuros e/ou passados

57 Usa-se um diagrama para cada não-terminal Usa-se um diagrama para cada não-terminal Nas transições, usa-se terminais ou não-terminais (na análise léxica: caracteres) Nas transições, usa-se terminais ou não-terminais (na análise léxica: caracteres) Exemplo para não-terminais: sejam as produções: Exemplo para não-terminais: sejam as produções: Y X..... X X Percorrer diagrama de X Diagrama de Y Diagrama de X

58 A seguir, diagramas de transições sintáticas de cada não- terminal da gramática do Mini-Pascal A seguir, diagramas de transições sintáticas de cada não- terminal da gramática do Mini-Pascal Incluídas transições para tratamento de erros sintáticos Incluídas transições para tratamento de erros sintáticos Tal tratamento é bem simples, só a título de ilustração Tal tratamento é bem simples, só a título de ilustração

59 a) Prog PROGRAM ID PVIRG Decls CmdComp PONTO FINAL

60 ExecTransic (X): Percorre o diagrama de X, antes de mudar de estado Estados 9 e 10: Tratamento de erro Incondicional: Mudança incondicional de estado

61 b) Decls ε VAR ListDecl

62 c) ListDecl DeclTipo DeclTipo ListDecl Para facilitar a construção do diagrama, pode-se escrever suas produções de outra maneira: ListDecl ( DeclTipo )+

63 d) DeclTipo ListId DPONTS Tip PVIRG

64 e) ListId ID ID VIRG ListId Pode-se escrever suas produções de outra maneira: ListId ID ( VIRG ID )*

65 f) Tip INTEGER BOOLEAN

66 g) CmdComp BEGIN ListCmd END

67 h) ListCmd Cmd Cmd PVIRG ListCmd Pode-se escrever suas produções de outra maneira: ListCmd Cmd ( PVIRG Cmd )*

68 i) Cmd CmdIf CmdWhile CmdRead CmdWrite | CmdAtrib CmdComp

69 j) CmdIf IF Expr THEN Cmd | IF Expr THEN Cmd ELSE Cmd Ambiguidade: a sub-forma sentencial Ambiguidade: a sub-forma sentencial IF Expr THEN IF Expr THEN Cmd ELSE Cmd tem duas árvores sintáticas tem duas árvores sintáticas Regra de solução: o ELSE corresponde ao último THEN encontrado Regra de solução: o ELSE corresponde ao último THEN encontrado O diagrama de transições resolve o problema O diagrama de transições resolve o problema

70 j) CmdIf IF Expr THEN Cmd | IF Expr THEN Cmd ELSE Cmd

71 k) CmdWhile WHILE Expr DO Cmd

72 l) l) CmdRead READ ABPAR ListId FPAR

73 m) m) CmdWrite WRITE ABPAR ListW FPAR

74 n) ListW ElemW ElemW VIRG ListW Pode-se escrever suas produções de outra maneira: ListW ElemW ( VIRG ElemW )*

75 o) o) ElemW CADEIA Expr

76 p) p) CmdAtrib ID ATRIB Expr

77 q) q) Expr ExprSimpl ExprSimpl OPREL ExprSimpl Pode-se escrever suas produções de outra maneira: Expr ExprSimpl ( OPREL ExprSimpl ) ?

78 r) ExprSimpl Term Term OPAD ExprSimpl Pode-se escrever suas produções de outra maneira: ExprSimpl Term ( OPAD Term )*

79 s) Term Fat Fat OPMULT Term Pode-se escrever suas produções de outra maneira: Term Fat ( OPMULT Fat )*

80 t) Fat ID CTE TRUE FALSE ABPAR Expr FPAR OPNEG Fat

81 3.4.3 – Implementação dos diagramas de transições sintáticas Primeiramente, uma função main para acionar o analisador sintático Primeiramente, uma função main para acionar o analisador sintático

82 void main () { printf ("A N A L I S E S I N T A T I C A\n\n"); printf ("Nome do arquivo: "); fflush (stdin); gets (nomearq); program = fopen (nomearq, "r"); result = fopen ("atomosmp", "w"); erro = FALSE; carac = NovoCarac (); NovoAtomo (); ExecProg (); printf ("\nAnalise do arquivo '%s' encerrada", nomearq); if (erro) printf ("\n\nPrograma com erros!!!"); printf ("\n\nVer analise no arquivo 'atomosmp'"); getch (); } Variáveis globais:logic erro nome nomearq; FILE *program, *result; char carac;atomo atom;char *cadeia; ExecProg: implementa o diagrama de transições do não- terminal Prog ; é o centro do analisador sintático

83 a)A função ExecProg:

84 void ExecProg () { int estado = 1; while (estado != 8) switch (estado) { case 1: if (atom.tipo == PROGRAM) {NovoAtomo (); estado = 2;} else {Esperado ("PROGRAM"); estado = 9;} break; case 2: if (atom.tipo == ID) {NovoAtomo (); estado = 3;} else {Esperado ("IDENTIFICADOR"); estado = 9;} break; case 3: if (atom.tipo == PVIRG) {NovoAtomo (); estado = 4;} else {Esperado ("PONTO E VIRGULA"); estado = 9; } break;

85 case 4: ExecDecls (); estado = 5; break; case 5: ExecCmdComp (); estado = 6; break; case 6: if (atom.tipo == PONTO) {NovoAtomo (); estado = 7;} else {Esperado ("PONTO"); estado = 10;} break; case 7: if (atom.tipo == FINAL) estado = 8; else {Esperado ("END OF FILE"); estado = 10;} break; case 9: if (atom.tipo == PVIRG) {NovoAtomo (); estado = 4;} else if (atom.tipo == FINAL) estado = 8; else {NovoAtomo (); estado = 9;} break; case 10: if (atom.tipo == FINAL) estado = 8; else {NovoAtomo (); estado = 10;} break;}}

86 b) b) A função ExecDecls: void ExecDecls () { int estado = 11; while (estado != 13) switch (estado) { case 11: if (atom.tipo == VAR) {NovoAtomo (); estado = 12;} else estado = 13; break; case 12: ExecListDecl (); estado = 13; break;}}

87 c) c) A função ExecListDecl: void ExecListDecl () { int estado = 14; while (estado != 16) switch (estado) { case 14: ExecDeclTipo (); estado = 15; break; case 15: if (atom.tipo == ID) estado = 14; else estado = 16; break;}}

88 d) d) A função DeclTipo:

89 void ExecDeclTipo () { int estado = 17; while (estado != 21) switch (estado) { case 17: ExecListId (); estado = 18; break; case 18: if (atom.tipo == DPONTS) {NovoAtomo (); estado = 19;} else {Esperado ("DOIS PONTOS"); estado = 22;} break; case 19: ExecTip (); estado = 20; break; case 20: if (atom.tipo == PVIRG) {NovoAtomo (); estado = 21;} else {Esperado ("PONTO E VIRGULA"); estado = 22;} break; case 22: if (atom.tipo == PVIRG) {NovoAtomo (); estado = 21;} else if (atom.tipo == FINAL) estado = 21; else {NovoAtomo (); estado = 22;} break; } } Funções para outros não-terminais ficam como exercícios

90 3.5 – Tabela de Símbolos em Diagramas de Transições – Objetivos da tabela de símbolos Agregar informações sobre todos os identificadores do programa Agregar informações sobre todos os identificadores do programa Disponibilizar essas informações para: Disponibilizar essas informações para: – Análise semântica – Geração do código intermediário

91 Para o Mini-Pascal, considerando só a fase de análise, as informações são as seguintes: Cadeia de caracteres do identificador Cadeia de caracteres do identificador Tipo do identificador: Tipo do identificador: – Nome de programa – Nome de variável – Nome de função (para o Pascal padrão) – Nome de procedimento (para o Pascal padrão)

92 Se for variável: Se for variável: – Tipo da variável (inteira, booleana) – Se é indexada (para o Pascal padrão) – Se tem inicialização – Se é referenciada Para a fase de síntese, outras informações: Para a fase de síntese, outras informações: – Endereço de memória – Número de bytes ocupados, etc.

93 3.5.2 – Estrutura de dados para a tabela de símbolos Pode-se usar estrutura de hashing aberto Pode-se usar estrutura de hashing aberto Função para o hashing: Função para o hashing:Onde: – NCLASSHASH é o número de classes. – n é o número de caracteres de x (sem o \0)

94 Exemplo: Tabela de símbolos (hashing) do programa do fatorial (NCLASSHASH = 23)

95 Neste exemplo, as classes têm somente 0 e 1 símbolo; Em outros, as listas das classes podem ser maiores.

96 Declarações para a tabela de símbolos: typedef struct celsimb celsimb; typedef celsimb *simbolo; struct celsimb { char *cadeia; int tid, tvar; logic inic, ref; simbolo prox; }; Variáveis globais: simbolo simb; simbolo tabsimb[NCLASSHASH];

97 3.5.3 – Implementação da tabela de símbolos em diagramas de transições A geração da tabela de símbolos é feita nas ações dos diagramas de transições sintáticas A geração da tabela de símbolos é feita nas ações dos diagramas de transições sintáticas O símbolo com o nome do programa é inserido na produção do não-terminal Prog O símbolo com o nome do programa é inserido na produção do não-terminal Prog

98 Ampliado a seguir:

99 InsereSimb (atom.atrib.cadeia, IDPROG); Insere na tabela de símbolos o atributo cadeia do átomo recém-formado, como sendo do tipo identificador de programa Insere na tabela de símbolos o atributo cadeia do átomo recém-formado, como sendo do tipo identificador de programa Retorna um ponteiro para a célula inserida na tabela de símbolos Retorna um ponteiro para a célula inserida na tabela de símbolos Sua programação consiste em inserir numa tabela hashing Sua programação consiste em inserir numa tabela hashing

100 Os nomes de variáveis são inseridos nas transições do não terminal ListId Os nomes de variáveis são inseridos nas transições do não terminal ListId

101 O diagrama de ListId é chamado: O diagrama de ListId é chamado: – No diagrama de DeclTip, na região das declarações – No diagrama de CmdRead, na região dos comandos Diagrama de DeclTip Diagrama de CmdRead

102 A inserção deve ocorrer na região das declarações e não na dos comandos A inserção deve ocorrer na região das declarações e não na dos comandos aqui sim aqui não Diagrama de DeclTip Diagrama de CmdRead

103 Pode-se usar uma variável-flag de nome declarando (global): Pode-se usar uma variável-flag de nome declarando (global): – Na região de declarações: declarando = VERDADE; – Nas outras regiões: declarando = FALSO; Em ListId, só se deve inserir quando Em ListId, só se deve inserir quando declarando == VERDADE No início da função ExecProg (início da análise sintática): No início da função ExecProg (início da análise sintática): void ExecProg () { int estado = 1; declarando = FALSO; while (estado != 8) switch (estado) { case 1:

104 No diagrama de Decls : No diagrama de Decls : No início, declarando = VERDADE; No início, declarando = VERDADE; No final, declarando = FALSO; No final, declarando = FALSO;

105 No diagrama de ListId, tratamento distinto para No diagrama de ListId, tratamento distinto para declarando == VERDADE declarando == VERDADE declarando == FALSO declarando == FALSO

106

107 ProcuraSimb (atom. atrib. cadeia): Procura na tabela de símbolos a célula que guarda o atributo cadeia do átomo recém-formado Procura na tabela de símbolos a célula que guarda o atributo cadeia do átomo recém-formado

108 ProcuraSimb (atom. atrib. cadeia): Quando encontra, retorna um ponteiro para a célula procurada; quando não, retorna NULL Quando encontra, retorna um ponteiro para a célula procurada; quando não, retorna NULL Sua programação consiste em procurar numa tabela hashing

109 ProcuraSimb (atom. atrib. cadeia): Nas declarações, em caso positivo, é uma dupla declaração Nas declarações, em caso positivo, é uma dupla declaração No comando READ, em caso negativo, é identificador usado mas não declarado No comando READ, em caso negativo, é identificador usado mas não declarado

110 Nas declarações, o tipo da variável só aparece mais adiante, fora do diagrama de ListId Nas declarações, o tipo da variável só aparece mais adiante, fora do diagrama de ListId Podem ser várias variáveis inseridas sem o tipo Podem ser várias variáveis inseridas sem o tipo

111 Solução: colocar os símbolos de uma declaração numa lista linear de símbolos (lista de ponteiros para células - global) Solução: colocar os símbolos de uma declaração numa lista linear de símbolos (lista de ponteiros para células - global) Mais adiante, quando aparecer o tipo na declaração, percorre- se essa lista, adicionando-o em cada célula Mais adiante, quando aparecer o tipo na declaração, percorre- se essa lista, adicionando-o em cada célula

112 Exemplo: i, fat, n: INTEGER; Exemplo: i, fat, n: INTEGER; listsimb: variável global

113 Para adicionar, nas células das variáveis declaradas, a informação sobre o tipo: No diagrama de DeclTip : No diagrama de DeclTip : – A lista global de símbolos é anulada e inicializada vazia, antes da chamada do diagrama de ListId – Depois da chamada do diagrama de Tip, adiciona-se o tipo às referidas células, usando o valor de outra variável global: tipocorrente

114 Para adicionar, nas células das variáveis declaradas, a informação sobre o tipo: E no diagrama de Tip : E no diagrama de Tip :

115 AdicTipoVar adiciona, em cada símbolo da lista linear, a informação contida na variável global tipocorrente i, fat, n: INTEGER;

116 No comando READ, a célula com o nome da variável é marcada como inicializada e referenciada No comando READ, a célula com o nome da variável é marcada como inicializada e referenciada

117 No diagrama de CmdAtrib: Se encontrado na tabela de símbolos, o identificador do lado esquerdo deve ser marcado como inicializado e como referenciado Se encontrado na tabela de símbolos, o identificador do lado esquerdo deve ser marcado como inicializado e como referenciado Se não encontrado, é identificador usado mas não declarado Se não encontrado, é identificador usado mas não declarado

118 No diagrama de Fat : Se encontrado na tabela de símbolos, o identificador deve ser marcado como referenciado Se encontrado na tabela de símbolos, o identificador deve ser marcado como referenciado Se não encontrado, é identificador usado mas não declarado Se não encontrado, é identificador usado mas não declarado

119

120 3.6 – Testes Semânticos em Diagramas de Transições – Especificações semânticas do Mini-Pascal Qualquer identificador de variável usado nos comandos do programa deve estar declarado Qualquer identificador de variável usado nos comandos do programa deve estar declarado Nenhum identificador pode ser declarado mais de uma vez no programa Nenhum identificador pode ser declarado mais de uma vez no programa Toda variável deve ser inicializada e referenciada no programa Toda variável deve ser inicializada e referenciada no programa O nome do programa não pode ser usado como variável O nome do programa não pode ser usado como variável

121 Especificações relacionadas com expressões: Num comando de atribuição, a expressão e a variável que recebe seu valor devem ser do mesmo tipo Num comando de atribuição, a expressão e a variável que recebe seu valor devem ser do mesmo tipo Os operadores +, -, ~, *, / e os relacionais, >= só admitem operandos inteiros Os operadores +, -, ~, *, / e os relacionais, >= só admitem operandos inteiros Os operandos dos operadores = e <> devem ser de mesmo tipo Os operandos dos operadores = e <> devem ser de mesmo tipo Os operadores AND, OR e NOT só admitem operandos booleanos Os operadores AND, OR e NOT só admitem operandos booleanos As expressões nos cabeçalhos dos comandos IF e WHILE devem ser booleanas As expressões nos cabeçalhos dos comandos IF e WHILE devem ser booleanas

122 3.6.2 – Detecção de identificadores de variáveis não- declaradas Ao ser usado num comando, um identificador deve estar na tabela de símbolos Ao ser usado num comando, um identificador deve estar na tabela de símbolos O tipo do identificador deve ser IDVAR O tipo do identificador deve ser IDVAR Um identificador é usado em: Um identificador é usado em: – Comandos READ – Lado esquerdo de comandos de atribuição – Fatores de expressões

123 a) Detecção em Comandos READ: no diagrama do ListId

124 b) Detecção no lado esquerdo de um comando de atribuição:

125 c) Detecção no fator de uma expressão :

126 3.6.3 – Detecção de dupla declaração de identificadores No diagrama de ListId, ao ser declarado, um identificador não deve estar na tabela de símbolos No diagrama de ListId, ao ser declarado, um identificador não deve estar na tabela de símbolos

127 3.6.4 – Detecção de identificadores não referenciados e não inicializados Percorrer todas as classes de TabSimb Visitar célula por célula em cada classe Reportar aquelas marcadas como não referenciadas e/ou não inicializadas TabSimb

128 3.6.5 – Determinação do tipo das expressões Os testes semânticos relacionados com expressões requerem a determinação do tipo de expressões e sub-expressões: Os testes semânticos relacionados com expressões requerem a determinação do tipo de expressões e sub-expressões: – Os operadores +, -, ~, *, / e os relacionais, >= só admitem operandos inteiros – Os operandos dos operadores =, <> devem ser de mesmo tipo – Os operadores AND, OR e NOT só admitem operandos booleanos – Num comando de atribuição, a expressão e a variável que recebe seu valor devem ser do mesmo tipo – As expressões nos cabeçalhos dos comandos IF e WHILE devem ser booleanas

129 Sejam as seguintes produções contendo operadores do Mini- Pascal: Sejam as seguintes produções contendo operadores do Mini- Pascal: Expr ExprSimpl ( OPREL ExprSimpl )? ExprSimpl Term ( OPAD Term )* Term Fat ( OPMULT Fat )* Fat OPNEG Fat Cada OPREL é cercado por duas ExprSimpls Cada OPREL é cercado por duas ExprSimpls Cada OPAD é cercado por dois Terms Cada OPAD é cercado por dois Terms Cada OPMULT é cercado por dois Fats Cada OPMULT é cercado por dois Fats Cada OPNEG é seguido por um Fat Cada OPNEG é seguido por um Fat Esses não-terminais representam os operandos de tais operadores

130 Expr ExprSimpl ( OPREL ExprSimpl )? ExprSimpl Term ( OPAD Term )* Term Fat ( OPMULT Fat )* Fat OPNEG Fat Os tipos dos operandos devem obedecer às especificações de compatibilidade com tais operadores Os tipos dos operandos devem obedecer às especificações de compatibilidade com tais operadores Idéia: a execução dos diagramas de Expr, ExprSimpl, Term e Fat pode retornar o tipo da sub-expressão que representam

131 int ExecExpr () { int ret; return ret; } int ExecExprSimpl () { int ret; return ret; } int ExecTerm () { int ret; return ret; } int ExecFat () { int ret; return ret; } ret: variável de retorno Deve guardar o tipo do não-terminal do diagrama executado O valor de ret deve ser calculado durante a execução do diagrama Idéia: a execução dos diagramas de Expr, ExprSimpl, Term e Fat pode retornar o tipo da sub-expressão que representam

132 Diagrama de Fat (função ExecFat): Seja cada um dos caminhos que levam, sem erros, ao estado 81

133 Na produção Fat ID: Na produção Fat ID: O tipo de Fat é o tipo da variável representada por ID

134 Nas produções Fat CTE | TRUE | FALSE Nas produções Fat CTE | TRUE | FALSE O tipos de Fat são respectivamente inteiro, booleano e booleano: FALSE

135 Na produção Fat ( Expr ): Na produção Fat ( Expr ): O tipo de Fat é o tipo de Expr a ser apresentado adiante

136 Produção Fat OPNEG Fat : O tipo de Fat do lado esquerdo deve ser o tipo admitido pelo atributo de OPNEG O tipo de Fat do lado esquerdo deve ser o tipo admitido pelo atributo de OPNEG O atributo de OPNEG pode ser: O atributo de OPNEG pode ser: – NOT, que só admite operando booleano – NEG, que só admite operando inteiro É necessário um teste de compatibilidade entre o atributo de OPNEG e o tipo de Fat do lado direito É necessário um teste de compatibilidade entre o atributo de OPNEG e o tipo de Fat do lado direito

137 Produção Fat OPNEG Fat : oper: variável local inteira, para guardar o atributo de um operador Em caso de erro, retorna-se o tipo admitido pelo atributo de OPNEG Da análise sintática

138 Term Fat ( OPMULT Fat )* Diagrama de Term: Term Fat ( OPMULT Fat )* Ao transitar de 75 para 76 pela primeira vez, não há teste de compatibilidade Ao voltar de 76 para 75, deve haver teste entre o OPMULT e o Fat anterior Ao transitar de 75 para 76 depois da primeira vez, deve haver teste entre o Fat e o OPMULT anterior Função ExecTerm

139 Term Fat ( OPMULT Fat )* Diagrama de Term: Term Fat ( OPMULT Fat )* Para não haver teste de compatibilidade, ao passar pela primeira vez: oper = 0, no início de ExecTerm

140 Term Fat ( OPMULT Fat )* Diagrama de Term: Term Fat ( OPMULT Fat )* O valor de ret veio de Fat na última transição de 75 para 76

141 Diagrama de ExprSimpl : ExprSimpl Term ( OPAD Term )* Estratégia análoga ao diagrama de Term

142 Diagrama de ExprSimpl : ExprSimpl Term ( OPAD Term )* oper = 0, no início de ExecExprSimpl

143 Diagrama de ExprSimpl : ExprSimpl Term ( OPAD Term )*

144 Diagrama de Expr: Expr ExprSimpl ( OPREL ExprSimpl )? Ao transitar de 68 para 69 não há teste de compatibilidade Ao transitar de 69 para 70, deve haver teste entre o OPREL e o ExprSimpl anterior Ao transitar de 70 para 71, deve haver teste entre o novo ExprSimpl e o OPREL anterior

145 Diagrama de Expr: Expr ExprSimpl ( OPREL ExprSimpl )?

146 Diagrama de Expr: Expr ExprSimpl ( OPREL ExprSimpl )?

147 Diagrama de Expr: Expr ExprSimpl ( OPREL ExprSimpl )? O tipo de uma expressão relacional é booleano

148 Diagrama de CmdAtrib: CmdAtrib ID ATRIB Expr O tipo de Expr deve ser o mesmo da variável correspondente ao ID

149 Diagrama de CmdAtrib: CmdAtrib ID ATRIB Expr tvar: variável local destinada a guardar o tipo da variável

150 Diagrama de CmdAtrib: CmdAtrib ID ATRIB Expr texpr: variável local destinada a guardar o tipo da expressão

151 Diagrama de CmdIf: CmdIf IF Expr THEN Cmd | IF Expr THEN Cmd ELSE Cmd | IF Expr THEN Cmd ELSE Cmd O tipo de Expr deve booleano

152 Diagrama de CmdIf: CmdIf IF Expr THEN Cmd | IF Expr THEN Cmd ELSE Cmd | IF Expr THEN Cmd ELSE Cmd

153 Diagrama de CmdWhile: CmdWhile WHILE Expr DO Cmd O tipo de Expr deve booleano

154 Diagrama de CmdWhile: CmdWhile WHILE Expr DO Cmd

155 3.7 – Geração de Código Intermediário Supor que serão utilizadas quádruplas Supor que serão utilizadas quádruplas A geração das quádruplas deve estar contida nas ações dos diagramas de transições sintáticas A geração das quádruplas deve estar contida nas ações dos diagramas de transições sintáticas Exemplo: Código intermediário não otimizado para o programa fatorial: Exemplo: Código intermediário não otimizado para o programa fatorial:

156 openmod: aloca memória para as variáveis locais e parâmetros de um módulo A estrutura de dados para essas quádruplas será vista em capítulo específico. O código intermediário deve ser otimizado e traduzido para Assembly


Carregar ppt "CES-41 COMPILADORES Capítulo III Diagramas de Transições."

Apresentações semelhantes


Anúncios Google