DEV Community

José Thomaz
José Thomaz

Posted on • Edited on

Processo de criação de uma linguagem de programação

Compilers diagram
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.

Sem tempo, irmão? 🕜😴

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

 

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.

Escolha da linguagem

Linguagens de programação

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.

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.

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.



fn simple_sum (a: number, b: number) do
  return a + b
end


Enter fullscreen mode Exit fullscreen mode

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.

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.



<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>


Enter fullscreen mode Exit fullscreen mode

 

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.

Representação de árvore sintática

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.

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)

 

Alguns links úteis para aprender sobre compiladores

 

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!😄

Top comments (1)

Collapse
 
kaique_ferraz profile image
Kaique De jesus

Muito obrigado pela explicação. Parabéns pelo conteúdo :)