# String Template

A biblioteca *String Template* fornece uma solução estruturada para a geração de código textual.

O software e documentação podem ser encontrados em [www.stringtemplate.org](http://www.stringtemplate.org) .

Para ser utilizada é apenas necessário o pacote *ST-4.?.jar* (a instalação feita do antlr4 já incluiu este pacote).

![](https://2105802016-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FP0B5wWrJT1pz8LDXyP2I%2Fuploads%2FaTuxmHKDeZFXuXzUCUDl%2Fa.png?alt=media\&token=e4ee20a4-ada4-4b67-99a1-47b5d03c9c8f)

Mesmo sendo um exemplo muito simples, podemos já verificar que a definição do padrão de texto, está separada do preenchimento dos “buracos” (atributos ou expressões) definidos, e da geração do texto final.

Podemos assim delegar em partes diferentes do gerador de código, a definição dos padrões (que passam a pertencer ao contexto do elemento de código a gerar), o preenchimento dos “buracos” definidos, e a geração do texto final de código.

Os padrões são blocos de texto e expressões.

O texto corresponde a código destino literal, e as expressões são em “buracos” que podem ser preenchidos com o texto que se quiser.

Sintaticamente, as expressões são identificadores delimitados por *\<expr>* (ou por *$*).

![](https://2105802016-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FP0B5wWrJT1pz8LDXyP2I%2Fuploads%2Fq4YjXsI8n4oG9X5Pxa5m%2Fa.png?alt=media\&token=3d9fea94-460b-4443-9a98-2f8cec5625f7)

### String Template Group

Podemos também agrupar os padrões numa espécie de funções (módulo *STGroup*):

![](https://2105802016-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FP0B5wWrJT1pz8LDXyP2I%2Fuploads%2Fmn4ilqSo34DeZ3zKxk1C%2Fa.png?alt=media\&token=cc402b3f-c0c7-4fc0-a248-2bb3dd9f283f)

Podemos também colocar cada função num ficheiro:

![](https://2105802016-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FP0B5wWrJT1pz8LDXyP2I%2Fuploads%2FBhuNo1wz2Eo1DVJQsZQt%2Fa.png?alt=media\&token=65733e93-7bf4-4d18-a1e2-3125740fe164)

![](https://2105802016-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FP0B5wWrJT1pz8LDXyP2I%2Fuploads%2FgTd9Mfwtx8qZEuNrd973%2Fa.png?alt=media\&token=c843f9a3-79aa-4b23-8a8d-4e578c051047)

Uma melhor opção é optar por ficheiros modulares contendo grupos de funções/padrões:

![](https://2105802016-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FP0B5wWrJT1pz8LDXyP2I%2Fuploads%2FmFxZima3OQDlLAmuth6b%2Fa.png?alt=media\&token=207ee7b1-806d-4519-ac03-fe93b73874da)

![](https://2105802016-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FP0B5wWrJT1pz8LDXyP2I%2Fuploads%2F9igWwfMYsks7S2M7ipyQ%2Fa.png?alt=media\&token=78df8127-1c00-4085-8c13-3a77bb5266ee)

### String Template: dicionários e condicionais

Neste módulos podemos ainda definir dicionários (arrays associativos).

![](https://2105802016-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FP0B5wWrJT1pz8LDXyP2I%2Fuploads%2FxNKoCdsXsK6lcDxjGJ2v%2Fa.png?alt=media\&token=0b20270f-a179-4def-8902-809aaa44c7e9)

Na definição de padrões podemos utilizar uma instrução condicional que só aplica o padrão caso o atributo seja adicionado:

![](https://2105802016-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FP0B5wWrJT1pz8LDXyP2I%2Fuploads%2FCB3IF4nlFIqiw8gAz9n5%2Fa.png?alt=media\&token=180f9ce5-67d4-4a7d-94e6-966b6433db9e)

O campo *separator* indica que em em cada operação add em *stat*, se irá utilizar esse sepa- rador (no caso, uma mudança de linha).

### String Template: Funções

Podemos ainda definir padrões utilizando outros padrões (como se fossem funções).

![](https://2105802016-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FP0B5wWrJT1pz8LDXyP2I%2Fuploads%2FkL3qYuhv3QnrIuUlSsgS%2Fa.png?alt=media\&token=b0d2b033-3864-4d45-9b33-78bdcbe0e580)

### String Template: listas

Também existe a possibilidade de utilizar listas para concatenar texto e argumentos de padrões:

![](https://2105802016-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FP0B5wWrJT1pz8LDXyP2I%2Fuploads%2FHuWAMyOJsPgE0xnXRHDB%2Fa.png?alt=media\&token=cb6b9238-083c-43cb-aef3-94cd69e3d1af)

## Geração de código: padrões comuns

Uma geração de código modular requer um contexto uniforme que permita a inclusão de qualquer combinação de código a ser gerado.

Na sua forma mais simples, o padrão comum pode ser simplesmente uma sequência de instruções.

Com este padrão, podemos inserir no lugar do “buraco” stat a sequência de instruções que quisermos.

Naturalmente, que para uma geração de código mais complexa podemos considerar a inclusão de buracos para membros de classe, múltiplas classes, ou mesmo vários ficheiros.

Para a linguagem C, teríamos o seguinte padrão para um módulo de compilação:

![](https://2105802016-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FP0B5wWrJT1pz8LDXyP2I%2Fuploads%2FgBVNrTtocWwEwIQOvNKo%2Fa.png?alt=media\&token=eb2f84d3-ccc7-4a74-8015-fb50eaddf7c9)

Se a geração de código for guiada pela árvore sintáctica (como normalmente acontece), então os padrões de código a ser gerados devem ter em conta as definições gramaticais de cada símbolo, permitindo a sua aplicação modular em cada contexto.

## Geração de código para expressões

Para ilustrar a simplicidade e poder de abstração do String Template vamos estudar o problema de geração de código para expressões.

Para resolver este problema de uma forma modular, podemos utilizar a seguinte estratégia:

1. Considerar que qualquer expressão tem a si associada uma variável (na linguagem destino) com o seu valor;
2. Para além dessa associação, podemos também associar a cada expressão um ST (*stats*) com as instruções que atribuem o valor adequado à variável.

Como habitual, para fazer estas associações podemos definir atributos na gramática, fazer uso do resultados das funções de um Visitor ou utilizar a classe *ParseTreeProperty*.

Desta forma, podemos fácil e de uma forma modular, gerar código para qualquer tipo de expressão.

Padrões para expressões (para *Java*) podem ser:

![](https://2105802016-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FP0B5wWrJT1pz8LDXyP2I%2Fuploads%2FF6T0AsoWg6Q7a62cqY9P%2Fa.png?alt=media\&token=eef2a637-2377-44eb-aea1-304470e33079)

Para C apenas seria necessário mudar o padrão *typeValue*:

![](https://2105802016-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FP0B5wWrJT1pz8LDXyP2I%2Fuploads%2FcDAEGZgnEq61S4So831g%2Fa.png?alt=media\&token=394c21c0-7aef-451a-8a8e-4e7ccf90d3e7)
