(geração de compiladores incrementais)
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".
Agenda --> AGENDA ident ItemList END '.' ItemList --> Item ItemList | Item --> ident num num morada email url | Grupo Grupo --> GRUPO ident ItemList FIMGRUPO
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) ;
WHITESPACE: < [\ \t\n] >; AGENDA: < "AGENDA:" >; END: < "END." >; GROUP: < "***(" >; ENDGROUP: < "*)" >; NUMERO: < [0-9\.\-\(\)]+ >; TEXTO: < [a-zA-Z\/\~\:\@\.\-\_\?\!0-9\ ]+ >;
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);};
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;
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 [ @ ::= @ ] ;
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 ^ ::= ^ ] ;
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; } ;