Initial commit. Grammar has some conflicts, no rules.

This commit is contained in:
Stefano Sanfilippo 2014-11-23 19:04:25 +01:00
commit 65b38e33c2
7 changed files with 582 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
/Monicelli.tab.*
/Monicelli.output
/mcc

11
Makefile Normal file
View File

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

166
Monicelli.ll Normal file
View File

@ -0,0 +1,166 @@
%{
#include "Type.h"
#include "Monicelli.tab.h"
#include <stdlib.h>
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;
};
%%

149
Monicelli.y Normal file
View File

@ -0,0 +1,149 @@
%{
#include "Type.h"
#include <stdlib.h>
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<strval> expression;
%type<intval> NUMBER;
%type<floatval> FLOAT;
%type<strval> ID;
%type<typeval> 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
;
%%

209
Specification.txt Normal file
View File

@ -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 <nome>, <tipo>[, come fosse <espressione>]
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 <direzione> 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 <variabile>
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
<corpo del ciclo>
e brematura anche, se <condizione>
*** Costrutto di selezione (switch+if) ***
"Che cos'è"
È l'unico costrutto di selezione, facente funzione sia di if, sia di switch
Sintassi:
che cos'è <articolo> <variabileDiControllo>?
<ipotesi>:
<codice>
<ipotesi>:
<codice>
[tarapia tapioco: #Else/default, opzionale
<codice>
]
e velocità di esecuzione.
<ipotesi> può essere:
* <espressione>:
il codice viene eseguito se il risultato dell'espressione è uguale alla variabileDiControllo
* <op_confronto> <espressione>:
il codice viene eseguito se è vero che: <variabileDiControllo> <op_confronto> <espressione>
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 <nome> [con <parametro>[, <parametro>]] {
<codice>
}
che definisce la funzione <nome> con i parametri in ingresso specificati
Le funzioni sono invocate con la sintassi:
brematurata la supercazzola <nome> con [<parametro>[, <parametro>]]
*** 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 <condizione>!
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)

13
Type.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef TYPE_H
#define TYPE_H
typedef enum {
TYPENAME_INT,
TYPENAME_CHAR,
TYPENAME_FLOAT,
TYPENAME_BOOL,
TYPENAME_DOUBLE
} Type;
#endif

31
main.c Normal file
View File

@ -0,0 +1,31 @@
#include "Type.h"
#include "Monicelli.tab.h"
#include <stdio.h>
#include <stdarg.h>
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();
}