Processo de criação de uma linguagem de programação
Tags: computerscience, compilers, tutorial, programminglanguage
Published: 2021-07-22 18:19:02

![Compilers diagram](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gafs5ntlo288v68s49g2.png)
Você já teve vontade de criar a sua própria linguagem de programação? Já teve a curiosidade de saber como funciona esse processo, o que você precisa saber e qual caminho seguir? Nesse artigo irei detalhar os passos e o caminho que estou trilhando nos meus estudos para criar a minha própria linguagem de programação, o que eu estudei, quais conteúdos eu consumi, livros, vídeos e também o que estou estudando agora.
<br />

## Sem tempo, irmão? :clock130::sleeping:

Está sem tempo? Vai um **resumo** então: o principal objetivo do artigo é elencar os processos e etapas para a criação de uma linguagem de programação, são eles:
1. Estudo da parte teórica de compiladores e linguagens
2. Escolha de uma linguagem que você domine para ser usada na construção do compilador/interpretador
3. Decisão sobre o uso de ferramentas, se vai usá-las, se sim quais?
4. Definição das características da linguagem
5. Análise Léxica
6. Análise Sintática e Semântica
7. Geração de código

&nbsp;

## Por onde começar?

A parte mais difícil é o começo, achar as informações certas, definir um caminho, materiais de estudo e os objetivos. Criar uma linguagem de programação é uma tarefa complexa, que exige conhecimentos variados, por isso é essencial começar estudando a **parte teórica de compiladores e linguagens**. Isso vai te ajudar a entender os algoritmos e estruturas de dados presentes em um compilador, assim como as suas etapas. 
<br />

## Escolha da linguagem

![Linguagens de programação](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/33hxoezq4yr5h6duf0bb.png)

Para criar uma linguagem você precisa de outra, isso quer dizer que para implementar a sua própria linguagem de programação você precisa de uma outra linguagem de programação já existente, que será utilizada para escrever o seu compilador/interpretador.
É importante escolher uma linguagem de programação que você domine, saiba sua sintaxe, suas estruturas de dados, tratamento de erros entre outros. Isso vai te ajudar a ser mais produtivo e eficiente na implementação.
No meu caso escolhi a linguagem C, por questões de desempenho e familiaridade com a linguagem, você pode escolher a que atender às suas necessidades e que você se sinta mais confortável no uso.
<br />

## Ferramentas

Há várias ferramentas para simplificar o trabalho do programador ao desenvolver um compilador/interpretador. Elas poupam muito tempo, e removem parte do trabalho massivo de análises e projeções de algoritmos, essas ferramentas podem ir desde a análise léxica até a análise sintática e semântica, assim como a geração de código.

Algumas dessas ferramentas são: LLVM, ANTLR, Lex, Yacc etc. É importante na fase de 
planejamento do seu projeto de linguagem de programação, decidir se irá usá-las, ou se irá
fazer essas tarefas "na mão", o que lhe dará mais liberdade e possibilidade de customização, porém exigirá um esforço maior.
<br />

## Definição das características da linguagem

Essa etapa é onde você definirá a gramática da sua linguagem, o seu alfabeto, seus tipos de dados, seus tipos de dados, suas regras de sintaxe e semântica, e também como será implementada a tradução no seu compilador/interpretador.

```rust
fn simple_sum (a: number, b: number) do
  return a + b
end
```
Esta é uma representação de código de uma linguagem hipotética, este código deve seguir as regras definidas pelo programador, para ser aceito pelo compilador corretamente e não gerar erros.
<br />

## Análise Léxica

A análise léxica é muito importante, é nessa fase da compilação que é feita a
decomposição das expressões. Uma expressão é desmembrada em lexemas, estes que 
devem ser reconhecidos pela linguagem caso sejam permitidos em sua gramática, caso
contrário, um erro léxico deve ser retornado ao usuário. Após o reconhecimento,
os lexemas são classificados em *tokens*, que serão utilizados por um analisador léxico posteriormente.

O exemplo abaixo mostra os lexemas obtidos na quebra das expressões correspondentes ao 
código apresentado na seção anterior. E além disso , estes lexemas também estão classificados em *tokens*.

```rust
<KEYWORD, fn> <IDENTIFIER, simple_sum> <LPAREN, (> <IDENTIFIER, a> <TT_COLON, :>

<KEYWORD, number> <TT_COMA, ,> <IDENTIFIER, b> <TT_COLON, :> <KEYWORD, number> <RPAREN, )>

< KEYWORD, do> <KEYWORD, return> <IDENTIFIER, a> <TT_PLUS, +> <IDENTIFIER, b> <KEYWORD, end>
```

&nbsp;

## Análise Sintática e Semântica

Análise Sintática e Análise Semântica são duas etapas diferentes de um compilador, elas 
possuem funções distintas, porém por serem interdependentes e próximas, algumas literaturas e implementações unem essas duas fases em uma só, o *parser*, ou "analisador"
em português.

### Análise Sintática

Nessa fase os *tokens* são organizados formando construções que podem ser entendidas de
maneira isolada, essas construções devem fazer sentido e respeitar as regras da linguagem. O analisador sintático recebe os *tokens* gerados pelo analisador léxico e cria uma representação intermediária, que é uma árvore de sintaxe.

Uma árvore de sintaxe é uma estrutura do tipo árvore que armazena informações sobre uma expressão, como por exemplo, se a expressão é um número, uma operação, uma variável, etc. Estruturas do tipo árvore, são grafos, portanto possuem vértices e nós, os nós interiores representam uma **operação**, e os nós externos representam os argumentos da operação, ou seja, os **termos**.

<center>
  <img style="border-radius: 15px;" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cao1xtz3rkfn42d91mu8.png" alt="Representação de árvore sintática"/>
</center>

### Análise Semântica

A análise semântica, diferentemente da análise sintática, analisa expressões completas,
checa se elas fazem sentido junto com o "todo", se ao serem combinadas com outras expressões são válidas para as regras da linguagem. 

Essa etapa também verifica os tipos de dados e operações. Traçando um paralelo com a língua portuguesa, a semântica é o estudo
do significado das expressões de uma linguagem, através de suas palavras, símbolos e composições.
<br />

## Geração de código

A geração de código é a parte onde você fará o seu código "funcionar", é nela que
você deverá transpilar o seu código para uma linguagem de alto nível, compilar para
*assembly* ou intepretar em tempo real. Caso escolha os métodos de transpilação ou compilação, a etapa de geração de código será subdividida em 3 partes:
1. Geração de código intermediário
2. Otimização do código intermediário  
3. Geração do código final (linguagem intermediária ou *assembly*)

&nbsp;

## Alguns links úteis para aprender sobre compiladores

* <a href="https://www.google.com/search?gs_ssp=eJzj4tTP1TcwtCyrLDBg9BJNzs8tyMxJLSpWSClKTM_PU0jKz88GALzxC5w&q=compilers+dragon+book&oq=compilers+drag&aqs=chrome.1.69i57j46i19j0i19l2j0i10i19i22i30.5120j0j7&sourceid=chrome&ie=UTF-8">Compilers: Principles, Techniques, and Tools</a> - o famoso
"livro do dragão" que é uma referência na área.

* <a href="https://www.youtube.com/user/adrianocomp1/playlists">Aulas de Computação - YouTube</a> - canal do Professor Adriano Santos com conteúdos teóricos sobre compiladores e linguagens.

* <a href="https://www.youtube.com/user/adrianocomp1/playlists">Professor Isidro - YouTube</a> - canal do Professor Isidro com conteúdos teóricos e práticos sobre a construção de um compilador.

* <a href="https://www.youtube.com/watch?v=Eythq9848Fg&list=PLZQftyCk7_SdoVexSmwy_tBgs7P0b97yD">CodePulse - YouTube</a> - playlist do canal
CodePulse com vídeos (em inglês) práticos da criação de um interpretador completo.

&nbsp;

## Conclusão

Chegamos ao final do nosso artigo, com isso em mente, vemos que criar uma nova linguagem de programação é realmente uma tarefa complexa e árdua, porém com esse guia, as coisas podem se tornar mais fáceis para quem estava sem saber para onde ir. Espero ter ajudado!:smile: