Sintax Graph Designer

Manual do Usuário
Versão 3.0 referente à versão 1.0 do SGD

Sumário



1. Introdução:
    1.1 O SGD.
    1.2 Finalização.
    1.3 Definições.

2. Modo de Uso:
    2.1 Utilização da barra de ferramentas.
    2.2 Criação de nós.
    2.3 Alteração das propriedades dos nós.
    2.4 Ligação dos nós.
    2.5 Utilização do menu.
    2.6 Práticas de bom uso.

3. Funcionamento:
    3.1 Estrutura Geral.
    3.2 Definição de um nó: A Classe CCell.
    3.3 Ligações de um nó: A Classe Arrow.
    3.4 Funções.
    3.5 Mensagens do Windows.

4. Alteração do Programa:
    4.1 Estado Atual do SGD.
    4.2 Comentários.
    4.3 Alteração das Funções.
    4.4 Criação de funções pelo usuário.
    4.5 Observações.

5. Glossário

6. Bibliografia



1. Introdução

1.1 O SGD
    O Sintax Graph Designer (SGD) é um sistema gráfico que permite ao usuário desenhar grafos sintáticos do tipo ESLL(1) [Setzer 1] para o sistema operacional Windows. Ele pode gerar um arquivo de saída contendo a declaração de um grafo sintático em C++ em forma de um vetor, para uso de um analisador sintático do tipo ESLL(1), conforme definido por Setzer em [Setzer 198x, 19xx]; no primeiro há uma definição informal, e no segundo uma definição formal tanto dos grafos como do algoritmo de análise sintática e das estratégias de correção de erros sintáticos. As gramaticas do tipo ESLL(1) são uma classe das gramáticas LL(1) [Aho 1] com lados direitos das produções podendo conter expressões regulares, isto é, com alternativas fatoradas, fechamentos transitivos, e símbolos opcionais [Setzer 2].
    O SGD foi criado para ser um programa Open Source, isto é, para que fosse publicado na internet e qualquer programador pudesse-o utilizar e alterar conforme suas necessidades.

    Usaremos as seguintes notações. Acionar o mouse significa pressionar o seu botão esquerdo. Acionar o mouse na posicão x significa colocar o cursor do mouse na posição x e depois acioná-lo. Doubleclick é o ato de se acionar duas vezes rapidamente o botão esquerdo do mouse. Mover o mouse significa mover o cursor do mouse por meio de movimentos deste. Arrastar o mouse da posição x até a posição y significa acionar o mouse na posição x e sem soltar o botão do mouse, mover o mouse até a posição y, e só então soltar o botão do mouse. Selecionar um nó significa acionar o botão do mouse no local onde se encontra o nó desejado e o mesmo se aplica para selecionar uma seta. Uma área de seleção é uma área dentro da área de trabalho na qual todos os nós serão selecionados. Para traçar uma área de seleção, basta acionar o mouse numa posição sem elementos da área de trabalho e arrastar o mouse até outro ponto. Durante o arrasto será mostrado um retângulo tracejado, e a área dentro deste retângulo é a área de seleção. Quando o botão do mouse for solto, o retângulo delimitando a área de seleção desaparecerá e todos os nós que estavam dentro da área de seleção nesta hora estarão selecionados.

1.2 Finalização
    O programa está com as funcionalidades básicas implementadas, permitindo o desenho confortável de grafos e a criação do arquivo necessário para o analisador sintático com relativa facilidade. As funcionalidades implementadas estão descritas abaixo.

1.3 Definições
    Grafo sintático é um grafo orientado desconexo que representa graficamente uma gramática; cada produção da gramática é representada por um subgrafo, sem arestas ligando-o com outros subgrafos. Assim, um grafo sintático, como qualquer gramática, define uma linguagem formal.
    Nó é uma representação de um símbolo de uma produção da gramática. A seqüência dos símbolos das produções é representada por arestas do grafo. Como o grafo é orientado, denominaremos as arestas de setas, para facilidade de compreensão e melhor aderência à simbologia gráfica. Cada nó pode ser do tipo Cabeça, Terminal, Não-Terminal e nó Vazio. Os nós do tipo Cabeça são a definição de um símbolo Não-Terminal e são os que começam os subgrafos que compõem cada grafo. São representados graficamente por um hexágono. Os nós Não-Terminais representam o uso de um símbolo não terminal, são nós Cabeça quando se encontram dentro de outro subgrafo, eles representam os subgrafos que já foram ou serão definidos. São representados graficamente por um retângulo. Os nós Terminais representam nós contendo um símbolo terminal da gramática, com as devidas informações sobre seu conteúdo. São representados graficamente por um retângulo com cantos arredondados. E por último, os nós "Vazios" que são nós terminais especiais com uma cadeia vazia. São representados graficamente por um círculo. Todas essas informações devem ser disponibilizadas graficamente. Cada nó deve armazenar o nome do símbolo gramatical que representa, o tipo de nó, seu sucessor e sua alternativa e o nome da rotina semântica associada ao nó.
    Uma seta liga um nó origem a um nó destino para onde ela aponta. Uma seta pode ser de dois tipos: seta sucessora e seta alternativa. A seta sucessora de um nó n aponta para o nó com o símbolo da produção que se segue a n, e sempre sai pelo lado direito de n. A seta alternativa de n aponta para o nó cujo símbolo deve ser o primeiro símbolo alternativo para o atual na produção, e sempre sai pelo lado inferior do nó origem. Note-se que, por terem lados direitos com expressões regulares, símbolos alternativos podem ocorrer em qualquer ponto de um lado direito. As setas sucessoras são diferenciadas graficamente das setas alternativas por sua grossura, sendo a seta alternativa mais grossa que a sucessora. As setas são compostas por segmentos de reta, que são retas finitas delimitadas por pontos, e uma ponta, denotada graficamente por um "V" no final do último segmento de reta da seta.
    Após mover um nó que aponta ou é apontado por alguém, as setas serão simplificadas automaticamente mas isso pode acarretar setas com mau comportamento, isto é, passando por dentro de nós ou escondendo-se atrás de outras setas. Deve-se procurar corrigir. Veja. como na seção [2.4 Ligação entre dois nós].
    A posição de um elemento gráfico pode ser definida pelo local onde ele se encontra dentro da área de trabalho. Cada nó possui uma posição calculada com base num ponto que fica um pouco à esquerda do seu centro. A área de trabalho possui uma grade invisível que serve para facilitar o posicionamento dos nós na tela de modo a deixá-los alinhados uns com os outros. Quando um nó é criado ou movido, sua posição é calculada e ele é movido para se encaixar dentro dessa grade.


2. Modo de Uso

    Como o objetivo deste programa é desenhar grafos sintáticos tem-se, na barra de ferramentas (segunda linha da tela), as funções mais básicas, aquelas de uso mais freqüente, isto é, criar nós e , eliminar elementos gráficos, desfazer e refazer mudanças. Importar e exportar grafos estão localizados no menu, as propriedades de um nó podem ser alteradas com o acionamento do botão direito do mouse sobre o nó desejado e a seleção de nós pode ser feita graficamente.

2.1 Utilização da barra de ferramentas
    Na barra de ferramentas, tem-se os seguintes botões, na ordem de sua exibição, da esquerda para a direita:
          [1] - Criar nó cabeça;
          [2] - Criar nó terminal;
          [3] - Criar nó não-terminal;
          [4] - Criar nó vazio;
          [5] - Criar seta sucessor;
          [6] - Criar seta alternativa;
          [7] - Apagar elementos gráficos;
          [8] - Desfazer mudança;
          [9] - Refazer mudança.
    Os quatro primeiros botões (que criam nós), ao serem acionados, permanecerão "pressionados" graficamente até que o usuário acione outro dos seis primeiros botões [1-6], ou pressione o botão esquerdo do mouse numa posição vazia da janela. Neste segundo caso, um nó do tipo selecionado será criado. Os dois botões seguintes (que criam setas) [5-6], ao serem acionados, permanecerão "pressionados" até que o usuário acione outro dos seis primeiros botões [1-6], ou pressione o botão esquerdo do mouse num nó. Neste segundo caso, uma seta do tipo selecionado será criada, tendo sua origem neste nó.
     O sétimo botão (intitulado Delete) [7] irá apagar da janela qualquer elemento ou grupo de elementos que estiverem selecionados (veja como selecionar elementos gráficos nas próximas seções) no momento em que o botão for acionado. Para desfazer alguma mudança no grafo, basta acionar o oitavo botão [8] da barra de ferramentas, e para refazer algo que foi desfeito, basta acionar o nono botão [9]. Só são permitidos cinco acionamentos válidos seguidos em cada botão, ou seja, só se pode desfazer ou refazer mudanças cinco vezes seguidas.

2.2 Criação de nós
     Para se criar um nó, basta acionar o botão do nó do tipo desejado e em seguida, pressionar o botão esquerdo do mouse com seu cursor na posição vazia da janela onde se quer que o nó fique. Caso a posição onde o cursor estava quando o botão esquerdo do mouse foi acionado esteja ocupada, o nó não será criado. Todos os nós, ao serem criados, não possuem nome ou rotina semântica associada ao nó. O usuário não pode mexer na sua posição absoluta na tela, pois o programa irá aproximá-la para a grade pré definida. Para criar-se mais de um nó do mesmo tipo do nó criado, basta segurar o botão Ctrl do teclado ao pressionar o botão esquerdo do mouse na área de trabalho. Se o usuário voltar a pressionar o botão esquerdo do mouse na área de trabalho sem estar segurando o botão Ctrl do teclado, será criado mais um nó e o usuário terá que voltar a acionar o botão na barra de ferramentas para criar outro. Todo nó, ao ser criado, passa a ser o único nó selecionado do grafo.

2.3 Alteração das propriedades dos nós
     Todos os nós possuem propriedades as seguintes propriedades: posição e tamanho, até nome do símbolo gramatical que representa, tipo e rotina semântica associada ao nó. Pode-se fazer o acesso às propriedades de um nó quando se pressiona o botão direito do mouse sobre o nó cujas propriedades se deseja alterar ou quando se dá doubleclick no nó. Ao fazer isso, uma nova janela se abrirá e irá mostrar as propriedades do nó, permitindo ao usuário alterá-las. Algumas propriedades como o nome do símbolo gramatical que representa, tipo e nome da rotina semântica não podem ser alteradas graficamente, apenas através do uso da janela de propriedades, outras como o tamanho e posição podem ser alteradas sem abrir a janela de propriedades. Para mudar os valores da janela de propriedades, basta pressionar o botão esquerdo do mouse no campo desejado e digitar o novo valor (note-se que posição e tamanho devem ser números inteiros (comece com valores próximos aos que aparecem assim que a janela de propriedades é aberta para ver o que acontece).
    Um nó também pode ser movido pela área de trabalho e ter seu tamanho alterado graficamente. Para movê-lo, basta selecionar o nó desejado e arrastar o mouse pela área de trabalho, até a posição desejada. Para alterar seu tamanho, acione o mouse no nó e 8 quadrados pequenos aparecerão ao redor do nó. Estes são os quadrados de tamanho e ao serem arrastados com o mouse, irão alterar o tamanho do nó, e talvez mudar um pouco sua aparência para se adequar às novas dimensões. Arrastando-se os quadrados em um lado horizontal ou vertical produz-se um aumento do tamanho deste lado; arrastando-se uma dos quadrados na diagonal, produz-se um aumento dos tamanhos dos lados do nó correspondentes a essa diagonal.
     Vários nós podem ser movimentados ou terem seus tamanhos aumentados ou diminuídos simultaneamente, para isso basta traçar uma área de seleção na área de trabalho que contenha os nós que se deseja alterar, e após estarem todos selecionados basta alterar um deles que os outros terão as mesmas alterações. Se por exemplo um dos nós selecionados for movido, todos os selecionados serão movidos na mesma direção e o mesmo espaço que o primeiro foi movido. O mesmo serve para alterar seu tamanho.
     Outras propriedades de um nó incluem seu sucessor e alternativa, mas isso será discutido nas próximas seções.

2.4 Ligação entre dois nós
     Como foi visto, cada nó pode possuir um nó sucessor e um nó alternativa. O nó sucessor indica qual símbolo deve ser esperado depois do atual, e o alternativa representa qual símbolo pode ser esperado no lugar deste. Um nó deve ser ligado ao seu sucessor por uma seta sucessora, que sempre sai pelo lado direito do nó, enquanto que a alternativa deve ser ligada por uma seta alternativa, que sempre sai do lado de baixo do nó. OBS: a seta pode aparentar estar saindo pelo lado oposto do nó caso o usuário não tenha ligado corretamente as setas. Isso significa que uma seta sucessor estaria saindo pelo lado esquerdo do nó e uma seta alternativa estaria saindo pelo lado superior do nó. Para ligar um nó origem m a um nó destino n, seleciona-se inicialmente o tipo de seta desejado, acionando-se a botão correspondente. Em seguida, aciona-se o mouse no nó n, arrasta-se o mouse traçando o caminho que se deseja, e finalmente aciona-se o mouse sobre o nó n. Caso já exista uma seta apontando para o nó n, pode-se acionar o mouse sobre a seta apontando para n, e o nó destino passará a ser n. Esta facilidade impede que os grafos fiquem muito confusos. Existem duas maneiras de traçar uma seta, utilizando o autotracer ou manualmente.
     O autotracer é uma opção especial do SGD que procura conectar quaisquer dois pontos na área de trabalho, utilizando apenas três segmentos de reta consecutivos, criando assim uma pequena "escada". Para cada ponto da área de trabalho que o usuário acionar o mouse, novas três setas ligadas serão criadas e a direção original será alterada em 90°. O usuário pode escolher o sentido em que a seta aponta. O autotracer deve ser usado apenas para se fazer ligações simples pois suas setas ficam complexas e desorganizadas. Ele já está ligado assim que o programa é iniciado Para ligações mais complicadas, o modo manual, descrito a seguir, é recomendado devido ao maior controle que ele oferece.
     O modo manual é mais restritivo que o autotracer e por isso evita confusões. Ao iniciar a criação de uma seta, do mesmo modo descrito no autotracer, o usuário só pode movê-la na direção inicial dela(para baixo para seta alternativa e para a direita para seta sucessora). Cada vez que o usuário aciona o mouse na área de trabalho, a seta traça um ângulo reto no sentido que o usuário escolher.
     Setas podem ser simplificadas. Isso significa que podemos diminuir o número de segmentos, fundindo dois paralelos que estão ligados por um único segmento. Para simplificar uma seta o usuário deve primeiro selecionar a seta que deseja simplificar. Ao selecioná-la, seus quadrados de movimento irão aparecer. O usuário deve então acionar o mouse sobre o quadrado de movimento do segmento de reta que deseja mover e, sem soltar o botão, mover o quadrado de movimento até um segmento de reta paralelo a este, que pertença a esta seta. O segmento movido e o segmento de destino devem estar ligados por apenas um segmento de reta. Enquanto o segmento estiver sendo movido, uma reta tracejada irá aparecer para ajudar o usuário a se localizar na área de trabalho. Quando os dois segmentos estiverem se sobrepondo, o usuário deve soltar o botão do mouse e então os dois segmentos irão se fundir, eliminando o segmento que havia entre eles.
     Para mudar o nó apontado por uma seta basta acionar o mouse sobre a ponta da seta que se deseja mover e, sem soltar o botão do mouse, mover a ponta até o nó que se deseja ter como destino. Note que a seta pode se simplificar durante este processo.

2.5 Utilização o menu
     O menu principal tem quatro opções: 'File', 'Edit', 'Options' e 'About'. Cada uma delas pode ser utilizada com um acionamento do mouse sobre seu nome, ou utilizando o teclado, ao segurar a tecla Alt e acionar o botão do teclado correspondente a letra sublinhada no menu.
     - O submenu File é o que utiliza as funções que salvam ou abrem arquivos. Dentro dele temos:
          - Open, para abrir um grafo salvo em um arquivo;
          - Save, para salvar o grafo sendo utilizado;
          - Save as, para salvar o grafo sendo utilizado em outro arquivo ou outro diretório;
          - Import, importa um grafo de um arquivo e coloca-o no final do que está atualmente na área de trabalho, ou seja, após a posição do nó cuja posição é a mais inferior;
          - Generate graph, gera o arquivo de saída em uma linguagem para ser lida por um analisador sintático. Ver seção [3.4 Funções];
          - Exit, sai do programa.
     - O submenu Edit, com o qual se pode fazer mudanças no grafo, com:
          - Delete, apaga qualquer objeto que esteja selecionado, corresponde ao botão desse nome;
          - Undo, desfaz até cinco mudanças no grafo consecutivas, corresponde ao botão desse nome;
          - Redo, refaz até cinco acionamentos do menu (ou botão) undo, corresponde ao botão desse nome;
     - O submenu Options, no qual se pode alterar opções do programa, com:
          - Automatic tracer, liga ou desliga o autotracer (passando ao traçado de manual de setas). Uma marca ao seu lado indica que está ligado.
          - Compilation, define se ao gerar o código de saída, o SGD deve deixá-lo pronto para ser compilado.
          - Interpretation, define se ao gerar o código de saída, o SGD deve deixá-lo pronto para ser interpretado.
          OBS: Um grafo pode gerar código para ser compilado ou para ser interpretado, um por vez. As diferenças entre o código compilado e interpretado estão descritas em [3.4 Funções].
     - O menu Help, só possui uma opção:
          - About, mostra a versão do programa e seu programador.

2.6 Práticas de bom uso
          - Sempre deixar os nós perto de seu sucessor e alternativa.
          - Sempre que possível, uma setas sucessora deve apontar para o nó sucessor pelo lado esquerdo deste. Uma seta alternativa deve apontar por cima do nó alternativo.
          - Ao traçar uma seta, se o nó destino já possui uma seta chegando a ele, deve-se tentar fazer com que a primeira aponte para a segunda.
          - Após ter criado uma seta, deve-se tentar simplificá-la o máximo possível (eliminando segmentos de reta desnecessários).
          - Deve-se tomar cuidado com nós cujo tamanho é maior que o original, pois podem cobrir outros nós ou ficar por cima de segmentos de setas.


3. Funcionamento

3.1 Estrutura Geral
     O programa é dividido em 2 classes, suas funções e as funções do programa principal. Objetos de cada uma das classes podem ser criados e alterados tanto no programa principal como na outra classe. Existem duas listas ligadas para cada classe, criadas e alteradas no programa principal através do uso das várias funções que estão disponíveis. As listas ligadas estão divididas em dois tipos, aquelas cujos membros correspondem a objetos cujas representações gráficas estão selecionadas e aqueles objetos cujas representações gráficas não estão selecionadas (o motivo disso é que as propriedades de um objeto só podem ser alteradas se este estiver selecionado, e com duas listas temos maior controle, velocidade e visualização sobre o que está acontecendo). Tanto os nós como as setas possuem esta divisão em duas listas.

3.2 Definição de um nó: A Classe CCell
     Esta é a classe onde cada objeto é um nó, e aqui guardamos todas as suas propriedades: nome do símbolo gramatical que representa, nome da rotina semântica associada ao nó, tipo, tamanho, posição, sucessor (representado por apontador para um objeto de tipo seta) e alternativa (idem). Aqui temos todas as funções que alteram essas propriedades.

3.3 Ligações de um nó: A Classe Arrow
     Esta é a classe onde cada objeto é uma seta, cuja finalidade é mostrar quem é o sucessor ou alternativa do nó de onde esta começa. Como isso é feito graficamente, e as setas podem ser bem complexas (isto é, conter muitos segmentos), temos muitas variáveis para guardar os atributos necessários, como os pontos delimitadores de cada segmento de reta, seus quadrados de movimento e outros. As setas possuem uma ponta para indicar para onde estão apontando e por conseqüência conhece-se o nó destino.

3.4 Funções
     No programa principal existem várias funções para alterar as listas ligadas de setas e nós, as próprias setas e os nós, cuidar da saída e da entrada e para tratar das mensagens do Windows. Muitas destas funções não precisavam realmente ser funções, mas foram programadas assim para que o programa ficasse mais modular e compreensível.
     A função "MakeOutputFile()" é a função que utilizando as informações disponíveis no grafo irá gerar a saída num arquivo chamado "carrega.cpp" que será lido pelo analisador sintático. O arquivo está no formato de dois vetores sendo uma para quando o arquivo for compilado e outra para quando este for interpretado. Cada linha deste arquivo é uma célula, contendo todas as propriedades de um nó, incluindo seu sucessor e alternativa. Neste arquivo existe uma propriedade extra que é um identificador para o nó, e por esse identificador podemos saber quem é o nó sucessor e o alternativa.

3.5 Mensagens do Windows
     O Windows funciona por meio de mensagens. Para cada evento que ocorre ele envia uma mensagem para o programa dizendo qual foi o evento. Teclado e mouse, ao serem usados, enviam mensagens. As mensagens possuem alguns parâmetros e através deles podemos saber que tipo de evento ocorreu e a sua posição na tela.
     Como neste programa não precisamos fazer nada enquanto o usuário não provocar um evento, como por exemplo mover o mouse, acioná-lo, etc., todas as funções são apenas chamadas após o usuário ter feito algo no teclado ou mouse.


4. Alteração do Programa

4.1 Estado Atual do SGD
     O SGD está completamente funcional, com todas as funcionalidades básicas requeridas para se construir um grafo sintático, salvá-lo e alterá-lo com relativa facilidade. Existem ainda diversas funcionalidades que poderiam ser implementadas, algumas facilmente outras dificilmente.

4.2 Comentários no programa
     Sempre que possível foi feito o comentário de um trecho de código antes mesmo de criá-lo, e quem quiser alterar o programa não terá muitos problemas em entender o código. Os comentários procuram fazer três coisas: descrever o que um determinado trecho de código faz, descrever o porque e ressaltar pedaços que podem ser confusos. Cada função possui um comentário que resumi o que ela faz, localizado logo acima da mesma.

4.3 Alteração das Funções
     Algumas das funções podem ser alteradas facilmente para suprir as necessidades do programador. Por exemplo, se o analisador sintático que será usado para ler o código gerado para um grafo e interpretá-lo usa um formato ou uma linguagem diferente de C++, basta alterar a função "MakeOutputFile()".
     O programador deve ter cuidado ao alterar uma função, para não alterar uma parte essencial do código que não deveria ser mudada, como por exemplo algum apontador essencial, o que pode dar problemas. Para solucionar isso, (o que é que você quer dizer? Solucionar os problemas ou descobrir o que pode ou não ser mudado??) veja o item seguinte.

4.4 Criação de funções pelo usuário
     Para alterações um pouco mais complexas é recomendável que se crie funções próprias. Se estas forem parecidas com alguma já existente, sugerimos copiar o código e depois o alterá-lo. Isso deve ajudar a impedir problemas mais sérios e deve acelerar o desenvolvimento.

4.5 Observações
        - É importante observar quais variáveis são globais e quais não são. A função "WndProc()", que recebe as mensagens do Windows, possui algumas variáveis estáticas porque, sendo uma função, tem suas variáveis apagadas da memória quando termina.
        - Ao usar a barra de rolagem, não é o campo de visão que muda, mas sim o que está sendo mostrado (a visão é fixa, o mundo é que se move), por isso os valores quando se está desenhando.


5. Glossário

     Área de trabalho: região da janela onde se desenha um grafo.
     Barra de Rolagem: Barras que ficam no canto direito e inferior da janela e que podem ser usadas para deslocar o grafo para cima e para baixo.
     Doubleclick: o ato de se pressionar duas vezes rapidamente o botão esquerdo do mouse.
     Elemento de um grafo: Um nó ou uma seta mostrados na área de trabalho.
     Elemento Selecionado: Qualquer elemento gráfico que tenha sido acionado com o botão esquerdo do mouse ou tenha acabado de ser criado. Denotado graficamente por pequenos quadrados, circundando um nó ou nos segmentos de reta de uma seta.
     Janela: Espaço gráfico do programa. Compreende toda a área de trabalho, o menu, a barra de ferramentas e as barras de rolagem.
     Quadrados de Movimento: Pequenos quadrados que aparecem no meio dos segmentos de reta de uma seta quando selecionados.
     Quadrados de Tamanho: Pequenos quadrados que aparecem ao redor de um nó quando selecionado.


6. Bibliografia

     [Setzer 1] - "Simple sintax graphs, their parse with automatic error recovery and an ANSI C simple sintax graph", Valdemar W. Setzer e Roberto C. Mayer
     [Setzer 2] - "A construção de um compilador" Valdemar W. Setzer e Inês S. Homem de Melo
     [Aho 1] - "Theory of Parsing, Translation and Compiling" Alfred V. Aho, Jeffrey D. Ullman



20/12/200
Autor: Giuliano Luz Pigatti Caliari
Orientador: Valdemar W. Setzer  





Este manual também está disponível no formato Word 97 para Windows.


 

Voltar para a página inicial