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?

corsi.it

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

Corsi.it - Il portale Nr.1 al mondo di corsi 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. 

Antonio Lamorgese

Amministratore di rete e sviluppatore. Dopo anni di esperienza nel settore, ho ideato un sistema di gestione dati MYSQL in PHP senza scrivere una sola riga di codice. Scopri di più....