| Anotação Estrutural de Documentos e sua Semântica | ||
|---|---|---|
| Prev | Apêndice C. Conversão de DTDs para Gramáticas | Next |
Cada um dos atributos no DTD vai corresponder a um símbolo não-terminal na gramática de atributos.
O SGML permite definir atributos de vários tipos. Apresenta-se, primeiro, uma regra geral que deverá ser aplicada sempre, independentemente do tipo do atributo. A seguir, apresentam-se as regras que permitem converter os tipos mais usuais de atributos.
Se elem tem atributos, sejam eles att1, ..., attn.
A sua declaração no DTD seria:
<!ATTLIST elem att1 att1-type att1-def-value
...
attn attn-type attn-def-value>A produção principal correspondente à regra geral, é:
elemAttList → Att1 ... Attnonde Atti é o símbolo não-terminal introduzido para representar o atributo atti.
att1-type, ..., attn-type representam o tipo de cada um dos atributos: enumerado, CDATA, NUMERICAL, ID, IDREF, IDREFS, ENTITY, e outros que já não se utilizam. Na declaração de um atributo também podemos associar-lhe um valor por omissão, representado acima por atti-def-value, que deve ser tido em conta sempre que o atributo não for instanciado pelo utilizador. Os valores possíveis para este são os definidos na tabela abaixo: #FIXED seguido de uma string, o que significa que se o atributo for instanciado terá que ser com um valor igual a string; um dos valores pertencentes a um tipo enumerado definido para esse atributo; ou uma das palavras-chave seguintes:
Tabela C-1. Valores por omissão de Atributos
| #IMPLIED | o valor poderá não ser instanciado, o atributo é opcional. |
| #REQUIRED | o utilizador terá obrigatoriamente que instanciar o atributo, este é obrigatório |
| #FIXED | o valor do atributo tem que aparecer a seguir à palavra-chave (ver Secção 7.1, Exemplo 7-3) significando que se o atributo for instanciado terá que ser com um valor igual ao declarado, caso não seja instanciado o sistema assumirá esse valor. |
| #CURRENT | o valor do atributo é herdado da última instância do mesmo elemento onde o valor do atributo foi instanciado (segue-se a ordem ascendente na árvore de elementos) |
| #CONREF | o valor é usado para referências externas (cada vez menos utilizado, não irá ser considerado nas regras que se seguem) |
| valor de um tipo enumerado | um dos valores pertencentes ao tipo enumerado definido para esse atributo. |
O valor por omissão levanta um problema: não é possível derivá-lo da gramática, ou seja, o comportamento deste item é essencialmente semântico - "se o atributo não estiver instanciado, então use-se este valor". Como tal, recorre-se a equações sobre atributos (da gramática de atributos) para o modelar, como se poderá ver nas regras seguintes.
As restantes produções de cada um dos atributos dependem dos seus tipos e valores por omissão. Serão tratadas nas regras que se seguem.
Exemplo C-4. Elemento News com atributos
No caso de estudo do serviço noticioso, o elemento News tinha dois atributos: Type e Subject. Assim, as produções correspondentes são:
News → NewsAttList NewsContent
NewsAttList → Type Subject
O conteúdo do elemento pode ser estruturado ou texto.
Se um atributo att do elemento X for declarado da seguinte maneira:
<!ATTLIST X att (att-val1 | ... | att-valn) att-vali>
é do tipo enumerado: o seu tipo está definido como a lista att-val1, ..., att-valn, e o seu valor por omissão é att-vali com 0<i<n. As produções correspondentes são:
att → att-val1
| ...
| att-valn
| &egr;Os símbolos att-val1, ..., att-valn são símbolos terminais da gramática, correspondem a tokens/palavras-chave fixos; &egr; corresponde à string vazia e esta derivação corresponde à inexistência do atributo na instância documental (a situação em que o utilizador não instancia o atributo) e onde deverá ser assumido o valor por omissão.
Assim as produções anteriores têm de ser enriquecidas com as seguintes equações sobre o atributo gramatical valor, que irá guardar o valor do atributo SGML att:
att → att-val1
valor = f(att-val1)
| ...
...
| att-valn
valor = f(att-valn)
| &egr;
valor = f(att-vali)Aqui e no resto das regras, a função f representa a conversão de tipos necessária para passar o valor devolvido pelo analisador léxico (tipo=string) para o valor pretendido no atributo semântico.
Exemplo C-5. Atributo do tipo enumerado
No sistema noticioso, o elemento News tem um atributo de nome Type do tipo enumerado, com valores Event ou Novelty, o que dá origem às seguintes produções:
Type → event
valor = "Event"
| novelty
valor = "Novelty"Se um atributo for do tipo CDATA, significa que tem um conteúdo textual e a produção correspondente é:
att → str
valor = f(str)O símbolo str é um símbolo terminal da gramática resultante.
Se um atributo for do tipo NUMERICAL, significa que tem um conteúdo numérico e a produção correspondente é:
att → number
valor = f(number)O símbolo number é um símbolo terminal da gramática resultante.
Se um atributo for do tipo ID, significa que tem um conteúdo textual e uma semântica associada: o valor do atributo, instanciado pelo utilizador, tem que ser único, i.e., não pode haver no documento mais nenhum atributo deste tipo instanciado com o mesmo valor. A produção e semântica correspondentes são:
att → ident
if( exists(ident, Tabid) )
erro = "Identificador já existente!"
else insert(ident, Tabid)
valor = f(ident)Se um atributo for do tipo IDREF, significa que tem um conteúdo textual e uma semântica associada, que é o inverso da situação anterior: o valor do atributo, instanciado pelo utilizador, tem que existir na tabela de identificadores, tem que estar declarado num atributo do tipo ID algures no documento. A produção e a semântica correspondentes definem-se como:
att → ident
if( !exists(ident, Tabid) )
erro = "Identificador inexistente!"
valor = f(ident) Se um atributo for do tipo ENTITY, significa que tem um conteúdo textual e uma semântica associada: o valor do atributo, instanciado pelo utilizador, tem que ser o identificador de uma entidade existente na tabela de entidades, tem que estar declarado numa declaração de entidade no DTD (Secção C.4). A produção e a semântica correspondentes definem-se como:
att → ent-ident
if( !exists(ent-ident, Tab-entidade) )
erro = "Entidade inexistente!"
valor = f(ent-ident)Se um atributo for definido com o valor por omissão #IMPLIED, significa que é opcional e as produções correspondentes são:
att → att-val
| &egr;A derivação pela string vazia acresce a uma das conversões anteriores dependendo do tipo. A produção att → att-val representa a produção resultante da conversão do tipo de atributo; ao juntar-se a conversão do valor por omissão acrescentam-se produções à derivação de att e, nalguns casos, alguns atributos e respectivas equações de cálculo.
Se um atributo for definido com o valor por omissão #REQUIRED, significa que é obrigatório e as produções correspondentes são:
att → att-val
| &egr;
erro = "Atributo obrigatório!" A derivação pela string vazia acresce a uma das conversões anteriores dependendo do tipo.
Se um atributo for definido com o valor por omissão #FIXED, significa que o seu valor foi fixo na declaração. O utilizador poderá sempre instanciá-lo mas o valor terá que ser igual ao fornecido na declaração do atributo no DTD. As produções e a semântica correspondentes definem-se como:
att → att-val
if(f(att-val) != Tab-attr(att).valor)
erro = "O valor do atributo não é o esperado!"
valor = Tab-attr(att).valor
| &egr;
valor = Tab-attr(att).valor A derivação pela string vazia e as condições de contexto acrescem a uma das conversões anteriores dependendo do tipo.
Este valor por omissão só se utiliza para atributos pertencentes a elementos que podem aninhar-se. Por exemplo, um documento pode construir a sua hierarquia de secções e subsecções à custa de apenas um elemento secção ao qual, no DTD, se deu permissão para aninhar recursivamente. Assim, uma secção que ocorra dentro de outra secção é uma subsecção daquela ou uma secção de nível dois.
Este tipo de elementos tem, normalmente, atributos, que se forem declarados com o valor por omissão #CURRENT não precisam de estar instanciados, nesse caso, o atributo herdará o seu valor da última instanciação desse atributo percorrendo os elementos de baixo para cima até encontrar um que o tenha instanciado.
As produções e a semântica correspondentes definem-se como:
att → att-val
valor = f(att-val)
| &egr;
valor = Procura(att, ASAD) A função Procura vai tentar calcular o valor do atributo percorrendo a árvore de sintaxe abstracta decorada calculada até ao momento, em ordem ascendente.
A derivação pela string vazia e as condições de contexto acrescem a uma das conversões anteriores dependendo do tipo.