Synta
Introduzione
Synta 1 è uno strumento a linea di comando per svolgere svariate operazioni sul formato di definizione regolare usato internamente a CartaBinaria per vincolare le nomenclature dei file. È disponibile presso cartabinaria/synta. Con Synta è possibile:
- verificare la validità di un file 
.synta; - convertire un file 
.syntain una espressione regolare; - convertire un file 
.syntain un file JSON che ne descrive i contenuti. 
Definizione del linguaggio
Il linguaggio Synta è definito dalla seguente BNF:
<upperletter> ::= "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" |
                  "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" |
                  "U" | "V" | "W" | "X" | "Y" | "Z"
<lowerletter> ::= "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" |
                  "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" |
                  "u" | "v" | "w" | "x" | "y" | "z"
<digit>       ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
<alphanum>    ::= <lowerletter> | <upperletter> | <digit>
<char>        ::= <alphanum> | ":" | ";" | "," | "." | "-" | "_"
<word>        ::= <char> <word> | <char>
<text>        ::= <word> " " <text> | <word>
<comment>     ::= "; " <text> "\n" | ";" <text> "\n"
<id>          ::= <lowerletter> <id> | <lowerletter>
<def>         ::= <id> " = " <regexp> "\n"
<commdef>     ::= <comment> <commdef> | <comment> <def>
<commdefs>    ::= <commdef> <commdefs> | <commdef>
<segment>     ::= "-" <id> | <opt_segment>
<opt_segment> ::= "(-" <id> ")?" | "(-" <id> <opt_segment> ")?"
<join>        ::= <segment> <join> | <segment>
<main>        ::= "> " <id> <join> "." <id> "\n"
<language>    ::= <commdefs> <main>
dove <regexp> è una valida sintassi che esprime una espressione regolare.
La sintassi regexp usata è quella di Go, ma per i nostri fini, dovrebbe essere
anche compatibile con quella di Javascript e Rust.
Esempi
; La tipologia della prova
tipo = scritto|orale
; Una data del tipo yyyy-mm-dd
data = \d{4}-\d{2}-\d{2}
; La fila e' un numero
fila = \d
; Una qualunque parola alfanumerica
extra = (\w|\d)+
; Estensione del file. Possibili valori:
; - txt, tex, md, pdf, doc, docx
ext = txt|tex|md|pdf|doc|docx
> tipo-data(-fila)?-extra.ext
Implementazione del parser
Per il parse dell’intero file, usiamo un parser semplicistico manipolando la stringa, in quanto l’analisi delle definizioni e dei commenti è piuttosto facile. Per il parse della linea finale, che contiene la concatenazione di tutte le regole, usiamo invece un piccolo FSA con side-effect come segue:
I side-effect sono:
L: variabile per gestire il livello di profonditàconcat: concatena il simbolo letto adidpush: a seconda del livello di profondita’ aggiunge alla struttura l’idletto fin’oragenerateOptional: crea la struttura per aggiungere blocchi opzionali in seguito tramite push
Sviluppo
Ecco una lista dei file nella repository e il loro scopo:
├── data.go        # Strutture dati per il parser
├── parser.go      # Logica di parsing e FSA
├── parser_test.go # Unit test per il parser
- 
Origine del nome: è uno dei top-10 nomi suggeriti da chat gpt. Abbiamo usato il prompt: “suggest me a short name for a tiny parser command line utility. the name must not be made up of two or more words” ↩︎