From 65b38e33c2ba6ac59428e3af4bf08f92b49a8296 Mon Sep 17 00:00:00 2001 From: Stefano Sanfilippo Date: Sun, 23 Nov 2014 19:04:25 +0100 Subject: [PATCH] Initial commit. Grammar has some conflicts, no rules. --- .gitignore | 3 + Makefile | 11 +++ Monicelli.ll | 166 ++++++++++++++++++++++++++++++++++++ Monicelli.y | 149 +++++++++++++++++++++++++++++++++ Specification.txt | 209 ++++++++++++++++++++++++++++++++++++++++++++++ Type.h | 13 +++ main.c | 31 +++++++ 7 files changed, 582 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 Monicelli.ll create mode 100644 Monicelli.y create mode 100644 Specification.txt create mode 100644 Type.h create mode 100644 main.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1ba4763 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/Monicelli.tab.* +/Monicelli.output +/mcc diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f803089 --- /dev/null +++ b/Makefile @@ -0,0 +1,11 @@ +compile: + bison --verbose -d Monicelli.y + flex Monicelli.ll + gcc -DYYDEBUG=1 Monicelli.tab.c lex.yy.c main.c -o mcc + rm Monicelli.tab.* lex.yy.c + +graph: + bison --graph Monicelli.y + +clean: + rm -f Monicelli.dot Monicelli.tab.* lex.yy.c Monicelli.output diff --git a/Monicelli.ll b/Monicelli.ll new file mode 100644 index 0000000..81c901a --- /dev/null +++ b/Monicelli.ll @@ -0,0 +1,166 @@ +%{ +#include "Type.h" +#include "Monicelli.tab.h" +#include + +extern int lineNumber; +extern void yyerror(const char *); +%} + +%option noyywrap + +DIGIT [0-9] +HEXDIGIT [0-9a-zA-Z] +CHAR [a-zA-Z_] + +%% +("\r\n"|"\n") { + lineNumber += 1; + return NEWLINE; +} + +^"bituma"[^\n]* { + lineNumber += 1; +} +"Lei ha clacsonato" { + return MAIN; +} +"vaffanzum" { + return RETURN; +} +"Necchi" { + yylval.typeval = TYPENAME_INT; + return TYPENAME; +} +"Mascetti" { + yylval.typeval = TYPENAME_CHAR; + return TYPENAME; +} +"Perozzi" { + yylval.typeval = TYPENAME_FLOAT; + return TYPENAME; +} +"Melandri" { + yylval.typeval = TYPENAME_BOOL; + return TYPENAME; +} +"Sassaroli" { + yylval.typeval = TYPENAME_DOUBLE; + return TYPENAME; +} +"conte" { + return STAR; +} +"voglio il" { + return VARDECL; +} +"come fosse" { + return ASSIGN; +} +("il"|"lo"|"la"|"i"|"gli"|"le"|"un"|"una"|"dei") { + return ARTICLE; +} +"più" { + return OP_PLUS; +} +"meno" { + return OP_MINUS; +} +"per" { + return OP_TIMES; +} +"diviso" { + return OP_DIV; +} +"sinistra" { + return OP_SHL; +} +"destra" { + return OP_SHR; +} +"minore di" { + return OP_LT; +} +"maggiore di" { + return OP_GT; +} +"minore o uguale a" { + return OP_LTE; +} +"maggiore o uguale a" { + return OP_GTE; +} +"a posterdati" { + return PRINT; +} +"mi porga" { + return INPUT; +} +"ho visto la" { + return ASSERT_BEGIN; +} +"!" { + return ASSERT_END; +} +"stuzzica" { + return LOOP_BEGIN; +} +"e brematura anche, se" { + return LOOP_CONDITION; +} +"che cos'è" { + return BRANCH_CONDITION; +} +"?" { + return BRANCH_BEGIN; +} +"tarapia tapioco" { + return BRANCH_ELSE; +} +"e velocità di esecuzione" { + return BRANCH_END; +} +":" { + return COLON; +} +"blinda la supercazzola" { + return FUNDECL; +} +"con" { + return PARAMS; +} +"," { + return COMMA; +} +"{" { + return LCURL; +} +"}" { + return RCURL; +} +"brematurata la supercazzola" { + return FUNCALL; +} +"avvertite don ulrico" { + return ABORT; +} + +[ \t\f\v] {} + +{CHAR}({DIGIT}|{CHAR})* { + yylval.strval = strdup(yytext); + return ID; +} + +{DIGIT}+ { + yylval.intval = strtol(yytext, NULL, 10); + return NUMBER; +} + +. { + yyerror("Unexpected token\n"); + return -1; +}; + +%% + diff --git a/Monicelli.y b/Monicelli.y new file mode 100644 index 0000000..4bf3c59 --- /dev/null +++ b/Monicelli.y @@ -0,0 +1,149 @@ +%{ +#include "Type.h" +#include + +extern void emit(const char *, ...); +%} + +%union { + Type typeval; + int intval; + double floatval; + char *strval; +} + +%token MAIN +%token RETURN +%token NEWLINE +%token ARTICLE TYPENAME STAR +%token VARDECL ASSIGN +%token PRINT INPUT +%token ASSERT_BEGIN ASSERT_END +%token LOOP_BEGIN LOOP_CONDITION +%token BRANCH_CONDITION BRANCH_BEGIN BRANCH_ELSE BRANCH_END +%token COLON COMMA LCURL RCURL +%token FUNDECL PARAMS FUNCALL +%token ABORT +%token ID NUMBER FLOAT + +%left OP_LT OP_GT OP_LTE OP_GTE +%left OP_PLUS OP_MINUS +%left OP_TIMES OP_DIV +%left OP_SHL OP_SHR + +%nonassoc LOWER_THAN_ELSE +%nonassoc BRANCH_ELSE + +%start program + +%type expression; +%type NUMBER; +%type FLOAT; +%type ID; +%type TYPENAME; + +%% + +program: + fun_decls main fun_decls +; +fun_decls: + /* epsilon */ | fun_decls fun_decl +; +fun_decl: + FUNDECL ID args LCURL statements RCURL +; +args: + /* epsilon */ | PARAMS arglist +; +arglist: + ID | ID COMMA arglist +; +main: + MAIN NEWLINE statements +; +statements: + /* epsilon */ | statements statement +; +statement: + var_decl | assign_stmt | print_stmt | input_stmt | return_stmt | + loop_stmt | branch_stmt | fun_call | abort_stmt | assert_stmt +; +var_decl: + VARDECL pointer ID COMMA TYPENAME var_init NEWLINE +; +pointer: + /* epsilon */ | STAR +; +var_init: + /* epsilon */ | ASSIGN numeric +; +numeric: + NUMBER | FLOAT +; +variable: + ID | ARTICLE ID +; +assign_stmt: + ID ASSIGN expression NEWLINE +; +print_stmt: + expression PRINT +; +input_stmt: + INPUT variable +; +return_stmt: + RETURN NEWLINE | RETURN expression NEWLINE; +; +loop_stmt: + LOOP_BEGIN statements LOOP_CONDITION expression +; +branch_stmt: + BRANCH_CONDITION variable BRANCH_BEGIN + branch_body + BRANCH_END +; +branch_body: + cases %prec LOWER_THAN_ELSE | + cases BRANCH_ELSE COLON statements +; +cases: + case_stmt | case_stmt cases +; +case_stmt: + case_hp COLON statements +; +case_hp: + numeric | variable +; +fun_call: + FUNCALL ID args NEWLINE | FUNCALL ID NEWLINE +; +abort_stmt: + ABORT { + emit("exit(1);\n"); + } +; +assert_stmt: + ASSERT_BEGIN expression ASSERT_END { + emit("assert(", $2, ");\n"); + } +; +expression: + numeric | + variable | + expression OP_LT expression | + expression OP_GT expression | + expression OP_LTE expression | + expression OP_GTE expression | + expression OP_PLUS expression | + expression OP_MINUS expression | + expression OP_TIMES expression | + expression OP_DIV expression | + expression OP_SHL expression | + expression OP_SHR expression +; + +%% + diff --git a/Specification.txt b/Specification.txt new file mode 100644 index 0000000..94b358d --- /dev/null +++ b/Specification.txt @@ -0,0 +1,209 @@ +Proposte per la definizione di un linguaggio di programmazione esoterico "Monicelli" + +Il "main" del programma inizia in corrispondenza di: + Lei ha clacsonato +che da il via alla supercazzola (cioè al programma) + + +Il programma termina con l'istruzione + vaffanzum +che equivale a + return +Può essere usato anche per terminare le funzioni restituendo un valore di ritorno: + vaffanzum antani + +*** Tipi di dato *** + * Necchi -> int + * Mascetti -> char + * Perozzi -> float + * Melandri -> bool + * Sassaroli -> double + +I puntatori si dichiarano anteponendo "conte" al nome della variabile + +quindi + conte Mascetti +è + char* + + +*** Dichiarazione variabili *** +Si usa la sintassi: + voglio il , [, come fosse ] +Esempio: + voglio il cappellano, Necchi +dichiara la variabile "cappellano" di tipo int +e: + voglio lo scrittoio, conte Mascetti +dichiara la variabile "scrittoio" di tipo "char*" +Eventualmente si può anche inizializzare immediatamente la variabile usando l'operatore di assegnamento (spiegato meglio nel seguito) + voglio il cappellano, Necchi, come fosse 4 + +Ogni volta che si deve utilizzare una variabile, è possibile precederla con un articolo. +La concordanza dell'articolo non è semanticamente verificata, ma ci si assicura sintatticamente +che l'articolo sia effettivamente un articolo. + + +*** Operatori *** +definiti a parole, per meglio integrarsi graficamente nella supercazzola. + +Aritmetici + * più + * meno + * per + * diviso + +Di shift: + con scappellamento a per X +dove X e il numero di posizioni dello shift e direzione può essere + * sinistra + * destra +Esempio: + antani con scappellamento a destra per 2 +equivale a + antani >> 2 + + +Di confronto + * minore di + * maggiore di + * minore o uguale a + * maggiore o uguale a + + +Di assegnamento +è "come fosse". +Perciò: + vicesindaco come fosse antani per due a destra +equivale a + vicesindaco = antani >> 2 + + +Operatore di output (postfisso): + a posterdati +Esempio: + antani a posterdati +Stampa la variabile "antani" a video + + +Operatore di input: + mi porga +Esempio + mi porga il cappellano +richiede all'utente di inserire il valore della variabile "cappellano" da standard input + + + + + +*** Cicli *** + +Stuzzica-Brematura +Stuzzica il palato eseguendo almeno una volta il corpo del ciclo, ed eventualmente lo brematura altre volte. +Sintassi: + stuzzica + + e brematura anche, se + + +*** Costrutto di selezione (switch+if) *** +"Che cos'è" +È l'unico costrutto di selezione, facente funzione sia di if, sia di switch +Sintassi: + che cos'è ? + : + + : + + [tarapia tapioco: #Else/default, opzionale + + ] + e velocità di esecuzione. + + può essere: + * : + il codice viene eseguito se il risultato dell'espressione è uguale alla variabileDiControllo + * : + il codice viene eseguito se è vero che: + +Esempio: + che cos'è il genio? + fantasia: + antani come se fosse vicesindaco per due + intuizione: + mi porga il cappellano + zingarata come fosse cappellano più uno + zingarata a posterdati + maggiore di mobiletto: + genio a posterdati + tarapia tapioco: + mi porga il cappello + e velocita di esecuzione + +Che corrisponde a (pseudocodice): + switch(genio) { + case genio=fantasia: + antani = vicesindaco*2 + case genio=intuizione: + input cappellano + zingarata = cappellano+1 + print zingarata + case genio > mobiletto: + print genio + default: + input cappello + } + +*** Funzioni *** +Una funzione può essere definita con la sintassi: + blinda la supercazzola [con [, ]] { + + } + +che definisce la funzione con i parametri in ingresso specificati + + +Le funzioni sono invocate con la sintassi: + brematurata la supercazzola con [[, ]] + +*** Eccezioni *** +Esiste un'unica eccezione possibile (di fatto, corrispondente a segnalare un errore non gestibile e +causa la terminazione del programma). +L'eccezione può essere lanciata tramite la frase: + avvertite don ulrico + +Esempio: + che cos'è il thermos? + un oggetto: + barilotto come se fosse antani per due + > 0: + thermos come se fosse thermos meno 1 + tarapia tapioco: + avvertite don ulrico + e velocità di esecuzione + +Che corrisponde a (pseudocodice): + switch(thermos) { + case thermos==oggetto: + barilotto = antani * 2 + case thermos>0: + thermos = thermos-1 + default: + raise exception + } + +*** Commenti *** +Ogni riga iniziata da "bituma" è un commento e viene completamente ignorata dal compilatore + +Esempio: + bituma il codice che esegue la FFT + + +*** Asserzioni *** + ho visto la ! +verifica che la condizione risulti vera, altrimenti avverte don Ulrico (ossia, lancia un'eccezione) + +Esempio: + ho visto il cappellano come fosse la lavagna! +equivale a + assert(cappellano==lavagna) \ No newline at end of file diff --git a/Type.h b/Type.h new file mode 100644 index 0000000..03cea9f --- /dev/null +++ b/Type.h @@ -0,0 +1,13 @@ +#ifndef TYPE_H +#define TYPE_H + +typedef enum { + TYPENAME_INT, + TYPENAME_CHAR, + TYPENAME_FLOAT, + TYPENAME_BOOL, + TYPENAME_DOUBLE +} Type; + +#endif + diff --git a/main.c b/main.c new file mode 100644 index 0000000..13b0b5a --- /dev/null +++ b/main.c @@ -0,0 +1,31 @@ +#include "Type.h" +#include "Monicelli.tab.h" + +#include +#include + +int lineNumber = 1; + +void yyerror(const char *message) { + fprintf(stderr, "At line %d: %s\n", lineNumber, message); +} + +void emit(const char *text, ...) { + va_list args; + va_start(args, text); + + const char *t; + for (t = text; t != NULL; t = va_arg(args, const char *)) { + printf("%s", t); + } + + va_end(args); +} + +int main() { +#if YYDEBUG + yydebug = 1; +#endif + return yyparse(); +} +