From 8c813602d4c603a0a966597f3eaad01099f1b31d Mon Sep 17 00:00:00 2001 From: Stefano Sanfilippo Date: Sat, 29 Nov 2014 22:31:25 +0100 Subject: [PATCH 01/23] Stop compilation when an unexpected character is encountered. --- Monicelli.lpp | 2 +- Monicelli.ypp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Monicelli.lpp b/Monicelli.lpp index 7d725a1..1e189c8 100644 --- a/Monicelli.lpp +++ b/Monicelli.lpp @@ -197,7 +197,7 @@ CHAR [a-zA-Z_] } . { - return -1; + return token::ERROR; } %% diff --git a/Monicelli.ypp b/Monicelli.ypp index 4fa0e33..d8e6bf3 100644 --- a/Monicelli.ypp +++ b/Monicelli.ypp @@ -51,7 +51,7 @@ static int yylex(Parser::semantic_type*, Parser::location_type*, Scanner&); } -%token MAIN +%token MAIN ERROR %token RETURN %token ARTICLE TYPENAME STAR %token VARDECL ASSIGN @@ -401,6 +401,7 @@ simple_expression: void Parser::error(const location_type& loc, const std::string &message) { std::cerr << "line " << loc.begin.line << ", col " << loc.begin.column; std::cerr << ": " << message << std::endl; + std::exit(1); } int yylex(Parser::semantic_type *lval, Parser::location_type *loc, Scanner &scanner) { From ad80fc51301f7349b04d50db71b13b5791e00dc3 Mon Sep 17 00:00:00 2001 From: Stefano Sanfilippo Date: Sat, 29 Nov 2014 22:37:57 +0100 Subject: [PATCH 02/23] Support for floating point literals. --- Monicelli.lpp | 14 ++++++++++---- examples/float.mc | 12 ++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 examples/float.mc diff --git a/Monicelli.lpp b/Monicelli.lpp index 1e189c8..f60c81f 100644 --- a/Monicelli.lpp +++ b/Monicelli.lpp @@ -22,7 +22,6 @@ #include "Parser.hpp" #include -#include static void meta(const char *); @@ -191,9 +190,16 @@ CHAR [a-zA-Z_] return token::ID; } -{DIGIT}+ { - lval->intval = strtol(yytext, NULL, 10); - return token::NUMBER; +[-+]?(({DIGIT}*".")?{DIGIT}+|{DIGIT}+".")([eE][-+]?{DIGIT}+)? { + std::string value(yytext); + + if (value.find(".") != std::string::npos) { + lval->floatval = std::stod(value); + return token::FLOAT; + } else { + lval->intval = std::stol(value); + return token::NUMBER; + } } . { diff --git a/examples/float.mc b/examples/float.mc new file mode 100644 index 0000000..12389c9 --- /dev/null +++ b/examples/float.mc @@ -0,0 +1,12 @@ +# Test all possible numerical forms (integer and float) + +Lei ha clacsonato + +2.0 a posterdati +-2.0 a posterdati +2. a posterdati +.232 a posterdati +-2 a posterdati +-.2233 a posterdati ++2 a posterdati ++2.233e-23 a posterdati From 76a4e3d7f29b85ded864d758a9b496411e39d0f5 Mon Sep 17 00:00:00 2001 From: Stefano Sanfilippo Date: Sun, 30 Nov 2014 13:03:45 +0100 Subject: [PATCH 03/23] Adding support for functions. --- Monicelli.ypp | 37 ++++++++++++++++++++++++------------- Nodes.cpp | 10 +++++++++- Nodes.hpp | 28 ++++++++++++++++++++++++---- examples/syntax.beauty.mc | 2 +- examples/syntax.mc | 4 ++-- 5 files changed, 60 insertions(+), 21 deletions(-) diff --git a/Monicelli.ypp b/Monicelli.ypp index d8e6bf3..7756ef5 100644 --- a/Monicelli.ypp +++ b/Monicelli.ypp @@ -79,6 +79,7 @@ static std::stack stmtStack; static std::stack argsStack; static std::stack paramsStack; static std::stack branchCaseStack; +static std::stack funArgStack; } %union { @@ -105,18 +106,20 @@ static std::stack branchCaseStack; Id* idval; Number* numericval; Function* funval; + FunArg *argval; Main* mainval; } %type NUMBER %type FLOAT %type ID -%type TYPENAME +%type TYPENAME fun_return %type statement %type branch_body %type assert_stmt %type fun_call +%type arg_decl %type fun_decl %type print_stmt %type input_stmt @@ -152,28 +155,36 @@ fun_decls: fun_decls ; fun_decl: - FUNDECL ID { - paramsStack.push(new IdList()); + FUNDECL fun_return ID { + funArgStack.push(new FunArgList()); } args FUN_END { stmtStack.push(new StatementList()); } statements { - $$ = new Function(new Id($2), paramsStack.top(), stmtStack.top()); - paramsStack.pop(); + $$ = new Function(new Id($3), $2, funArgStack.top(), stmtStack.top()); + funArgStack.pop(); stmtStack.pop(); } ; -args: - /* epsilon */ | PARAMS arglist +fun_return: + /* epsilon */ { $$ = Type::VOID; } | TYPENAME { $$ = $1; } ; -arglist: - variable { - paramsStack.top()->push_back($1); +args: + /* epsilon */ | PARAMS args_decl +; +args_decl: + arg_decl { + funArgStack.top()->push_back($1); } - | variable { - paramsStack.top()->push_back($1); + | arg_decl { + funArgStack.top()->push_back($1); + } + COMMA args_decl +; +arg_decl: + variable pointer TYPENAME { + $$ = new FunArg($1, $3, $2); } - arglist ; main: MAIN { diff --git a/Nodes.cpp b/Nodes.cpp index 92853f6..1ed587b 100644 --- a/Nodes.cpp +++ b/Nodes.cpp @@ -40,6 +40,9 @@ std::ostream& monicelli::operator<<(std::ostream &stream, const Type &type) { case Type::DOUBLE: stream << "double"; break; + case Type::VOID: + stream << "void"; + break; } return stream; @@ -185,10 +188,15 @@ void FunctionCall::emit(std::ostream &stream, int indent) { stream << ")"; } +void FunArg::emit(std::ostream &stream, int indent) { + stream << type << (pointer? "* ": " "); + name->emit(stream); +} + void Function::emit(std::ostream &stream, int indent) { emitIndent(stream, indent); - stream << "void "; + stream << type << ' '; name->emit(stream); stream << "("; args->emit(stream); diff --git a/Nodes.hpp b/Nodes.hpp index e635bb3..b51aeaa 100644 --- a/Nodes.hpp +++ b/Nodes.hpp @@ -31,7 +31,8 @@ enum class Type { CHAR, FLOAT, BOOL, - DOUBLE + DOUBLE, + VOID }; std::ostream& operator<<(std::ostream &stream, const Type &type); @@ -285,20 +286,39 @@ private: }; +class FunArg: public Emittable { +public: + FunArg(Id *n, Type t, bool p): name(n), type(t), pointer(p) {} + virtual ~FunArg() {} + + virtual void emit(std::ostream &stream, int indent = 0); + +private: + Pointer name; + Type type; + bool pointer; +}; + + +typedef ListEmittable FunArgList; + + class Function: public Emittable { public: - Function(Id *n, IdList *a, StatementList *b): - name(n), args(a), body(b) {} + Function(Id *n, Type r, FunArgList *a, StatementList *b): + name(n), type(r), args(a), body(b) {} virtual ~Function() {} virtual void emit(std::ostream &stream, int indent = 0); private: Pointer name; - Pointer args; + Type type; + Pointer args; Pointer body; }; + class Program: public Emittable { public: virtual void emit(std::ostream &stream, int indent = 0); diff --git a/examples/syntax.beauty.mc b/examples/syntax.beauty.mc index 59f123a..4d180bc 100644 --- a/examples/syntax.beauty.mc +++ b/examples/syntax.beauty.mc @@ -40,7 +40,7 @@ Lei ha clacsonato vicesindaco come se fosse brematurata la supercazzola avanti con il vicesindaco o scherziamo, vaffanzum 0! -blinda la supercazzola antanizzata con alfio o scherziamo? +blinda la supercazzola Necchi antanizzata con alfio Mascetti, barilotto Necchi o scherziamo? vaffanzum alfio meno 2! bituma al finale? diff --git a/examples/syntax.mc b/examples/syntax.mc index 2c21ac9..911d84a 100644 --- a/examples/syntax.mc +++ b/examples/syntax.mc @@ -10,5 +10,5 @@ o tarapia tapioco: mi porga il cappello e velocità di esecuzione, vicesindaco a posterdati, mi porga il vicesindaco, brematurata la supercazzola tombale con alfio, serio o scherziamo? avvertite don ulrico, ho visto la signora! vicesindaco come se fosse brematurata la supercazzola avanti con il vicesindaco -o scherziamo, vaffanzum 0! blinda la supercazzola antanizzata con alfio o scherziamo? -vaffanzum alfio meno 2! bituma al finale? +o scherziamo, vaffanzum 0! blinda la supercazzola Necchi antanizzata con alfio +Mascetti o scherziamo? vaffanzum alfio meno 2! bituma al finale? From 0a49ccfeca6fa1f7b275479650ac429cc1628b50 Mon Sep 17 00:00:00 2001 From: Stefano Sanfilippo Date: Sun, 30 Nov 2014 13:05:59 +0100 Subject: [PATCH 04/23] Emitting prototypes for all declared functions. --- Nodes.cpp | 18 +++++++++++++++--- Nodes.hpp | 1 + 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Nodes.cpp b/Nodes.cpp index 1ed587b..8df3fe3 100644 --- a/Nodes.cpp +++ b/Nodes.cpp @@ -194,15 +194,20 @@ void FunArg::emit(std::ostream &stream, int indent) { } void Function::emit(std::ostream &stream, int indent) { + emitSignature(stream, indent); + stream << " {\n"; + body->emit(stream, indent + 1); + stream << "}\n\n"; +} + +void Function::emitSignature(std::ostream &stream, int indent) { emitIndent(stream, indent); stream << type << ' '; name->emit(stream); stream << "("; args->emit(stream); - stream << ") {\n"; - body->emit(stream, indent + 1); - stream << "}\n\n"; + stream << ")"; } void Main::emit(std::ostream &stream, int indent) { @@ -217,6 +222,13 @@ void Program::emit(std::ostream &stream, int indent) { stream << "#include \n"; stream << "#include \n\n"; + for (Function *f: functions) { + f->emitSignature(stream); + stream << ";\n"; + } + + stream << "\n"; + for (Function *f: functions) { f->emit(stream); } diff --git a/Nodes.hpp b/Nodes.hpp index b51aeaa..b7e18c3 100644 --- a/Nodes.hpp +++ b/Nodes.hpp @@ -310,6 +310,7 @@ public: virtual ~Function() {} virtual void emit(std::ostream &stream, int indent = 0); + void emitSignature(std::ostream &stream, int indent = 0); private: Pointer name; From a6954b6ff7ec7e0ad58eae114f38f7d5647a56f3 Mon Sep 17 00:00:00 2001 From: Stefano Sanfilippo Date: Sun, 30 Nov 2014 13:17:30 +0100 Subject: [PATCH 05/23] Documenting function declaration and invocation in README. --- README.md | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 681bbb7..36e1c1e 100644 --- a/README.md +++ b/README.md @@ -285,10 +285,59 @@ where the `o tarapia tapioco` part is like the `default` block. Functions --------- -_Coming in a few releases..._. +###Declaration -We can already parse and emit them, although there are some ambiguities -yet to be solved in the specification. +A function is declared with the `blinda la supercazzola` statement: + + blinda la supercazzola [] [con [, ...]] o scherziamo? + + +Where `` can be omitted for a void function. For instance: + + blinda la supercazzola Necchi antanizzata con alfio Mascetti o scherziamo? + vaffanzum alfio meno 2! + +is a function of type `Necchi`, taking one argument of type `Mascetti`. +Multiple arguments must be comma-separed, like in: + + blinda la supercazzola Necchi antanizzata con alfio Mascetti, barilotto Necchi o scherziamo? + vaffanzum alfio meno 2! + +which is a function of type `Necchi`, taking two arguments of type `Mascetti` +and `Necchi`. It maps to: + + int antanizzata(char alfio, int barilotto) { + return alfio - 2; + } + +Finally, this: + + blinda la supercazzola antanizzata o scherziamo? + vaffanzum alfio meno 2! + +is a `void` function taking no arguments and becomes: + + void antanizzata() { + return alfio - 2; + } + +Functions cannot be nested and can be declared before or after the main in any +order. `mcc` will not check that a return statement is always reachable inside + a non-void function. Failing to return a value leads to undefined behaviour. + +###Invocation + +A function is called with the `brematurata la supercazzola` statement: + + brematurata la supercazzola [con [, ...] o scherziamo? + +Functions might be called inside expressions. For instance, this: + + antani come se fosse brematurata la supercazzola alfio con barilotto diviso 3 o scherziamo? per 2 + +maps to: + + antani = alfio(barilotto / 3) * 2; Exceptions ---------- From 2bc017d0bb0569dda4d68e627190db5db5bc405e Mon Sep 17 00:00:00 2001 From: Stefano Sanfilippo Date: Sun, 30 Nov 2014 13:19:19 +0100 Subject: [PATCH 06/23] Allow floating point literals with exponent and without decimal part. --- Monicelli.lpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Monicelli.lpp b/Monicelli.lpp index f60c81f..e79dd0b 100644 --- a/Monicelli.lpp +++ b/Monicelli.lpp @@ -29,6 +29,12 @@ using namespace monicelli; typedef Parser::token token; #define YY_USER_ACTION location->begin.columns(yyleng); + +inline +bool in(const char *sub, const std::string &str) { + return str.find(sub) != std::string::npos; +} + %} %option ecs stack warn c++ @@ -193,7 +199,7 @@ CHAR [a-zA-Z_] [-+]?(({DIGIT}*".")?{DIGIT}+|{DIGIT}+".")([eE][-+]?{DIGIT}+)? { std::string value(yytext); - if (value.find(".") != std::string::npos) { + if (in(".", value) || in("e", value) || in("E", value)) { lval->floatval = std::stod(value); return token::FLOAT; } else { From 36de368b19f03643c9aff70270ffa75cc3970456 Mon Sep 17 00:00:00 2001 From: Stefano Sanfilippo Date: Sun, 30 Nov 2014 13:40:08 +0100 Subject: [PATCH 07/23] Enclose output expression in (). --- Nodes.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Nodes.cpp b/Nodes.cpp index 8df3fe3..f2d2515 100644 --- a/Nodes.cpp +++ b/Nodes.cpp @@ -161,9 +161,9 @@ void Assignment::emit(std::ostream &stream, int indent) { } void Print::emit(std::ostream &stream, int indent) { - stream << "std::cout << "; + stream << "std::cout << ("; expression->emit(stream); - stream << " << std::endl"; + stream << ") << std::endl"; } void Input::emit(std::ostream &stream, int indent) { From 8913c12a7f552d2b08f7f5313cc948cca29ad08a Mon Sep 17 00:00:00 2001 From: Alessandro Pellegrini Date: Sun, 30 Nov 2014 20:33:17 +0100 Subject: [PATCH 08/23] Hello World There cannot be any programming language without a Hello World. --- examples/hello-world.mc | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 examples/hello-world.mc diff --git a/examples/hello-world.mc b/examples/hello-world.mc new file mode 100644 index 0000000..1a8a4d7 --- /dev/null +++ b/examples/hello-world.mc @@ -0,0 +1,16 @@ +# Author: Alessandro Pellegrini +# Released under GPLv3 + +Lei ha clacsonato +voglio una bucaiola, Necchi come se fosse 0 voglio prematurata, Mascetti come se fosse 72 +prematurata a posterdati voglio antifurto, Mascetti come se fosse 87. +voglio una cofandina, Mascetti come se fosse prematurata con scappellamento a sinistra per 1. +cofandina come fosse cofandina meno 33 brematurata la supercazzola antanizzata con antifurto, +cofandina o scherziamo? vaffanzum bucaiola! bituma scusi, noi siamo in quattro. +blinda la supercazzola antanizzata con Alfio Mascetti, tarapia Mascetti o scherziamo? +voglio vicesindaco, Mascetti come se fosse 101 vicesindaco a posterdati voglio pastene, +Mascetti come se fosse vicesindaco più 7 pastene a posterdati bituma in un certo senso. +pastene a posterdati tarapia a posterdati Alfio a posterdati tarapia a posterdati +voglio scappellamento, Mascetti come se fosse 114 scappellamento a posterdati +pastene a posterdati voglio Antani, Mascetti come se fosse pastene meno 8 Antani a posterdati +vaffanzum! From e9be8b4419312f8f2865dc8060a083bfff191b3a Mon Sep 17 00:00:00 2001 From: Alessandro Gatti Date: Sat, 29 Nov 2014 23:37:28 +0100 Subject: [PATCH 09/23] Don't assume Italian accented characters are available. --- Monicelli.lpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Monicelli.lpp b/Monicelli.lpp index e79dd0b..14b5b73 100644 --- a/Monicelli.lpp +++ b/Monicelli.lpp @@ -93,7 +93,7 @@ CHAR [a-zA-Z_] ("il"|"lo"|"la"|"l'"|"i"|"gli"|"le"|"un"|"un'"|"una"|"dei"|"delle") { return token::ARTICLE; } -"più" { +"pi"("ù"|"u`") { return token::OP_PLUS; } "meno" { @@ -147,7 +147,7 @@ CHAR [a-zA-Z_] "e "("b"|"p")"rematura anche, se" { return token::LOOP_CONDITION; } -"che cos'è" { +"che cos'"("è"|"e`") { return token::BRANCH_CONDITION; } "?" { @@ -156,7 +156,7 @@ CHAR [a-zA-Z_] "o tarapia tapioco" { return token::BRANCH_ELSE; } -"e velocità di esecuzione" { +"e velocit"("à"|"a`")" di esecuzione" { return token::BRANCH_END; } ":" { From 10034f38df3455ee63558afedfd05ab63f6f8d12 Mon Sep 17 00:00:00 2001 From: Stefano Sanfilippo Date: Mon, 1 Dec 2014 00:29:49 +0100 Subject: [PATCH 10/23] Accept "supercazzora" as alternate spelling of "supercazzola". As mentioned in #2 --- Monicelli.lpp | 4 ++-- README.md | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Monicelli.lpp b/Monicelli.lpp index 14b5b73..b68d2e5 100644 --- a/Monicelli.lpp +++ b/Monicelli.lpp @@ -162,7 +162,7 @@ CHAR [a-zA-Z_] ":" { return token::COLON; } -"blinda la supercazzola" { +"blinda la supercazzo"("r"|"l")"a" { return token::FUNDECL; } "con" { @@ -171,7 +171,7 @@ CHAR [a-zA-Z_] "," { return token::COMMA; } -("b"|"p")"rematurata la supercazzola" { +("b"|"p")"rematurata la supercazzo"("r"|"l")"a" { return token::FUNCALL; } "o scherziamo"("?")? { diff --git a/README.md b/README.md index 36e1c1e..8c417bd 100644 --- a/README.md +++ b/README.md @@ -285,6 +285,9 @@ where the `o tarapia tapioco` part is like the `default` block. Functions --------- +**Note**: the alternate spelling `supercazzora` might be used in place + of `supercazzola` wherever the latter appears. + ###Declaration A function is declared with the `blinda la supercazzola` statement: From d031031e4efc638f416e8707140f7f1d603931c6 Mon Sep 17 00:00:00 2001 From: Stefano Sanfilippo Date: Mon, 1 Dec 2014 00:33:57 +0100 Subject: [PATCH 11/23] Void functions might not return a value. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8c417bd..5b69159 100644 --- a/README.md +++ b/README.md @@ -316,12 +316,12 @@ and `Necchi`. It maps to: Finally, this: blinda la supercazzola antanizzata o scherziamo? - vaffanzum alfio meno 2! + vaffanzum! is a `void` function taking no arguments and becomes: void antanizzata() { - return alfio - 2; + return; } Functions cannot be nested and can be declared before or after the main in any From ffb2c6f9754d60dff10bd0613433c3192ca6dfd2 Mon Sep 17 00:00:00 2001 From: Stefano Sanfilippo Date: Mon, 1 Dec 2014 09:55:06 +0100 Subject: [PATCH 12/23] Make in() static since it's not supposed to be used outside the lexer. --- Monicelli.lpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Monicelli.lpp b/Monicelli.lpp index b68d2e5..e7e4336 100644 --- a/Monicelli.lpp +++ b/Monicelli.lpp @@ -30,7 +30,7 @@ typedef Parser::token token; #define YY_USER_ACTION location->begin.columns(yyleng); -inline +static inline bool in(const char *sub, const std::string &str) { return str.find(sub) != std::string::npos; } From 87ca7614e4087aff9c7ce1d07c85bf50cecb2615 Mon Sep 17 00:00:00 2001 From: Stefano Sanfilippo Date: Mon, 1 Dec 2014 10:16:56 +0100 Subject: [PATCH 13/23] Crediting the people who contributed to the initial specs. --- README.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 5b69159..0e8d8f7 100644 --- a/README.md +++ b/README.md @@ -46,10 +46,14 @@ The compiler reads from standard input and print result to standard output. Language overview ================= -The original specification can be found in `Specification.txt`, which -unfortunately is not complete. This project is an ongoing effort to implement -it, which means filling gaps and ambiguities. This file only documents -usable features of the language. +The original specification can be found in `Specification.txt`, and was +initially conceived by my colleagues and dear friends Alessandro Barenghi, +Michele Tartara and Nicola Vitucci, to whom goes my gratitude. + +Unfortunately, their proposal was meant to be a joke and is not complete. +This project is an ongoing effort to produce a rigorous specification for the +language and implement a compiler, which implies filling gaps and ambiguities +with sensible choices. Statements have no terminator, i.e. no semicolon `;` or the like. A single statement can be split across multiple lines and multiple statements can be From b254b63faf8fa47f79e8af592c5fcf4418f763a9 Mon Sep 17 00:00:00 2001 From: Stefano Sanfilippo Date: Mon, 1 Dec 2014 10:17:14 +0100 Subject: [PATCH 14/23] Accented letters vs. backtick + smal fix to README. --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0e8d8f7..1c39b35 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,10 @@ words **cannot** be split on multiple lines. A comma might be inserted after each statement, if it fits the sentence ;) +Accented letters can be replaced by the non-accented letter followed by a +backtick `` ` ``, although the use of the correct Italian spelling is strongly +encouraged for maximizing the antani effect. + Main ---- @@ -198,7 +202,7 @@ defined as follows: For example: voglio antani, Necchi come se fosse 10 - stuzzica: + stuzzica antani come fosse antani meno 1 e brematura anche, se antani maggiore di 0 From 761ce64ca28ebb86b8551b301cd6bcdffc640d6d Mon Sep 17 00:00:00 2001 From: Stefano Sanfilippo Date: Mon, 1 Dec 2014 10:19:25 +0100 Subject: [PATCH 15/23] More meaningful example for bituma comment. --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1c39b35..9fc7e50 100644 --- a/README.md +++ b/README.md @@ -371,9 +371,11 @@ Comments -------- Any character after `bituma` is ignored until a line break is encountered. For -instance: +instance, in: - antani come se fossee 4 bituma lorem ipsum + antani come se fosse 4 bituma, scusi, noi siamo in quattro + +`, scusi, noi siamo in quattro` is ignored. Comments are useful to fill the "supercazzola" and make it more readable, since any word (including reserved words) can be inserted into it. From 8e80aa4969d94bf634bdda885f7614b7af44d7ea Mon Sep 17 00:00:00 2001 From: Stefano Sanfilippo Date: Tue, 2 Dec 2014 01:34:39 +0100 Subject: [PATCH 16/23] Show the variable name when asking the user for some input. --- Nodes.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Nodes.cpp b/Nodes.cpp index f2d2515..3a33b50 100644 --- a/Nodes.cpp +++ b/Nodes.cpp @@ -167,6 +167,10 @@ void Print::emit(std::ostream &stream, int indent) { } void Input::emit(std::ostream &stream, int indent) { + stream << "std::cout << \""; + variable->emit(stream); + stream << "? \";\n"; + emitIndent(stream, indent); stream << "std::cin >> "; variable->emit(stream); } From 5160c82adbff473832aa40362bdbffbb088457e4 Mon Sep 17 00:00:00 2001 From: Stefano Sanfilippo Date: Tue, 2 Dec 2014 13:09:17 +0100 Subject: [PATCH 17/23] Add a note to Specification.txt to remark that it's not up-to-date. --- Specification.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Specification.txt b/Specification.txt index 676563a..f0ef8ed 100644 --- a/Specification.txt +++ b/Specification.txt @@ -1,3 +1,14 @@ +------------------------------------------------------------------------- + +NOTE: this document was left here only for historical purposes, + refer to REAMDE.md for the current spec. + +NOTA: questo documento è obsoleto ed è qui solo per memoria storica, in + quanto rappresenta la prima specifica proposta per il linguaggio. + README.md contiene l'attuale versione. + +------------------------------------------------------------------------- + Proposte per la definizione di un linguaggio di programmazione esoterico "Monicelli" Il "main" del programma inizia in corrispondenza di: From e984b5d0ea8a2790dcd70644fdf23257ab1d6403 Mon Sep 17 00:00:00 2001 From: Stefano Sanfilippo Date: Tue, 2 Dec 2014 14:14:58 +0100 Subject: [PATCH 18/23] Uniform token naming convention. --- Monicelli.lpp | 4 ++-- Monicelli.ypp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Monicelli.lpp b/Monicelli.lpp index e7e4336..bb67002 100644 --- a/Monicelli.lpp +++ b/Monicelli.lpp @@ -163,7 +163,7 @@ CHAR [a-zA-Z_] return token::COLON; } "blinda la supercazzo"("r"|"l")"a" { - return token::FUNDECL; + return token::FUN_DECL; } "con" { return token::PARAMS; @@ -172,7 +172,7 @@ CHAR [a-zA-Z_] return token::COMMA; } ("b"|"p")"rematurata la supercazzo"("r"|"l")"a" { - return token::FUNCALL; + return token::FUN_CALL; } "o scherziamo"("?")? { return token::FUN_END; diff --git a/Monicelli.ypp b/Monicelli.ypp index 7756ef5..7e6664a 100644 --- a/Monicelli.ypp +++ b/Monicelli.ypp @@ -60,7 +60,7 @@ %token LOOP_BEGIN LOOP_CONDITION %token BRANCH_CONDITION BRANCH_BEGIN BRANCH_ELSE BRANCH_END CASE_END %token COLON COMMA -%token FUNDECL PARAMS FUNCALL FUN_END +%token FUN_DECL PARAMS FUN_CALL FUN_END %token ABORT %token ID NUMBER FLOAT @@ -155,7 +155,7 @@ fun_decls: fun_decls ; fun_decl: - FUNDECL fun_return ID { + FUN_DECL fun_return ID { funArgStack.push(new FunArgList()); } args FUN_END { stmtStack.push(new StatementList()); @@ -305,7 +305,7 @@ case_stmt: } ; fun_call: - FUNCALL { + FUN_CALL { argsStack.push(new ExpressionList()); } ID call_args FUN_END { From 2f66c31729f8b50205035fb2549758eb4a596830 Mon Sep 17 00:00:00 2001 From: Stefano Sanfilippo Date: Tue, 2 Dec 2014 16:22:03 +0100 Subject: [PATCH 19/23] Getting rid of explicit stacks with more left-recursive rules. As a result, the grammar should be more readable. --- Monicelli.ypp | 127 ++++++++++++++++++++++---------------------------- Nodes.cpp | 10 ++-- Nodes.hpp | 17 +++++-- 3 files changed, 74 insertions(+), 80 deletions(-) diff --git a/Monicelli.ypp b/Monicelli.ypp index 7e6664a..8840c34 100644 --- a/Monicelli.ypp +++ b/Monicelli.ypp @@ -1,6 +1,6 @@ /* * Monicelli: an esoteric language compiler - * + * * Copyright (C) 2014 Stefano Sanfilippo * * This program is free software: you can redistribute it and/or modify @@ -72,16 +72,6 @@ %nonassoc LOWER_THAN_ELSE %nonassoc BRANCH_ELSE -%code { -#include - -static std::stack stmtStack; -static std::stack argsStack; -static std::stack paramsStack; -static std::stack branchCaseStack; -static std::stack funArgStack; -} - %union { int intval; double floatval; @@ -96,17 +86,21 @@ static std::stack funArgStack; Input* inputval; Abort* abortval; Branch* branchval; + Branch::Body* branchbodyval; VarDeclaration* declval; Assignment* assignval; Loop* loopval; BranchCase *caseval; + BranchCaseList *caselistval; Return* returnval; Expression* expressionval; + ExpressionList* exprlistval; SemiExpression *semiexpval; Id* idval; Number* numericval; Function* funval; FunArg *argval; + FunArgList *arglistval; Main* mainval; } @@ -114,23 +108,26 @@ static std::stack funArgStack; %type FLOAT %type ID %type TYPENAME fun_return - %type statement -%type branch_body +%type statements +%type branch_body %type assert_stmt %type fun_call %type arg_decl +%type args_decl args %type fun_decl %type print_stmt %type input_stmt %type abort_stmt %type branch_stmt %type case_stmt +%type cases %type var_decl %type assign_stmt %type loop_stmt %type return_stmt %type expression maybe_expression simple_expression var_init +%type call_arglist call_args %type semi_expression %type variable %type numeric @@ -155,31 +152,24 @@ fun_decls: fun_decls ; fun_decl: - FUN_DECL fun_return ID { - funArgStack.push(new FunArgList()); - } args FUN_END { - stmtStack.push(new StatementList()); - } - statements { - $$ = new Function(new Id($3), $2, funArgStack.top(), stmtStack.top()); - funArgStack.pop(); - stmtStack.pop(); + FUN_DECL fun_return ID args FUN_END statements { + $$ = new Function(new Id($3), $2, $4, $6); } ; fun_return: /* epsilon */ { $$ = Type::VOID; } | TYPENAME { $$ = $1; } ; args: - /* epsilon */ | PARAMS args_decl + /* epsilon */ { $$ = new FunArgList(); }| PARAMS args_decl { $$ = $2; } ; args_decl: arg_decl { - funArgStack.top()->push_back($1); + $$ = new FunArgList(); + $$->push_back($1); } - | arg_decl { - funArgStack.top()->push_back($1); + | args_decl COMMA arg_decl { + $1->push_back($3); } - COMMA args_decl ; arg_decl: variable pointer TYPENAME { @@ -187,23 +177,20 @@ arg_decl: } ; main: - MAIN { - stmtStack.push(new StatementList()); - } - statements { - $$ = new Main(stmtStack.top()); - stmtStack.pop(); + MAIN statements { + $$ = new Main($2); } ; statements: /* epsilon */ { + $$ = new StatementList(); } - | statement { - if ($1 != nullptr) { - stmtStack.top()->push_back($1); + | statements statement { + if ($2 != nullptr) { + $1->push_back($2); } + $$ = $1; } - statements ; statement: assert_stmt { $$ = $1; } @@ -264,61 +251,59 @@ maybe_expression: expression { $$ = $1; } | /* epsilon */ { $$ = nullptr; } ; loop_stmt: - LOOP_BEGIN { - stmtStack.push(new StatementList()); - } - statements LOOP_CONDITION expression { - $$ = new Loop(stmtStack.top(), $5); - stmtStack.pop(); + LOOP_BEGIN statements LOOP_CONDITION expression { + $$ = new Loop($2, $4); } ; branch_stmt: - BRANCH_CONDITION variable BRANCH_BEGIN { - branchCaseStack.push(new BranchCaseList()); - } - branch_body BRANCH_END { - $$ = new Branch($2, branchCaseStack.top(), $5); - branchCaseStack.pop(); + BRANCH_CONDITION variable BRANCH_BEGIN branch_body BRANCH_END { + $$ = new Branch($2, $4); } ; branch_body: cases %prec LOWER_THAN_ELSE { - $$ = nullptr; + $$ = new Branch::Body($1); } - | cases BRANCH_ELSE COLON { - stmtStack.push(new StatementList()); - } - statements { - $$ = stmtStack.top(); - stmtStack.pop(); + | cases BRANCH_ELSE COLON statements { + $$ = new Branch::Body($1, $4); } ; cases: - case_stmt | case_stmt CASE_END cases + case_stmt { + $$ = new BranchCaseList(); + $$->push_back($1); + } + | cases CASE_END case_stmt { + $1->push_back($3); + $$ = $1; + } ; case_stmt: - semi_expression COLON { - stmtStack.push(new StatementList()); - } statements { - branchCaseStack.top()->push_back(new BranchCase($1, stmtStack.top())); - stmtStack.pop(); + semi_expression COLON statements { + $$ = new BranchCase($1, $3); } ; fun_call: - FUN_CALL { - argsStack.push(new ExpressionList()); - } - ID call_args FUN_END { - $$ = new FunctionCall(new Id($3), argsStack.top()); - argsStack.pop(); + FUN_CALL ID call_args FUN_END { + $$ = new FunctionCall(new Id($2), $3); } ; call_args: - /* epsilon */ | PARAMS call_arglist + /* epsilon */ { + $$ = new ExpressionList(); + } + | PARAMS call_arglist { + $$ = $2; + } ; call_arglist: - expression { argsStack.top()->push_back($1); } - | expression { argsStack.top()->push_back($1); } COMMA call_arglist + expression { + $$ = new ExpressionList(); + $$->push_back($1); + } + | call_arglist COMMA expression { + $$->push_back($3); + } ; abort_stmt: ABORT { diff --git a/Nodes.cpp b/Nodes.cpp index 3a33b50..002b2bd 100644 --- a/Nodes.cpp +++ b/Nodes.cpp @@ -122,9 +122,9 @@ void Branch::emit(std::ostream &stream, int indent) { stream << "if ("; var->emit(stream); - if (cases->size() > 0) { - BranchCase *last = cases->back(); - for (BranchCase *c: *cases) { + if (body->cases->size() > 0) { + BranchCase *last = body->cases->back(); + for (BranchCase *c: *body->cases) { c->emit(stream, indent + 1); if (c != last) { stream << " else if ("; @@ -133,12 +133,12 @@ void Branch::emit(std::ostream &stream, int indent) { } } - if (els == nullptr) { + if (body->els == nullptr) { return; } stream << " else {\n"; - els->emit(stream, indent + 1); + body->els->emit(stream, indent + 1); emitIndent(stream, indent); stream << "}"; } diff --git a/Nodes.hpp b/Nodes.hpp index b7e18c3..546a68e 100644 --- a/Nodes.hpp +++ b/Nodes.hpp @@ -265,14 +265,23 @@ typedef PointerList BranchCaseList; class Branch: public Statement { public: - Branch(Id *v, BranchCaseList *c, StatementList *e): - var(v), cases(c), els(e) {} + struct Body { + public: + Body(BranchCaseList *c, StatementList *e = nullptr): cases(c), els(e) {} + + private: + Pointer cases; + Pointer els; + + friend class Branch; + }; + + Branch(Id *v, Branch::Body *b): var(v), body(b) {} virtual void emit(std::ostream &stream, int indent = 0); private: Pointer var; - Pointer cases; - Pointer els; + Pointer body; }; From c4dd6e3c6b68f86c9a26dfc33083bb9f759b4a21 Mon Sep 17 00:00:00 2001 From: Stefano Sanfilippo Date: Tue, 2 Dec 2014 16:28:01 +0100 Subject: [PATCH 20/23] Removing extra \n when no functions are defined. --- Nodes.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Nodes.cpp b/Nodes.cpp index 002b2bd..3dbc097 100644 --- a/Nodes.cpp +++ b/Nodes.cpp @@ -231,7 +231,9 @@ void Program::emit(std::ostream &stream, int indent) { stream << ";\n"; } - stream << "\n"; + if (!functions.empty()) { + stream << "\n"; + } for (Function *f: functions) { f->emit(stream); From e5fd0ed6bc2aa11a82ec41c744434a8332fc1651 Mon Sep 17 00:00:00 2001 From: Stefano Sanfilippo Date: Tue, 2 Dec 2014 17:28:21 +0100 Subject: [PATCH 21/23] Honour CXX environment variable. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5b5fc51..3bb8848 100644 --- a/Makefile +++ b/Makefile @@ -24,8 +24,8 @@ bison2: patch2 default unpatch2 compile: bison Monicelli.ypp flex Monicelli.lpp - g++ \ -Wall -Wno-deprecated-register -std=c++11 -DYYDEBUG=0 -O2 \ + $(CXX) \ Parser.cpp lex.yy.cc Nodes.cpp main.cpp -o mcc patch2: From f148814087a0dbf08c5c4185781fba2c0d3e83e1 Mon Sep 17 00:00:00 2001 From: Stefano Sanfilippo Date: Tue, 2 Dec 2014 17:28:42 +0100 Subject: [PATCH 22/23] g++ 4.6.x compatibility --- Makefile | 2 +- Nodes.hpp | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 3bb8848..102b29b 100644 --- a/Makefile +++ b/Makefile @@ -24,8 +24,8 @@ bison2: patch2 default unpatch2 compile: bison Monicelli.ypp flex Monicelli.lpp - -Wall -Wno-deprecated-register -std=c++11 -DYYDEBUG=0 -O2 \ $(CXX) \ + -Wall -Wno-deprecated-register -std=c++0x -DYYDEBUG=0 -O2 \ Parser.cpp lex.yy.cc Nodes.cpp main.cpp -o mcc patch2: diff --git a/Nodes.hpp b/Nodes.hpp index 546a68e..572fa54 100644 --- a/Nodes.hpp +++ b/Nodes.hpp @@ -39,7 +39,10 @@ std::ostream& operator<<(std::ostream &stream, const Type &type); template -using Pointer = std::unique_ptr; +class Pointer: public std::unique_ptr { +public: + Pointer(T *p = nullptr): std::unique_ptr(p) {} +}; class Emittable { From ea2c46fcbac8256bb0e2f87d6289b1b2e0e8a079 Mon Sep 17 00:00:00 2001 From: Nicola Sanitate Date: Thu, 4 Dec 2014 11:56:57 +0100 Subject: [PATCH 23/23] Readme.md typo fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9fc7e50..f3929c8 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Usage subset of C++. For those of you who want to get to the code ASAP, the `examples/` folder contains a set of programs covering most of the features of the language. -A good wat to learn on the field is comparing the resulting C++ with the +A good way to learn on the field is comparing the resulting C++ with the input. Well, mostly with the beautified version of the input, `*.beauty.mc`. The compiler reads from standard input and print result to standard output.