• Sonuç bulunamadı

CENNET VE CEHENNEMİN MEVCUDİYETİ

Belgede Cennet ve cehennemin ebediliği (sayfa 37-43)

O motor de geração de sentenças é implementado na linguagem Lua. O seu código consiste da implementação das funções de gramática, os critérios de cobertura e a função de geração. Nesta seção são apresentadas as implementações das funções de gramática e da função de geração. A codificação destas funções está dividida em dois módulos:

grammar_engine.lua egrammar_engine_EBNF.lua. O primeiro módulo contém as funções de

gramática que pertencem ao padrão BNF [BACKUS, 1959] e a função de geração. No segundo módulo estão codificadas as funções de gramática que são definidas no padrão EBNF e as funçõesnewContexteIdent. Ambos os módulos são importados na especificação

Lua gerada pelo componente tradutor.

Todas as funções de gramática retornam como resultado de sua execução funções anô- nimas que serão executadas durante o processo de derivação das sentenças. Estas funções são chamadas de funções geradoras. Elas têm assinatura padronizada: o retorno é um valor booleano que informa se deve ou não ser interrompido o processo de derivação de uma sentença, apresentado na seção 5.3.2, e seus argumentos são:

1. g: tabela que representa a gramática para qual estão sendo geradas as sentenças.

2. env: tabela que mantém uma lista de não-terminais utilizados durante o processo

de geração das sentenças.

3. prefix: string que mantém o prefixo da sentença que está sendo gerada na execução

da função.

4. maxCycles: número máximo de ciclos, repetições de não-terminais na derivação, per-

mitidos na derivação de uma sentença.

5.3 Motor de Geração 50

6. ’’..." : argumento variável que mantém a lista de não-terminais utilizados até o

momento para derivação de uma sentença.

1 f u n c t i o n t e r m i n a l ( s t r ) 2 c C r i t e r i a . d o T e r m i n a l ( s t r )

3 r e t u r n f u n c t i o n( g , env , p r e f i x , maxCycles , maxDerivLen , . . . ) 4 −− V e r i f i c a p e r m i s s a o nos c r i t e r i o s de c o b e r t u r a 5 i f c C r i t e r i a . c h e c k T e r m i n a l ( s t r ) then 6 l o c a l s = A r r a y L i s t . new ( arg ) 7 c o r o u t i n e . y i e l d ( p r e f i x . . s t r , s ) 8 r e t u r n t r u e 9 end 10 r e t u r n f a l s e 11 end 12 end

Figura 5.9: Função de gramática terminal.

O código da função terminal é listado na figura 5.9. A função terminal recebe como

parâmetro uma cadeia de caracteres que corresponde a um terminal (o parâmetro str),

constrói e devolve uma função geradora específica para este terminal (linhas 3 a 11). Esta função geradora concatena o terminal ao final do parâmetro prefix, esse terminal é recebido

durante a execução pelo argumento str. Esta função geradora retorna através da execução

do comando yield (linha 7), específico para o retorno de valores e suspensão de execução

da corotina correspondente. Este comando yield (linha 7) tem como resultado a string

contendo a porção da sentença gerada até o momento, prefix .. str, e a lista ordenada dos

não-terminais utilizados na derivação desta string. Esta lista é utilizada pelos mecanismos de controle.

As instruções return das linhas 8 e 10 sinalizam a continuidade ou interrupção do pro-

cesso de geração através do retorno do valor true ou false respectivamente. Este padrão

faz parte do esquema de controle citado na seção 5.3.2. Detalhes inerentes à implementa- ção dos critérios de cobertura podem ser observados nas linhas 2 e 5, as informações sobre este processo serão apresentadas na seção 5.4 e não serão mais abordadas nesta seção.

A função alt é apresentada na figura 5.10. Esta função pode ter n parâmetros, re-

presentados pelo argumento variável ..., esse tipo de argumento é acessado pela variável

pré-definida arg como pode ser visto na linha 2. O retorno de alt é uma função geradora

(linhas 4 a 16) que gera sentenças para cada um de seus parâmetros (for da linha 9).

Por exemplo, caso existam dois parâmetros patt1 e patt2 e estes sejam terminais, ambos

serão gerados de maneira independente através do yield das funções geradoras criadas

5.3 Motor de Geração 51

1 f u n c t i o n a l t ( . . . )

2 l o c a l p a t t s = arg −−A r r a y que a c e s s a o s a r g u m e n t o s de . . . 3 c C r i t e r i a . d o A l t ( )

4 r e t u r n f u n c t i o n( g , env , p r e f i x , maxCycles , maxDerivLen , . . . ) 5 l o c a l r s l = f a l s e

6 l o c a l c h e c k P a t t i = c C r i t e r i a . c h e c k A l t ( )

7 −−Caso c h e c k P a t t i == n i l nao r e a l i z a a g e r a c a o d a s s e n t e n c a s p a r a e s s e

֒→ c o n j u n t o de a l t e r n a t i v a s .

8 i f not c h e c k P a t t i then r e t u r n f a l s e end

9 f o r i , p a t t i n i p a i r s ( p a t t s ) do −−I t e r a c a o s o b r e o s p a d r o e s de . . . 10 i f c h e c k P a t t i ( r s l , i , p a t t s . n ) and

11 p a t t ( g , env , p r e f i x , maxCycles , maxDerivLen , unpack ( arg ) ) then 12 r s l = t r u e 13 end 14 end 15 r e t u r n r s l 16 end 17 end

Figura 5.10: Função de gramática alt.

liberação pela função checkPatti proveniente da implementação dos critérios de cobertura.

O resultado da função geradora é computado com base na execução de cada padrão con- tido no argumento da função alt, logo se apenas um dos padrões retornar o valor true a

função retornará true. Isto porque a variável rsl é inicializada com o valor false, linha 5,

e uma vez executado qualquer padrão ela passa a ter o valortrue, linha 12, que é utilizado

como retorno desta função geradora, linha 15.

A funçãoseq, listada na figura 5.11, recebe como argumentos de entrada duas funções, patt1 e patt2, que podem ser funções simples ou compostas. Como as outras funções de

gramática, seq constrói e retorna uma função geradora (linhas 3 a 29) que, no seu caso,

concatena cada resultado da execução depatt1 com cada resultado de patt2. Esta função

geradora utiliza o patt1 para produzir a parte inicial da sentença através da criação de

uma corotinam1nas linhas 6-8 e da execução posterior dem1na linha 11. Nesta execução

a estrutura de controle for é utilizada para consumir cada prefixo de sentença produzido

porm1. Estes trechos e o resultado de cada execução são mantidos nas variáveis stri e rsl

como pode ser visto na linha 11. Uma vez produzido um destes resultados, este é passado para outra corotina definida nas linhas 15 a 17. Esta corotina é executada em um novo

for, definido nas linhas 19 a 25, que produz as sentenças finais para a construção. Caso a

execução da corotinam2sinalize uma interrupção da derivação através da variável rsl02, a

sentença é descartada e uma nova tentativa de execução será realizada pelo laço. Tomando como exemplo dois terminais, a construção executará o primeiro e seu resultado será dado como prefixo para a execução do segundo, desta forma produzindo a concatenação das

5.3 Motor de Geração 52

strings associadas a cada um deles.

1 f u n c t i o n s e q ( p a t t 1 , p a t t 2 ) 2 c C r i t e r i a . doSeq ( )

3 r e t u r n f u n c t i o n( g , env , p r e f i x , maxCycles , maxDerivLen , . . . ) 4 c C r i t e r i a . c h e c k S e q ( )

5 −−C o r o t i n a que consome o p r i m e i r o p a d r a o 6 l o c a l m1 = c o r o u t i n e . wrap ( f u n c t i o n ( )

7 p a t t 1 ( g , env , p r e f i x , maxCycles , maxDerivLen , unpack ( arg ) ) 8 end) 9 10 l o c a l r s l 0 2 , a l l R s l , p a d d i n g = n i l , f a l s e , n i l 11 f o r s t r i , r s l i n m1 do 12 i f r s l then 13 p a d d i n g = s t r i . . " " −−Espacamento e n t r e t e r m i n a i s 14 −−C o r o t i n a que g e r a o s e gu n d o p a d r a o 15 l o c a l m2 = c o r o u t i n e . wrap ( f u n c t i o n ( )

16 p a t t 2 ( g , env , p a d d i n g , maxCycles , maxDerivLen , unpack ( arg ) ) 17 end) 18 19 f o r s t r 2 , r s l 0 2 i n m2 do 20 i f r s l 0 2 then 21 −−Produz a s e n t e n c a e a u n i a o do c o n j u n t o de nao−t e r m i n a i s 22 c o r o u t i n e . y i e l d ( s t r 2 , r s l + r s l 0 2 ) 23 a l l R s l = t r u e 24 end 25 end 26 end 27 end 28 r e t u r n a l l R s l 29 end 30 end

Figura 5.11: Função de gramática seq.

Além da sentença, também é retornado o conjunto que representa os não-terminais utilizados na sua derivação, segundo argumento da função yield na linha 22. Este é o

resultado da união1 dos não-terminais associados a

patt1 e os a patt2. O resultado da

função anônima associada a seq será true caso exista uma produção de sentença nesta

função, como pode ser observado através da variável allRsl nas linhas 10, 23 e 28. No

caso da execução de alguns dos padrões retornar false a sentença produzida por ele será

descartada e a próxima, caso haja, será utilizada. Este mecanismo é uma otimização que elimina algumas expansões desnecessárias durante o processo de derivação e pode ser visto através das restrições das linhas 12 e 20.

A função non_terminal é responsável pela expansão dos não-terminais contidos na

especificação da gramática. A expansão de um não-terminal consiste da execução da

1As variáveis

rsl e rsl02 são tabelas que representam conjuntos e a operação de união é representada pelo símbolo de adição. A implementação deste tipo de tabela está no apêndice D

5.3 Motor de Geração 53

1 f u n c t i o n n o n _ t e r m i n a l ( n t ) 2 c C r i t e r i a . doNonTerminal ( n t )

3 r e t u r n f u n c t i o n( g , env , p r e f i x , maxCycles , maxDerivLen , . . . ) 4 i f g [ n t ] == n i l then 5 e r r o r( " E r r o ao t e n t a r r e s o l v e r o s i m b o l o : " . . n t ) 6 end 7 8 l o c a l r s l , newCL , newDL = c C r i t e r i a . c h e c k N o n T e r m i n a l ( n t ) , n i l , n i l 9 i f r s l then 10 −−P r o c e d i m e n t o de c a l c u l o d a s r e s t r i c o e s

11 r s l , newCL , newDL = d e c i s i o n ( g , nt , maxCycles , maxDerivLen , arg ) 12 i f r s l then

13 env . l i s t N T [ n t ] = env . l i s t N T [ n t ] + 1 14 l o c a l tmp = arg ; tmp[#tmp+1] = n t 15 −−Execucao do nao−t e r m i n a l n t

16 r s l = g [ n t ] ( g , env , p r e f i x , newCL , newDL , unpack ( tmp ) ) 17 i f ( not r s l ) then env . l i s t N T [ n t ] = env . l i s t N T [ n t ]−1 end 18 end

19 end

20 i f not r s l then funcGC ( ) end −−C o n t r o l e de memoria 21 r e t u r n r s l

22 end 23 end

Figura 5.12: Função de gramática non_terminal.

função geradora associada à string contida no argumentontque representa o não-terminal.

Na figura 5.12 é apresentada a codificação desta função. Ela tem como parâmetro uma string, nt, que representa o não-terminal e retorna uma função geradora (linhas 3 a 22)

que segue o padrão das funções de gramática. Além disso, esta função geradora faz a checagem dos mecanismos de controle de derivações, apresentados na seção 5.3.2. A restrição do número máximo de recursões de um não-terminal é mantida emmaxCycles e

a do número máximo de derivações é mantida em maxDerivLen. Estas duas restrições são

calculadas na função auxiliar decision executada na linha 11. Uma vez verificadas todas

as restrições, o não-terminal é expandido com os novos valores demaxCycles, maxDerivLen

e ... na linha 16. O resultado desta função é igual ao resultado do padrão associado ao

símbolo não-terminal expandido.

A funçãonon_terminalnão é utilizada diretamente na especificação Lua, mas através da

tabela auxiliarV. Todos os acessos a elementos desta tabela são traduzidos em chamadas

à funçãonon_terminal. Logo, quando é codificado na especificação o padrãoV.A ouV["A"]

este é traduzido em tempo de execução paranon_terminal("A"). Esta tradução é necessária

por conta da característica recursiva das gramáticas livres de contexto e também por tornar a especificação mais natural e legível.

5.3 Motor de Geração 54

básicas, isto é funções compatíveis com a notação BNF. Através delas o motor de gera- ção gera um conjunto de sentenças que, quando não interrompido, satisfaz o critério de cobertura de derivações.

5.3.3.1 Função de Geração

1 f u n c t i o n gen ( g , rNum , maxCycles , maxDerivLen ) 2 −−C o n f i g u r a n . r e c u r s o e s p a r a o p e r a d o r OOMS 3 numRecLimit = rNum or 0 4 maxDerivLen = maxDerivLen or 1 5 m a x C y c l e s = m a x C y c l e s or 1 6 7 c C r i t e r i a . i n i t G e n ( ) 8 9 l o c a l env = { l i s t N T ={}} 10 f o r i d x , v i n p a i r s ( g ) do 11 env . l i s t N T [ i d x ] = 0 12 end 13 14 l o c a l co = c o r o u t i n e . wrap ( f u n c t i o n ( )

15 n o n _ t e r m i n a l ( g . s t a r t S y m b o l ) ( g , env , "" , maxCycles , maxDerivLen ) 16 end) 17 l o c a l i C o u n t = 0 18 f o r s t r i n co do 19 i f c C r i t e r i a . c h e c k S e n t e n c e ( ) then 20 p r i n t( s t r ) 21 i C o u n t = i C o u n t +1 22 end 23 end 24 25 c C r i t e r i a . f i n a l i z e G e n ( r s l F u n c , r s l D e b u g ) 26 r e t u r n i C o u n t 27 end

Figura 5.13: Função gen.

O processo de geração das sentenças é feito pela função gen. Esta função tem quatro

parâmetros: (1)gque representa a gramática, (2) rNum que limita o número de recursões

permitidas para a função de gramática OneOrMoreSep (OOMS), (3) maxCycles número

máximo de ciclos de não-terminais, e (4)maxDerivLen número máximo de passos para as

derivações. Uma simplificação da função é apresentada na figura 5.13. Outros detalhes contidos na sua implementação são referentes às informações sobre o desempenho do processo de geração e estão incluídos na versão completa apresentada no apêndice B. Os valores padrão para os argumentos são definidos nas linhas 3 a 5 e são utilizados no caso destes não serem informados. O parâmetrorNumé mantido na variável globalnumRecLimit,

linha 3, que é utilizada na implementação da função de gramática OneOrMoreSep. Esta

5.3 Motor de Geração 55

com separados, apresentada na seção 5.3.2. O símbolo inicial da gramática, definido em

g.startSymbol, é expandido tendo como argumento os valores deg, maxCyclese maxDerivLen

através da criação da corotinaco nas linhas 14 a 16. Além destes, também são passados

o valor do prefixo como uma string vazia e a tabela env, criada e inicializada no início

da função. Esta tabela mantém a informação de quais não-terminais foram utilizados durante o processo de geração e só é mantida por compatibilidade com versões anteriores da implementação.

Durante o processo, todo o controle de backtracking necessário para que todas as derivações sejam exploradas é feito pelas corotinas, simplificando a implementação do motor de geração. Cada função geradora executada produzirá uma parte da sentença a ser gerada. Esta parte é chamada de prefixo e será passada como argumento na execução das funções subsequentes. Desta forma a sentença é formada através da execução gradativa das funções anônimas resultantes da execução das funções de gramática utilizadas no momento da especificação da gramática. No caso da função ser composta, cada uma das suas partes é executada e o seu resultado computado utilizando os retornos das suas partes, tendo cada implementação de função uma forma peculiar para combinar estes resultados. Já quando se trata de uma função simples, o método yield é invocado, tendo

como parâmetro todo o conteúdo gerado pelo processo até então. Neste ponto, a execução volta novamente para a chamadaresumemais próxima na pilha de execução e traz a string

da sentença produzida pelas funções aninhadas. Uma vez retomada a execução desta função superior, o processo é continuado e as funções restantes são executadas até toda a especificação ter sido executada.

Ordem gen seq terminal

1 co=wrap(seq(’’, ’a’ , ’b’ ))

2 for str in co do seq( ’ ’ , ’a’ , ’b’)

3 m1=wrap(’’,’a’)

4 for stri in m1 do terminal ( ’ ’ , ’a’ )

5 yield ( ’a’ )

6 m2=wrap(’aЂ’,’b’)

7 for str2 in m2 do terminal ( ’aЂ’ , ’b’)

8 yield ( ’aЂb’)

9 yield ( ’aЂb’)

10 print( ’aЂb’)

Tabela 5.3: Exemplo de execução do motor de geração.

Um exemplo abstrato da execução do motor de geração a partir da função gen é

apresentado na tabela 5.3. Este representa o processo de geração para a expressão

seq( terminal ( ’a’ ), terminal ( ’b’ )). Algumas simplificações foram realizadas, as funções ge-

5.4 Critérios de Cobertura 56

função de gramática, o prefixo e os argumentos terminal ( ’a’ ) e terminal ( ’b’). Outra sim-

plificação é que a função terminal, quando chamada dentro deseq, é representada apenas

como uma string. A tabela é organizada da seguinte forma: a coluna ordem enumera a sequência de passos da execução, a coluna gen mostra as funções executadas na função gen, a coluna seq mostra as funções que são executadas dentro da função seq, e por fim a

coluna terminal apresenta as funções executadas dentro da função terminal.

Como resultado da execução da gramática, temos um conjunto de sentenças que são geradas num arquivo texto em que cada linha representa um programa válido em relação à sintaxe para a linguagem descrita. É importante notar que através do uso das corotinas a implementação do motor de geração é enxuta e simplificada. Em outras abordagens para a geração de sentenças a partir de gramáticas a implementação se torna complexa. Um exemplo é o do algoritmo proposto em [PURDOM, 1972] e que foi implementado posteri- ormente por [MALLOY; POWER, 2001]. A implementação do autor tem aproximadamente 3000 linhas de código na versão inicial feita na linguagem C e menos de 500 na segunda implementação feita na linguagem Python [MALLOY; POWER, 2005] . Em comparação, a nossa implementação tem 283 linhas de código.

5.4

Critérios de Cobertura

O motor de geração permite o uso de diferentes critérios de cobertura durante a ge- ração das sentenças. Estes devem ser fornecidos ao motor e configurados na especificação Lua através da função setCoverageCriteria, que recebe como parâmetro uma referência

para uma tabela que tem as funções da API de comunicação do motor de geração. No trabalho apresentado foram implementados dois critérios de cobertura: cobertura de ter- minais e cobertura de regras de produção. Os dois critérios servem de exemplo para a implementação de outros critérios.

O motor de geração suporta a definição de novos critérios de cobertura. Esta defini- ção é feita através de uma tabela que implementa funções de uma API de comunicação fornecida pelo motor. As funções desta API são divididas em dois grupos que estão relaci- onados a dois momentos distintos durante a execução do motor de geração. O primeiro é chamado de funções de construção e é utilizado no momento da execução das funções de gramática dentro da especificação Lua, momento da definição da gramática. Neste grupo estão contidas as funções que são ativadas de acordo com cada tipo de construção que é encontrada durante a execução da especificação. Estas funções são identificadas

5.4 Critérios de Cobertura 57

através de nomes que são compostos pelo prefixo on mais o nome da construção que está sendo executada. Por exemplo, para as construçõesseq, alt e terminal, quando executadas,

são disparadas as funçõesonSeq, onAlteonTerminalque sinalizam a utilização das constru-

ções. No caso de uma determinada construção não ter definida sua função equivalente, um comportamento padrão será adotado e não causará nenhum problema ao processo. Por conta deste mecanismo a implementação do critério pode ser simplificada pelo foco apenas nas construções necessárias ao novo critério. A relação das funções deste grupo é apresentada na tabela 5.4.

Função de Gramática Funções de Construção

terminal onTerminal seq onSeq alt onAlt non_terminal onNonTerminal optional onOptional oneOrMoreSep onOneOrMoreSep Ident onIdent

Tabela 5.4: Sumário das funções de construção disponíveis para critérios de cobertura. O intuito deste primeiro grupo de funções é de permitir a construção de uma estrutura de dados customizada para cada critério implementado. Com esta abordagem é fornecida uma estrutura flexível para a implementação de novos critérios de cobertura.

O segundo grupo é chamado de funções de controle e é utilizado no momento da geração das sentenças, durante a execução da função gen. De maneira semelhante às

funções do grupo anterior, cada função de gramática tem uma função na API que será executada durante a geração. As funções deste grupo podem ser utilizadas para o controle do processo de geração de sentenças. Para este grupo o padrão de nomenclatura de suas funções têm como prefixo check. Como exemplos temos as funções seq e terminal que

têm como equivalentes checkSeq e checkTerminal respectivamente. Cada uma das funções

deste grupo pode ser utilizada para interromper o processo de geração de uma sentença caso perceba-se que esta sentença não tem a contribuir para a satisfação do critério de cobertura em questão. Este controle é feito através do valor de retorno fornecido durante a execução de cada uma das funções deste grupo. Desta forma, é possível controlar o fluxo de busca dentro do processo de geração das sentenças.

Todas as funções pertencentes ao segundo grupo recebem, além de outros parâmetros específicos de cada função, o parâmetro firstInNT que informa se determinada construção

é a raiz na definição de um não-terminal. Uma construção raiz é aquela que pri- meiro é executada na definição de uma regra de produção. As funções checkTerminal e

5.4 Critérios de Cobertura 58

checkNonTerminaltambém recebem informações sobre qual o não-terminal e terminal, res-

pectivamente, que estão associados à execução da função. A função checkAlternate tem

um tipo de retorno especial. Seu retorno é uma função que deve conter três parâme- tros, sendo eles : (1) lastReturn valor booleano que informa o resultado da última opção

executada na alternativa, que para a execução da primeira alternativa será nil; (2) index

índice que referencia a opção da alternativa que será executada, começando de 1 e indo até o número de opções existentes na construção; e (3)countnúmero de opções existentes

na alternativa. Esta função de retorno deve devolver um valor booleano que indica se a opção de índice especificado em index deve ou não ser executada. A relação das funções

deste grupo é apresentada na tabela 5.5.

Função de Gramática Funções de Controle

terminal checkTerminal seq checkSeq alt checkAlt non_terminal checkNonTerminal optional checkOptional oneOrMoreSep checkOneOrMoreSep Ident checkIdent newContext newContext

Tabela 5.5: Sumário das funções de controle disponíveis para critérios de cobertura. Além das funções descritas anteriormente cada grupo tem algumas funções especiais que podem ser utilizadas para simplificar tanto a construção de estruturas de dados como para coletar e computar informações sobre a execução dos critérios. As funçõesinitGrammar

efinalizeGrammar pertencem ao primeiro grupo e notificam o início e o fim do processo de

definição da gramática. Com o intuito de facilitar a implementação de novos critérios de cobertura a função finalizeGrammar fornece como parâmetro uma estrutura de dados

que mantém informações sobre aos não-terminais e os símbolos deriváveis a partir destes. Esta representação é definida através da estrutura MS que é dada na definição 5.4.1. É importante observar que o custo do cálculo desta estrutura de controle não tem impacto significativo no processo de geração por este ser realizado uma única vez antes do início deste processo de geração.

Na definição a seguir utilizamos alguns conceitos da teoria de gramáticas que são formalizados da seguinte forma: uma gramática é definida através da 4-upla hN, T, s, P i; N representa um conjunto de não-terminais, T um conjunto de terminais tendo N ∩T = ∅; s representa o símbolo inicial da gramática que pertence à N ; e P um conjunto finito de regras de produção em que seus elementos têm a forma α → β, tal que α ∈ (N ∪T )∗

5.4 Critérios de Cobertura 59

T )∗ e β ∈ (N ∪ T )∗. Nas gramáticas livres de contexto os elementos do conjunto P

tem a forma A → α, tal que A ∈ N e α ∈ (N ∪ T )∗. Tendo α′

, β′ ∈ (N ∪ T )∗, α′ gera diretamenteβ′ , representado por α′ ⇒ β′ , se e somente se existem α1, α2, α, β ∈ (N ∪T )∗, tal que α′

= α1αα2, β′ = α1βα2e α → β ∈ P . O fecho transitivo reflexivo de ⇒ é denotado

por ∗

⇒ e seu fecho transitivo por ⇒ [+ HARRISON, 1978].

Definição 5.4.1. Dada uma gramática livre de contexto G = hN, T, s, P i e definindo o conjunto V tal que V := N ∪ T ∪ {ǫ}. MS é uma estrutura que associa cada não-terminal A ∈ N ao conjunto dos símbolos atingíveis a partir de A:

M S = {(A, S) ∈ N × P(V ) | S = {s ∈ V | ∃α, β ∈ V∗

• A ⇒ αsβ}}

Os critérios de cobertura de terminais e regras de produção utilizam o conjunto MS na sua implementação. Apesar da disponibilidade desta representação, seu uso não é obrigatório, ficando a cargo do implementador a avaliação de seu uso ou não dentro da sua codificação. Outra função especial deste grupo é a onProductionRule que representa o

final da definição de um não-terminal e tem como parâmetro uma string representando o não-terminal que está sendo definido.

No segundo grupo também existem algumas funções especiais, sendo elas: (1) a função

initGen que notifica o início do processo de geração; (2) finalizeGen que notifica o final do

processo de geração e recebe como parâmetros duas funções : uma que é utilizada para

Belgede Cennet ve cehennemin ebediliği (sayfa 37-43)

Benzer Belgeler