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

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

Capítulo III Diagramas de Transições

Apresentações semelhantes


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

1 Capítulo III Diagramas de Transições
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 Forma didática de concepção de um front-end 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 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
d é um dígito genérico

6 Estado não final Estado final d é um dígito genérico

7 São reconhecidas constantes como: 13, +13, -13, 13. , 1. 25,. 25, -
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
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

9 3.2 – Uma linguagem ilustrativa: Mini-Pascal
3.2.1 – Gramática do Mini-Pascal 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-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

10 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) :
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) :
Expr  ExprSimpl  ExprSimpl OPREL ExprSimpl ExprSimpl  Term  Term OPAD ExprSimpl Term  Fat  Fat OPMULT Term Fat  ID  CTE  ( Expr ) TRUE  FALSE  OPNEG Fat

13 3.2.2 – Especificações léxicas
Cada átomo tem pelo menos um atributo chamado tipo 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 Tabela de palavras reservadas:

14 letra ( letra | dígito )*
3.2.2 – Especificações léxicas Á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 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

15 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):
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 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
3.3.1 – Objetivos da análise léxica Os caracteres do programa são grupados em átomos Os átomos têm sua validade verificada Os átomos válidos são classificados e recebem seus atributos

18 Tabela de átomos e seus atributos
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 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 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: Caractere(s) responsável(eis) Ações antes da transição

22 Forma Cadeia: introduz caractere numa cadeia
Pega Caractere: lê novo caractere do programa; retorna ‘\0’ para end-of-file 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 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 Á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 Átomo formado: CADEIA - cadeia

25 d) Um dos caracteres + - * / ~ = é o primeiro
Class Caractere: classifica caractere lido Possíveis átomos: OPMULT - VEZES OPMULT - DIV OPAD - MAIS OPAD - MENOS OPNEG - NEG OPREL - 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
Átomo de tipo FINAL: artificial Possíveis átomos: FINAL INVAL

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 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

32 nome nomearq; FILE *program, *result;
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 (); typedef struct atomo atomo; struct atomo { int tipo; atribatomo atrib; }; typedef union atribatomo atribatomo; union atribatomo { char *cadeia; long valor; int atr; char carac; }; Variáveis globais: nome nomearq; FILE *program, *result; char carac; atomo atom; char *cadeia; 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 Implementa o caminhamento pelo diagrama de transições léxicas A seguir o esquema geral de NovoAtomo

34 if (atom.tipo == ID || atom.tipo == CADEIA) free (atom.atrib.cadeia);
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); Preparação para uma eventual formação de cadeia Caso o átomo anterior tenha como atributo uma cadeia, ela deve ser desalocada Aqui ocorrem as transições de estados e o preparo do átomo Depois de formado o átomo, a cadeia é desalocada

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)) { 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; }

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;}

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

44 void FormaCadeia (void):
Funções auxiliares: void FormaCadeia (void): 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 atomo ClassificaCadeia (void): Classifica uma cadeia de caracteres Possíveis classes: Identificador palavra reservada operadores and, or e not; Retorna o átomo formado (tipo e atributo)

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

47 3.4 – Análise Sintática por Diagramas de Transições
3.4.1 – Objetivos da análise sintática Verificar a estrutura sintática de um programa Servir de esqueleto para: Construção da tabela de símbolos Análise semântica Geração do código intermediário 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: 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:
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 Muitas gramáticas não admitem métodos preditores Requerem a análise de átomos futuros e/ou passados

57 Percorrer diagrama de X
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) 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
Incluídas transições para tratamento de erros sintáticos 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 ListDecl  ( DeclTipo )+
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 ListCmd  Cmd ( PVIRG Cmd )*
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 IF Expr THEN IF Expr THEN Cmd ELSE Cmd
j) CmdIf  IF Expr THEN Cmd | IF Expr THEN Cmd ELSE Cmd Ambiguidade: a sub-forma sentencial IF Expr THEN IF Expr THEN Cmd ELSE Cmd tem duas árvores sintáticas Regra de solução: o ELSE corresponde ao último THEN encontrado 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) CmdRead  READ ABPAR ListId FPAR

73 m) CmdWrite  WRITE ABPAR ListW FPAR

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

75 o) ElemW  CADEIA  Expr

76 p) CmdAtrib  ID ATRIB Expr

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

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

79 Term  Fat ( OPMULT Fat )*
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

82 Variáveis globais: logic erro nome nomearq; FILE *program, *result;
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;} case 3: if (atom.tipo == PVIRG) {NovoAtomo (); estado = 4;} else {Esperado ("PONTO E VIRGULA"); estado = 9; }

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;} case 9: if (atom.tipo == PVIRG) {NovoAtomo (); estado = 4;} else if (atom.tipo == FINAL) estado = 8; else {NovoAtomo (); estado = 9;} case 10: else {NovoAtomo (); estado = 10;} }

86 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; }

87 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; }

88 d) A função DeclTipo:

89 Funções para outros não-terminais ficam como exercícios
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) 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
3.5.1 – Objetivos da tabela de símbolos Agregar informações sobre todos os identificadores do programa 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 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: 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: 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 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 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 Retorna um ponteiro para a célula inserida na tabela de símbolos 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

101 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 CmdRead Diagrama de DeclTip

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

103 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 declarando == VERDADE No início da função ExecProg (início da análise sintática): void ExecProg () { int estado = 1; while (estado != 8) switch (estado) { case 1:

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

105 No diagrama de ListId , tratamento distinto para
declarando == VERDADE 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

108 ProcuraSimb (atom . atrib . cadeia):
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 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
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) 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;
listsimb: variável global

113 Para adicionar, nas células das variáveis declaradas, a informação sobre o tipo:
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 :

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

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 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 não encontrado, é identificador usado mas não declarado

119

120 3.6 – Testes Semânticos em Diagramas de Transições
3.6.1 – Especificações semânticas do Mini-Pascal Qualquer identificador de variável usado nos comandos do programa deve estar declarado Nenhum identificador pode ser declarado mais de uma vez no programa Toda variável deve ser inicializada e referenciada no programa 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 Os operadores +, -, ~, *, / e os relacionais <, <=, >, >= só admitem operandos inteiros Os operandos dos operadores = e <> devem ser de mesmo tipo Os operadores AND, OR e NOT só admitem operandos booleanos 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 O tipo do identificador deve ser IDVAR 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

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 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:
Expr  ExprSimpl ( OPREL ExprSimpl )? ExprSimpl  Term ( OPAD Term )* Term  Fat ( OPMULT Fat )* Fat  OPNEG Fat Cada OPREL é cercado por duas ExprSimpl’s Cada OPAD é cercado por dois Term’s Cada OPMULT é cercado por dois Fat’s 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 Idéia: a execução dos diagramas de Expr, ExprSimpl, Term e Fat pode retornar o tipo da sub-expressão que representam

131 ret: variável de retorno
Idéia: a execução dos diagramas de Expr, ExprSimpl, Term e Fat pode retornar o tipo da sub-expressão que representam 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

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: O tipo de Fat é o tipo da variável representada por ID

134 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 ):
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 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

137 Produção Fat  OPNEG Fat :
Da análise sintática 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

138 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 oper = 0, no início de ExecTerm
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 Diagrama de Term: Term  Fat ( OPMULT Fat )*
O valor de ret veio de Fat na última transição de 75 para 76

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

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

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

144 Expr  ExprSimpl ( OPREL ExprSimpl )?
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 Expr  ExprSimpl ( OPREL ExprSimpl )?
Diagrama de Expr: Expr  ExprSimpl ( OPREL ExprSimpl )?

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

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

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

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

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

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

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

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

154 CmdWhile  WHILE Expr DO Cmd
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 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:

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 "Capítulo III Diagramas de Transições"

Apresentações semelhantes


Anúncios Google