IV. ARAŞTIRMADA TAKİP EDİLEN YÖNTEM ve KAYNAKLAR
2. KIRÂAT, TİLÂVET VE TERTÎL KAVRAMLARININ KUR’AN’DA
2.3. Tertîl Kavramının Kur’an’da Kullanılması
características. A seleção das características que serão compostas podem ser feitas ma- nualmente verificando as restrições entre elas, ou pode se usar a ferramenta FeatureIDE [Kastner et al., 2009], que possui integração com Feature House, para fazer a seleção das características. FeatureIDE é um ambiente de desenvolvimento baseado no Eclipse que suporta todas as fases de POC no desenvolvimento de LPS [Kastner et al., 2009]. Para utilizar o FeatureIDE, é preciso configurar o modelo de características da LPS na ferramenta. Dessa forma o FeatureIDE não irá permitir que seja selecionada uma configuração inválida. A Seção 3.4 mostra melhor estes pontos.
Figura 3.1. Fases do processo de criação do G4FOP.
3.2
Criando a Gramática
A criação de uma gramática para ser integrada ao Feature House deve ser feita uti- lizando o formato FeatureBNF [Kästner et al., 2008]. Podemos dizer que FeatureBNF é uma extensão da notação BNF, que foi introduzida por John Backus e Peter Naur na década de 60 como uma notação formal para descrever a sintaxe de uma linguagem [Marcotty & Ledgard, 2012]. FeatureBNF adicionou alguns artefatos ao BNF, de forma que o programador possa anotar a gramática da linguagem com atributos. A Figura 3.2 mostra um exemplo do uso da anotação na gramática. As duas principais formas de fazer anotações na gramática com Feature House são colocar um @FSTTerminal ou um @FSTNonTerminal. O primeiro define que aquele nó é terminal e o segundo define que o nó não é terminal. Por padrão, todas as regras de produção que não receberem anotações serão definidas como terminais. Sendo assim, a vantagem de uti- lizar o @FSTTerminal é poder especificar o nome que irá aparecer no nó da FST e na composição de dois nós terminais correspondentes [Apel et al., 2009].
1 @FSTTerminal
2 I m p o r t D e c l a r a t i o n :
3 " import " [ " s t a t i c " <NONE> ] Name [ ImportPackage ] @! [<SEMICOLON>] 4 ;
24 Capítulo 3. G4FOP: Uma Extensão do Feature House para Groovy
Grande parte da gramática que deve ser escrita para integrar uma linguagem ao Feature Houseé feita utilizando o JavaCC [Cognisync, 2016]. JavaCC é a abreviação para Java Compiler Compiler e é um gerador de parser e de analisador léxico. Ele faz a leitura da descrição de uma linguagem e gera o código, escrito em Java, que vai ler e analisar aquela linguagem.
Uma gramática escrita em FeatureBNF consiste em duas partes. A primeira con- tém instruções para o JavaCC, especialmente para a análise léxica, uma vez que nesta parte são declarados os tokens da linguagem. A segunda parte é separada da primeira pela palavra “GRAMMARSTART”, e consiste nas construções sintáticas da linguagem [Kästner et al., 2008]. A gramática escrita para o Groovy foi baseada na gramática do Java, uma vez que as linguagens são parecidas. Porém, diversas construções e alterações tiveram de ser feitas para que a gramática se adaptasse ao Groovy.
A primeira parte da gramática é destinada aos tokens da linguagem, e é a partir dela que será gerado o token manager da gramática. O token manager é um ana- lisador léxico. Ou seja, ele analisa a entrada de caracteres, quebra ela em partes chamadas tokens, e define cada um como um tipo de token [Norvell, 2007]. A segunda parte da gramática consiste em produções no formato BNF, mais as anotações do Feature House. As produções seguem o seguinte padrão: “NomeDaProdução : To- kens :: NomeDaEscolha | Tokens :: NomeDaEscolha | ... ;”. Primeiro vem o nome da produção, depois múltiplas escolhas, onde cada uma representa uma sequência de tokens, e pode ou não ser nomeada. Os tokens informados podem ser não terminais, de forma a referenciarem outras produções, ou podem ser tokens léxicos [Apel et al., 2009]. A Figura 3.3 mostra a produção da estrutura closure da gramática de Groovy, como exemplo. Na Figura há a criação da produção chamada “ClosureExpression”. Dentro dela são chamada mais duas produções, “ClosureParameterInitializer” e “Expression”. “ClosureParameterInitializer” representa a inicialização de uma closure, que é uma lista de parâmetros separados por vírgula. “<IDENTIFIER>” representa um identificador qualquer, utilizado para dar nome a um atributo. “<COMMA>” representa uma vír- gula e “<ARROW>” uma seta (->). Estes símbolos são definidos na primeira parte da gramática. O que está dentro de colchetes é interpretado como opcional. O que está entre parênteses com um asterisco no final possibilita que este conteúdo se repita várias vezes.
3.2. Criando a Gramática 25 1 C l o s u r e E x p r e s s i o n : 2 "{" [<IDENTIFIER>] ( C l o s u r e P a r a m e t e r I n i t i a l i z e r )∗ 3 [<ARROW>] ( E x p r e s s i o n ) ∗ "}" ; 4 C l o s u r e P a r a m e t e r I n i t i a l i z e r : 5 <COMMA> <IDENTIFIER>;
Figura 3.3. Produção da estrutura closure.
Para cada produção deve-se informar ao Feature House, através de anotações, se um nó é terminal ou não terminal. Se for terminal, basta colocar um @FSTTerminal na linha acima da produção. Caso seja não terminal, basta colocar @FSTNonTer- minal. Caso uma produção não sofra anotação, ela será considerada como terminal. Feature Housetambém fornece mais duas anotações, uma chamada FSTExportName e a outra FSTInline. FSTExportName serve para definir o nome de exportação do nó. FSTInline serve para colocar a produção na mesma linha da produção que a chama, servindo assim apenas para facilitar a leitura e escrita da gramática [Apel et al., 2009]. Um importante mecanismo utilizado na escrita da gramática foi o chamado lookahead, que é um mecanismo que permite informar quantos tokens devem ser analisados an- tes de escolher um caminho, sendo importante para evitar recursões infinitas [Norvell, 2007].
Para a escrita da gramática Groovy, foi utilizada como base a gramática da linguagem Java, que já estava integrada no Feature House. Porém foram necessárias diversas adaptações na mesma, visto que a linguagem Groovy traz algumas diferenças para Java. Foi necessário adicionar algumas palavras chave na gramática. Por exemplo para “as” e “in” foi necessário retirar a obrigatoriedade do ponto e vírgula no fim de cada comando, uma vez que em Groovy isto é opcional. Também foi preciso alterar para opcional a tipagem de variáveis, uma vez que em Groovy é possível declarar uma variável utilizando a palavra “def” sem definir seu tipo em tempo de compilação.
Também foram criadas novas formas de declarar algumas estruturas da lingua- gem, como array, map e for. Por exemplo, em Groovy um array de 0 a 20 pode ser definido com o seguinte comando: (0..20).toArray(). Foi preciso criar novas estruturas, como por exemplo a chamada closure, que é um bloco de código que pode receber parâmetros, retornar um valor e pode ser associado a uma variável [Apache, 2016b]. Também foi necessário fazer com que a gramática reconhecesse a estrutura chamada expando, que é uma meta-classe capaz de expandir seu estado e comportamento [Koenig et al., 2007]. Foi preciso fazer com que a gramática suportasse novos operadores que estão presentes em Groovy, como os chamados spread e safe, por exemplo. A Figura
26 Capítulo 3. G4FOP: Uma Extensão do Feature House para Groovy
3.4 exemplifica o operador spread. Ele executa uma ação em todos os componentes de uma coleção. Neste exemplo, todas as palavras da lista seriam convertidas para letra maiúscula. A Figura 3.5 mostra um exemplo de utilização do operador safe. Ele é uti- lizado para evitar exceções do tipo NullPointerException, pois ele verifica se o objeto é nulo antes de tentar resgatar o atributo solicitado. A gramática de Groovy está no Apêndice A deste trabalho.
1 d e f p a l a v r a s = [ ’ C a r a c t e r i s t i c a ’ , ’ S o f t w a r e ’ , ’ Gramatica ’ ] 2 p a l a v r a s ∗ . toUpperCase ( )
Figura 3.4. Operador spread da linguagem Groovy.
1 d e f u s e r = User . g e t ( 1 )
2 d e f username = u s e r ? . username
Figura 3.5. Operador safe da linguagem Groovy.