Synthesizer Generator

(geração de compiladores incrementais)



José Carlos Leite Ramalho






Synthesizer Generator


Especificação da Linguagem

Sintaxe Abstracta
definição dos termos para a árvore de derivação; declaração dos lexemas (terminais)
Sintaxe Concreta
análise sintática das frases (utilização de um atributo para a construção dos termos concretos da árvore)
Regras de formatação ("unparsing")
criação de representações para a árvore de sintaxe (1 ou mais), ex: linguagem fonte e objecto
Atributos
declaração e equações de cálculo: análise semântica
Transformações
transformação dos termos da árvore de sintaxe, expansão de termos mediante interacção com o utilizador


Implementação de um exemplo

Problema:

Pretende-se criar um editor/compilador que assista e valide a escrita de agendas pessoais. As agendas em causa obedecem a uma determinada sintaxe apresentada a seguir e pretende-se que a ferramenta gerada force essa sintaxe e que como produto final gere um ficheiro HTML com a semântica pertinente.

A agenda é composta por um conjunto de entradas. Cada entrada pode ser simples ou um grupo. Por sua vez, um grupo é composto por um conjunto de entradas e assim "ad infinitum".

GIC:

Agenda --> AGENDA  ident  ItemList  END  '.'

ItemList --> Item  ItemList
           |  

Item --> ident  num  num  morada  email  url
       | Grupo

Grupo --> GRUPO  ident  ItemList  FIMGRUPO


Implementação em SGEN

Sintaxe Abstracta


        root ag;
	ag : Agenda(identificador itemlist)
	   ;

	list itemlist;
	itemlist : ItemListNil()
	         | ItemListPair(item itemlist)
	         ;

	item : ItemNull()
	     | Single(identificador num num morada email url)
	     | Group(identificador itemlist)
	     ;

	identificador : IdentNull()
	              | Identifier(TEXTO)
	              ;

	morada : MoradaNull()
	       | Morada(TEXTO)
	       ;

	email : EmailNull()
	      | Email(TEXTO)
	      ;

	url : UrlNull()
	    | Url(TEXTO)
	    ;

	num : NumNull()
	    | Numero(NUMERO)
	    ;


Lexemas

	WHITESPACE:    < [\ \t\n] >;
	AGENDA:        < "AGENDA:" >;
	END:           < "END." >;
	GROUP:         < "***(" >;
	ENDGROUP:      < "*)"   >;

	NUMERO:        < [0-9\.\-\(\)]+ >;
	TEXTO:         < [a-zA-Z\/\~\:\@\.\-\_\?\!0-9\ ]+ >;


Sintaxe Concreta

	AG ::= (AGENDA Id ItemList END)
	       {$$.t = Agenda(Id.t, ItemList.t);};

	ItemList ::= (Item) {$$.t = (Item.t :: ItemListNil);}
	          |  (Item ItemList) {$$.t=(Item.t::ItemList$2.t);}
	          ;

	Item ::= ('+' Id Num Num Mor EM U)
	         {$$.t = Single(Id.t, Num$1.t, Num$2.t, Mor.t, EM.t, U.t);}
	       | (GROUP Id ItemList ENDGROUP) 
                 {$$.t = Group(Id.t, ItemList.t);}
	       ;

	Id ::= (TEXTO) {$$.t = Identifier(TEXTO);};
	Mor ::= (TEXTO) {$$.t = Morada(TEXTO);};
	EM ::= (TEXTO) {$$.t = Email(TEXTO);};
	U ::= (TEXTO) {$$.t = Url(TEXTO);};
	Num ::= (NUMERO) {$$.t = Numero(NUMERO);};


Regras de Associação

	AG 		{syn ag t;};
	Item 		{syn item t;};
	ItemList 	{syn itemlist t;};
	Id 		{syn identificador t;};
	Mor 		{syn morada t;};
	EM 		{syn email t;};
	U 		{syn url t;};
	Num 		{syn num t;};

	ag ~ AG.t;
	item ~ Item.t;
	itemlist ~ ItemList.t;
	identificador ~ Id.t;
	morada ~ Mor.t;
	email ~ EM.t;
	url ~ U.t;
	num ~ Num.t;


Regras de "unparsing"

	ag : Agenda [ @ ::= "AGENDA: " @
                    "     Registos: " itemlist.acount
                    "%t%n" @ "%b%nEND." ];

	itemlist : ItemListNil  [ @ ::= ]
                 | ItemListPair [ @ ::= @ ["%n"] @ ];

	item : ItemNull [ @ ::= "<item>" ]
             | Single   [ @ ::= "--> " @
			  " : " @ " : " @ " : "
			  @ " : " @ " : " @ ]
             | Group   [ @ ::= "*** [" @ "]%t%t%n" @ 
                         "%b%b%n***%n" ];

	identificador : IdentNull  [ @ ::= "<identificador>" ]
                      | Identifier [ @ ::= @ ]
                      ;

	morada : MoradaNull  [ @ ::= "<morada>" ]
               | Morada      [ @ ::= @ ]
               ;

	email : EmailNull  [ @ ::= "<email>" ]
              | Email      [ @ ::= @ ]
              ;

	url : UrlNull  [ @ ::= "<url>" ]
     	    | Url      [ @ ::= @ ]
     	    ;

	num : NumNull [ @ ::= "<numero>" ]
            | Numero  [ @ ::= @ ]
            ;


Geração de Código: outras regras de "unparsing"

	view HTML;

	ag : Agenda [ HTML ^ ::= "<HTML>%t%n"
                      "<TITLE>AGENDA:
		      " ^ "</TITLE>"
                      "<BODY>%t%n"
                      "<UL>%t%n"
		      ^ "%b%n</UL>"
                      "%b%n</BODY>"
                      "%b%n</HTML>"
		    ];

	itemlist : ItemListNil  [ HTML ^ ::= ]
                 | ItemListPair [ HTML ^ ::= ^ ["%n"] ^ ];

	item : ItemNull [ HTML ^ ::= "<LI> <item>" ]
       	     | Single   [ HTML ^ ::= "<LI>
			  " ^ " : " ^ " : " ^ 
                          " : " ^ " : " ^ "
		          : " ^ ]
             | Group    [ HTML ^ ::= "<LI><I> " ^
                          "</I>%t%t%n<OL>%n"
		          ^ "%n</OL>%b%b%n" ]
             ;

	identificador : IdentNull  [ HTML ^ ::= 
                                     "<identificador>" ]
                      | Identifier [ HTML ^ ::= ^ ];

	morada : MoradaNull  [ HTML ^ ::= "<morada>" ]
               | Morada      [ HTML ^ ::= ^ ];

	email : EmailNull  [ HTML ^ ::= "<email>" ]
              | Email      [ HTML ^ ::= "<A HREF=\"mailto:" 
                             ^ "\">email</A>" ];

	url : UrlNull  [ HTML ^ ::= "<url>" ]
            | Url      [ HTML ^ ::= "<A HREF=\"http://"
			 ^ "\">homepage</A>" ];

	num : NumNull [ HTML ^ ::= "<numero>" ]
            | Numero  [ HTML ^ ::= ^ ] ;


Atributos

	itemlist,item {inh INT bcount;
          	       syn INT acount;
         	      };

	ag : Agenda {  itemlist.bcount = 0; };

	itemlist : ItemListNil  { $$.acount = $$.bcount;}
                 | ItemListPair { item.bcount = itemlist$1.bcount;
                                  itemlist$2.bcount = item.acount;
                                  itemlist$1.acount = itemlist$2.acount;
			        };

	item : ItemNull { $$.acount = $$.bcount; }
     	     | Single   { $$.acount = $$.bcount+1; }
     	     | Group    { itemlist.bcount = $$.bcount;
                          $$.acount = itemlist.acount; }
             ;



Editor Gerado

Estado Inicial

janela principal

janela da geração de código


Inserindo entradas

Item selecionado: ficam disponiveis 2 opções

Depois de selecionar "Simples"

Depois de selecionar "Grupo"


Exemplo de uma agenda

agenda na linguagem fonte

agenda em HTML