Come creare un interprete come TypeScript
In questo tutorial, realizzerai un interprete che converte un’istruzione del linguaggio TypeScript in JavaScript utilizzando Flex per il lexer e Bison per il parser. Il tuo traduttore di codice prenderà in input un file TypeScript e genererà un file JavaScript corrispondente. Esattamente quello che fa Typescript con il comando “tsc” che è l’abbreviazione di TypeScript Compiler ed è lo strumento principale per compilare il codice TypeScript in JavaScript.
Indice del Post...
Desideri acquisire nuove competenze?

l'opportunità di acquisire nuove competenze e di
migliorare il tuo curriculum professionale.
Clicca qui per seguire le prime lezioni gratuite online

1. Installazione degli strumenti necessari
Per la progettazione di questo interprete devi assicurati di avere installati Flex e Bison. Di seguito troverai le istruzioni da eseguire per installare questi due strumenti gratuiti sui più diffusi sistemi operativi:
Linux (Ubuntu/Debian)
sudo apt update
sudo apt install flex bison gcc
MacOS (con Homebrew)
brew install flex bison gcc
Windows (con MSYS2 e pacman)
MSYS2 è un ambiente che fornisce una shell Unix-like su Windows e permette di installare strumenti GNU, come Flex e Bison, utilizzando il gestore di pacchetti pacman (simile a quello di Arch Linux).
Innanzitutto scarica e installa MSYS2 dal sito ufficiale: https://www.msys2.org/. MSYS2 (acronimo di Minimal System 2) è un ambiente di sviluppo open-source per Windows, che fornisce strumenti Unix-like per compilare, eseguire e gestire software in modo simile a un sistema dotato di kernel Linux. Basato su Cygwin e MinGW-w64, MSYS2 offre una shell Bash, in poche parole un terminale, e un gestore di pacchetti Pacman, simile a quello di Arch Linux.
Dopo l’installazione, apri MSYS2 MSYS, e aggiorna il package manager con il comando:
pacman -Syu
Nota: Dopo questo comando, MSYS2 potrebbe chiudersi automaticamente. Riaprilo e riesegui pacman -Syu per completare l’aggiornamento.
Ora, devi installare Flex, Bison e GCC eseguendo questo semplice comando all’interno del terminale MSYS2:
pacman -S mingw-w64-x86_64-flex mingw-w64-x86_64-bison mingw-w64-x86_64-gcc
Assicurati che il percorso C:\msys64\mingw64\bin sia aggiunto alla variabile d’ambiente PATH di Windows, in modo da poter eseguire Flex e Bison da qualsiasi posizione all’interno del file system.
Leggi anche: Creare un linguaggio di programmazione con Python
2. Creazione del Lexer con Flex
Il lexer analizza il codice TypeScript e suddivide le parole chiave, gli identificatori e i simboli in token. A questo punto crea un file di nome “lexer.l”, copia e incolla il seguente codice al suo interno:
File: lexer.l
%{
// Include il file header generato da Bison
#include "parser.tab.h"
#include <stdio.h>
%}
// Evita problemi con l'input di Flex
%option noyywrap
%%
Let { return LET; }
[a-zA-Z_][a-zA-Z0-9_]* { yylval.str = strdup(yytext); return IDENTIFIER; }
[0-9]+ { yylval.num = atoi(yytext); return NUMBER; }
= { return ASSIGN; }
; { return SEMICOLON; }
[ \t\n] { /* Ignora spazi e nuove righe */ }
. { printf("Carattere sconosciuto: %s\n", yytext); }
%%
3. Creazione del Parser con Bison
Il parser analizza la sequenza di token, restituiti dal lexer, e genera un file JavaScript corrispondente.
File: parser.y
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void yyerror(const char *s);
int yylex();
extern int yylineno;
FILE *outputFile;
%}
%union {
char *str;
int num;
}
%token LET IDENTIFIER ASSIGN NUMBER SEMICOLON
%type <str> IDENTIFIER
%type <num> NUMBER
%%
program:
statement { fprintf(outputFile, "var %s = %d;\n", $1, $3); }
;
statement:
LET IDENTIFIER ASSIGN NUMBER SEMICOLON { $$ = $2; $$ = $4; }
;
%%
void yyerror(const char *s) {
fprintf(stderr, "Errore: %s alla riga %d\n", s, yylineno);
}
4. Creazione del File di Esecuzione
File: main.c
#include <stdio.h>
#include <stdlib.h>
extern FILE *yyin;
extern FILE *outputFile;
int yyparse();
int main(int argc, char *argv[]) {
if (argc < 3) {
fprintf(stderr, "Usa: %s input.ts output.js\n", argv[0]);
return 1;
}
yyin = fopen(argv[1], "r");
if (!yyin) {
perror("Errore nell'apertura del file sorgente");
return 1;
}
outputFile = fopen(argv[2], "w");
if (!outputFile) {
perror("Errore nella creazione del file di output");
fclose(yyin);
return 1;
}
yyparse();
fclose(yyin);
fclose(outputFile);
return 0;
}
5. Compilazione e Esecuzione
Ora puoi compilare il tuo interprete di codice in Linux, macOS e Windows. Prima però crea il file “input.ts” con questa istruzione: “Let x = 42;”e successivamente l’interprete creerà il file “output.js” con questa istruzione: “var x = 42;” cioè con l’istruzione Typescript convertita in Javascript.
Linux/macOS
bison -d parser.y -o parser.tab.c
flex -o lexer.c lexer.l
gcc -o transpiler lexer.c parser.tab.c main.c -lfl
./transpiler input.ts output.js
Windows (MSYS2)
bison -d parser.y -o parser.tab.c
flex -o lexer.c lexer.l
gcc -o transpiler.exe lexer.c parser.tab.c main.c -lfl
./transpiler input.ts output.js
6. Conclusione
Hai creato un interprete di codice che converte da TypeScript in JavaScript utilizzando Flex e Bison. Ora, per migliorarlo, potresti implementare la gestione di tipi TypeScript. Rivedi pazientemente quanto è stato fatto nei file lexer.l e parser.y e aggiungi le istruzioni necessarie per integrare la conversione di altre istruzioni.