Merge branch 'master' into cmake
Conflicts: CMakeLists.txt
This commit is contained in:
commit
d0e1af34b2
|
@ -22,7 +22,6 @@
|
||||||
#include "Parser.hpp"
|
#include "Parser.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
static void meta(const char *);
|
static void meta(const char *);
|
||||||
|
|
||||||
|
@ -30,6 +29,12 @@ using namespace monicelli;
|
||||||
typedef Parser::token token;
|
typedef Parser::token token;
|
||||||
|
|
||||||
#define YY_USER_ACTION location->begin.columns(yyleng);
|
#define YY_USER_ACTION location->begin.columns(yyleng);
|
||||||
|
|
||||||
|
static inline
|
||||||
|
bool in(const char *sub, const std::string &str) {
|
||||||
|
return str.find(sub) != std::string::npos;
|
||||||
|
}
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%option ecs stack warn c++
|
%option ecs stack warn c++
|
||||||
|
@ -88,7 +93,7 @@ CHAR [a-zA-Z_]
|
||||||
("il"|"lo"|"la"|"l'"|"i"|"gli"|"le"|"un"|"un'"|"una"|"dei"|"delle") {
|
("il"|"lo"|"la"|"l'"|"i"|"gli"|"le"|"un"|"un'"|"una"|"dei"|"delle") {
|
||||||
return token::ARTICLE;
|
return token::ARTICLE;
|
||||||
}
|
}
|
||||||
"più" {
|
"pi"("ù"|"u`") {
|
||||||
return token::OP_PLUS;
|
return token::OP_PLUS;
|
||||||
}
|
}
|
||||||
"meno" {
|
"meno" {
|
||||||
|
@ -142,7 +147,7 @@ CHAR [a-zA-Z_]
|
||||||
"e "("b"|"p")"rematura anche, se" {
|
"e "("b"|"p")"rematura anche, se" {
|
||||||
return token::LOOP_CONDITION;
|
return token::LOOP_CONDITION;
|
||||||
}
|
}
|
||||||
"che cos'è" {
|
"che cos'"("è"|"e`") {
|
||||||
return token::BRANCH_CONDITION;
|
return token::BRANCH_CONDITION;
|
||||||
}
|
}
|
||||||
"?" {
|
"?" {
|
||||||
|
@ -151,14 +156,14 @@ CHAR [a-zA-Z_]
|
||||||
"o tarapia tapioco" {
|
"o tarapia tapioco" {
|
||||||
return token::BRANCH_ELSE;
|
return token::BRANCH_ELSE;
|
||||||
}
|
}
|
||||||
"e velocità di esecuzione" {
|
"e velocit"("à"|"a`")" di esecuzione" {
|
||||||
return token::BRANCH_END;
|
return token::BRANCH_END;
|
||||||
}
|
}
|
||||||
":" {
|
":" {
|
||||||
return token::COLON;
|
return token::COLON;
|
||||||
}
|
}
|
||||||
"blinda la supercazzola" {
|
"blinda la supercazzo"("r"|"l")"a" {
|
||||||
return token::FUNDECL;
|
return token::FUN_DECL;
|
||||||
}
|
}
|
||||||
"con" {
|
"con" {
|
||||||
return token::PARAMS;
|
return token::PARAMS;
|
||||||
|
@ -166,8 +171,8 @@ CHAR [a-zA-Z_]
|
||||||
"," {
|
"," {
|
||||||
return token::COMMA;
|
return token::COMMA;
|
||||||
}
|
}
|
||||||
("b"|"p")"rematurata la supercazzola" {
|
("b"|"p")"rematurata la supercazzo"("r"|"l")"a" {
|
||||||
return token::FUNCALL;
|
return token::FUN_CALL;
|
||||||
}
|
}
|
||||||
"o scherziamo"("?")? {
|
"o scherziamo"("?")? {
|
||||||
return token::FUN_END;
|
return token::FUN_END;
|
||||||
|
@ -191,13 +196,20 @@ CHAR [a-zA-Z_]
|
||||||
return token::ID;
|
return token::ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
{DIGIT}+ {
|
[-+]?(({DIGIT}*".")?{DIGIT}+|{DIGIT}+".")([eE][-+]?{DIGIT}+)? {
|
||||||
lval->intval = strtol(yytext, NULL, 10);
|
std::string value(yytext);
|
||||||
return token::NUMBER;
|
|
||||||
|
if (in(".", value) || in("e", value) || in("E", value)) {
|
||||||
|
lval->floatval = std::stod(value);
|
||||||
|
return token::FLOAT;
|
||||||
|
} else {
|
||||||
|
lval->intval = std::stol(value);
|
||||||
|
return token::NUMBER;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
<INITIAL,shift>. {
|
<INITIAL,shift>. {
|
||||||
return -1;
|
return token::ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
147
Monicelli.ypp
147
Monicelli.ypp
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Monicelli: an esoteric language compiler
|
* Monicelli: an esoteric language compiler
|
||||||
*
|
*
|
||||||
* Copyright (C) 2014 Stefano Sanfilippo
|
* Copyright (C) 2014 Stefano Sanfilippo
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -50,7 +50,7 @@
|
||||||
static int yylex(Parser::semantic_type*, Parser::location_type*, Scanner&);
|
static int yylex(Parser::semantic_type*, Parser::location_type*, Scanner&);
|
||||||
}
|
}
|
||||||
|
|
||||||
%token MAIN
|
%token MAIN ERROR
|
||||||
%token RETURN
|
%token RETURN
|
||||||
%token ARTICLE TYPENAME STAR
|
%token ARTICLE TYPENAME STAR
|
||||||
%token VARDECL ASSIGN
|
%token VARDECL ASSIGN
|
||||||
|
@ -59,7 +59,7 @@
|
||||||
%token LOOP_BEGIN LOOP_CONDITION
|
%token LOOP_BEGIN LOOP_CONDITION
|
||||||
%token BRANCH_CONDITION BRANCH_BEGIN BRANCH_ELSE BRANCH_END CASE_END
|
%token BRANCH_CONDITION BRANCH_BEGIN BRANCH_ELSE BRANCH_END CASE_END
|
||||||
%token COLON COMMA
|
%token COLON COMMA
|
||||||
%token FUNDECL PARAMS FUNCALL FUN_END
|
%token FUN_DECL PARAMS FUN_CALL FUN_END
|
||||||
%token ABORT
|
%token ABORT
|
||||||
%token ID NUMBER FLOAT
|
%token ID NUMBER FLOAT
|
||||||
|
|
||||||
|
@ -71,15 +71,6 @@
|
||||||
%nonassoc LOWER_THAN_ELSE
|
%nonassoc LOWER_THAN_ELSE
|
||||||
%nonassoc BRANCH_ELSE
|
%nonassoc BRANCH_ELSE
|
||||||
|
|
||||||
%code {
|
|
||||||
#include <stack>
|
|
||||||
|
|
||||||
static std::stack<StatementList*> stmtStack;
|
|
||||||
static std::stack<ExpressionList*> argsStack;
|
|
||||||
static std::stack<IdList*> paramsStack;
|
|
||||||
static std::stack<BranchCaseList*> branchCaseStack;
|
|
||||||
}
|
|
||||||
|
|
||||||
%union {
|
%union {
|
||||||
int intval;
|
int intval;
|
||||||
double floatval;
|
double floatval;
|
||||||
|
@ -94,39 +85,48 @@ static std::stack<BranchCaseList*> branchCaseStack;
|
||||||
Input* inputval;
|
Input* inputval;
|
||||||
Abort* abortval;
|
Abort* abortval;
|
||||||
Branch* branchval;
|
Branch* branchval;
|
||||||
|
Branch::Body* branchbodyval;
|
||||||
VarDeclaration* declval;
|
VarDeclaration* declval;
|
||||||
Assignment* assignval;
|
Assignment* assignval;
|
||||||
Loop* loopval;
|
Loop* loopval;
|
||||||
BranchCase *caseval;
|
BranchCase *caseval;
|
||||||
|
BranchCaseList *caselistval;
|
||||||
Return* returnval;
|
Return* returnval;
|
||||||
Expression* expressionval;
|
Expression* expressionval;
|
||||||
|
ExpressionList* exprlistval;
|
||||||
SemiExpression *semiexpval;
|
SemiExpression *semiexpval;
|
||||||
Id* idval;
|
Id* idval;
|
||||||
Number* numericval;
|
Number* numericval;
|
||||||
Function* funval;
|
Function* funval;
|
||||||
|
FunArg *argval;
|
||||||
|
FunArgList *arglistval;
|
||||||
Main* mainval;
|
Main* mainval;
|
||||||
}
|
}
|
||||||
|
|
||||||
%type<intval> NUMBER
|
%type<intval> NUMBER
|
||||||
%type<floatval> FLOAT
|
%type<floatval> FLOAT
|
||||||
%type<strval> ID
|
%type<strval> ID
|
||||||
%type<typeval> TYPENAME
|
%type<typeval> TYPENAME fun_return
|
||||||
|
|
||||||
%type<statementval> statement
|
%type<statementval> statement
|
||||||
%type<statlistval> branch_body
|
%type<statlistval> statements
|
||||||
|
%type<branchbodyval> branch_body
|
||||||
%type<assertval> assert_stmt
|
%type<assertval> assert_stmt
|
||||||
%type<callval> fun_call
|
%type<callval> fun_call
|
||||||
|
%type<argval> arg_decl
|
||||||
|
%type<arglistval> args_decl args
|
||||||
%type<funval> fun_decl
|
%type<funval> fun_decl
|
||||||
%type<printval> print_stmt
|
%type<printval> print_stmt
|
||||||
%type<inputval> input_stmt
|
%type<inputval> input_stmt
|
||||||
%type<abortval> abort_stmt
|
%type<abortval> abort_stmt
|
||||||
%type<branchval> branch_stmt
|
%type<branchval> branch_stmt
|
||||||
%type<caseval> case_stmt
|
%type<caseval> case_stmt
|
||||||
|
%type<caselistval> cases
|
||||||
%type<declval> var_decl
|
%type<declval> var_decl
|
||||||
%type<assignval> assign_stmt
|
%type<assignval> assign_stmt
|
||||||
%type<loopval> loop_stmt
|
%type<loopval> loop_stmt
|
||||||
%type<returnval> return_stmt
|
%type<returnval> return_stmt
|
||||||
%type<expressionval> expression maybe_expression simple_expression var_init
|
%type<expressionval> expression maybe_expression simple_expression var_init
|
||||||
|
%type<exprlistval> call_arglist call_args
|
||||||
%type<semiexpval> semi_expression
|
%type<semiexpval> semi_expression
|
||||||
%type<idval> variable
|
%type<idval> variable
|
||||||
%type<numericval> numeric
|
%type<numericval> numeric
|
||||||
|
@ -151,47 +151,45 @@ fun_decls:
|
||||||
fun_decls
|
fun_decls
|
||||||
;
|
;
|
||||||
fun_decl:
|
fun_decl:
|
||||||
FUNDECL ID {
|
FUN_DECL fun_return ID args FUN_END statements {
|
||||||
paramsStack.push(new IdList());
|
$$ = new Function(new Id($3), $2, $4, $6);
|
||||||
} args FUN_END {
|
|
||||||
stmtStack.push(new StatementList());
|
|
||||||
}
|
|
||||||
statements {
|
|
||||||
$$ = new Function(new Id($2), paramsStack.top(), stmtStack.top());
|
|
||||||
paramsStack.pop();
|
|
||||||
stmtStack.pop();
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
fun_return:
|
||||||
|
/* epsilon */ { $$ = Type::VOID; } | TYPENAME { $$ = $1; }
|
||||||
|
;
|
||||||
args:
|
args:
|
||||||
/* epsilon */ | PARAMS arglist
|
/* epsilon */ { $$ = new FunArgList(); }| PARAMS args_decl { $$ = $2; }
|
||||||
;
|
;
|
||||||
arglist:
|
args_decl:
|
||||||
variable {
|
arg_decl {
|
||||||
paramsStack.top()->push_back($1);
|
$$ = new FunArgList();
|
||||||
|
$$->push_back($1);
|
||||||
}
|
}
|
||||||
| variable {
|
| args_decl COMMA arg_decl {
|
||||||
paramsStack.top()->push_back($1);
|
$1->push_back($3);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
arg_decl:
|
||||||
|
variable pointer TYPENAME {
|
||||||
|
$$ = new FunArg($1, $3, $2);
|
||||||
}
|
}
|
||||||
arglist
|
|
||||||
;
|
;
|
||||||
main:
|
main:
|
||||||
MAIN {
|
MAIN statements {
|
||||||
stmtStack.push(new StatementList());
|
$$ = new Main($2);
|
||||||
}
|
|
||||||
statements {
|
|
||||||
$$ = new Main(stmtStack.top());
|
|
||||||
stmtStack.pop();
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
statements:
|
statements:
|
||||||
/* epsilon */ {
|
/* epsilon */ {
|
||||||
|
$$ = new StatementList();
|
||||||
}
|
}
|
||||||
| statement {
|
| statements statement {
|
||||||
if ($1 != nullptr) {
|
if ($2 != nullptr) {
|
||||||
stmtStack.top()->push_back($1);
|
$1->push_back($2);
|
||||||
}
|
}
|
||||||
|
$$ = $1;
|
||||||
}
|
}
|
||||||
statements
|
|
||||||
;
|
;
|
||||||
statement:
|
statement:
|
||||||
assert_stmt { $$ = $1; }
|
assert_stmt { $$ = $1; }
|
||||||
|
@ -252,61 +250,59 @@ maybe_expression:
|
||||||
expression { $$ = $1; } | /* epsilon */ { $$ = nullptr; }
|
expression { $$ = $1; } | /* epsilon */ { $$ = nullptr; }
|
||||||
;
|
;
|
||||||
loop_stmt:
|
loop_stmt:
|
||||||
LOOP_BEGIN {
|
LOOP_BEGIN statements LOOP_CONDITION expression {
|
||||||
stmtStack.push(new StatementList());
|
$$ = new Loop($2, $4);
|
||||||
}
|
|
||||||
statements LOOP_CONDITION expression {
|
|
||||||
$$ = new Loop(stmtStack.top(), $5);
|
|
||||||
stmtStack.pop();
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
branch_stmt:
|
branch_stmt:
|
||||||
BRANCH_CONDITION variable BRANCH_BEGIN {
|
BRANCH_CONDITION variable BRANCH_BEGIN branch_body BRANCH_END {
|
||||||
branchCaseStack.push(new BranchCaseList());
|
$$ = new Branch($2, $4);
|
||||||
}
|
|
||||||
branch_body BRANCH_END {
|
|
||||||
$$ = new Branch($2, branchCaseStack.top(), $5);
|
|
||||||
branchCaseStack.pop();
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
branch_body:
|
branch_body:
|
||||||
cases %prec LOWER_THAN_ELSE {
|
cases %prec LOWER_THAN_ELSE {
|
||||||
$$ = nullptr;
|
$$ = new Branch::Body($1);
|
||||||
}
|
}
|
||||||
| cases BRANCH_ELSE COLON {
|
| cases BRANCH_ELSE COLON statements {
|
||||||
stmtStack.push(new StatementList());
|
$$ = new Branch::Body($1, $4);
|
||||||
}
|
|
||||||
statements {
|
|
||||||
$$ = stmtStack.top();
|
|
||||||
stmtStack.pop();
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
cases:
|
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:
|
case_stmt:
|
||||||
semi_expression COLON {
|
semi_expression COLON statements {
|
||||||
stmtStack.push(new StatementList());
|
$$ = new BranchCase($1, $3);
|
||||||
} statements {
|
|
||||||
branchCaseStack.top()->push_back(new BranchCase($1, stmtStack.top()));
|
|
||||||
stmtStack.pop();
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
fun_call:
|
fun_call:
|
||||||
FUNCALL {
|
FUN_CALL ID call_args FUN_END {
|
||||||
argsStack.push(new ExpressionList());
|
$$ = new FunctionCall(new Id($2), $3);
|
||||||
}
|
|
||||||
ID call_args FUN_END {
|
|
||||||
$$ = new FunctionCall(new Id($3), argsStack.top());
|
|
||||||
argsStack.pop();
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
call_args:
|
call_args:
|
||||||
/* epsilon */ | PARAMS call_arglist
|
/* epsilon */ {
|
||||||
|
$$ = new ExpressionList();
|
||||||
|
}
|
||||||
|
| PARAMS call_arglist {
|
||||||
|
$$ = $2;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
call_arglist:
|
call_arglist:
|
||||||
expression { argsStack.top()->push_back($1); }
|
expression {
|
||||||
| expression { argsStack.top()->push_back($1); } COMMA call_arglist
|
$$ = new ExpressionList();
|
||||||
|
$$->push_back($1);
|
||||||
|
}
|
||||||
|
| call_arglist COMMA expression {
|
||||||
|
$$->push_back($3);
|
||||||
|
}
|
||||||
;
|
;
|
||||||
abort_stmt:
|
abort_stmt:
|
||||||
ABORT {
|
ABORT {
|
||||||
|
@ -400,6 +396,7 @@ simple_expression:
|
||||||
void Parser::error(const location_type& loc, const std::string &message) {
|
void Parser::error(const location_type& loc, const std::string &message) {
|
||||||
std::cerr << "line " << loc.begin.line << ", col " << loc.begin.column;
|
std::cerr << "line " << loc.begin.line << ", col " << loc.begin.column;
|
||||||
std::cerr << ": " << message << std::endl;
|
std::cerr << ": " << message << std::endl;
|
||||||
|
std::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int yylex(Parser::semantic_type *lval, Parser::location_type *loc, Scanner &scanner) {
|
int yylex(Parser::semantic_type *lval, Parser::location_type *loc, Scanner &scanner) {
|
||||||
|
|
48
Nodes.cpp
48
Nodes.cpp
|
@ -40,6 +40,9 @@ std::ostream& monicelli::operator<<(std::ostream &stream, const Type &type) {
|
||||||
case Type::DOUBLE:
|
case Type::DOUBLE:
|
||||||
stream << "double";
|
stream << "double";
|
||||||
break;
|
break;
|
||||||
|
case Type::VOID:
|
||||||
|
stream << "void";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return stream;
|
return stream;
|
||||||
|
@ -119,9 +122,9 @@ void Branch::emit(std::ostream &stream, int indent) {
|
||||||
stream << "if (";
|
stream << "if (";
|
||||||
var->emit(stream);
|
var->emit(stream);
|
||||||
|
|
||||||
if (cases->size() > 0) {
|
if (body->cases->size() > 0) {
|
||||||
BranchCase *last = cases->back();
|
BranchCase *last = body->cases->back();
|
||||||
for (BranchCase *c: *cases) {
|
for (BranchCase *c: *body->cases) {
|
||||||
c->emit(stream, indent + 1);
|
c->emit(stream, indent + 1);
|
||||||
if (c != last) {
|
if (c != last) {
|
||||||
stream << " else if (";
|
stream << " else if (";
|
||||||
|
@ -130,12 +133,12 @@ void Branch::emit(std::ostream &stream, int indent) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (els == nullptr) {
|
if (body->els == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream << " else {\n";
|
stream << " else {\n";
|
||||||
els->emit(stream, indent + 1);
|
body->els->emit(stream, indent + 1);
|
||||||
emitIndent(stream, indent);
|
emitIndent(stream, indent);
|
||||||
stream << "}";
|
stream << "}";
|
||||||
}
|
}
|
||||||
|
@ -158,12 +161,16 @@ void Assignment::emit(std::ostream &stream, int indent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Print::emit(std::ostream &stream, int indent) {
|
void Print::emit(std::ostream &stream, int indent) {
|
||||||
stream << "std::cout << ";
|
stream << "std::cout << (";
|
||||||
expression->emit(stream);
|
expression->emit(stream);
|
||||||
stream << " << std::endl";
|
stream << ") << std::endl";
|
||||||
}
|
}
|
||||||
|
|
||||||
void Input::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 >> ";
|
stream << "std::cin >> ";
|
||||||
variable->emit(stream);
|
variable->emit(stream);
|
||||||
}
|
}
|
||||||
|
@ -185,16 +192,26 @@ void FunctionCall::emit(std::ostream &stream, int indent) {
|
||||||
stream << ")";
|
stream << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FunArg::emit(std::ostream &stream, int indent) {
|
||||||
|
stream << type << (pointer? "* ": " ");
|
||||||
|
name->emit(stream);
|
||||||
|
}
|
||||||
|
|
||||||
void Function::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);
|
emitIndent(stream, indent);
|
||||||
|
|
||||||
stream << "void ";
|
stream << type << ' ';
|
||||||
name->emit(stream);
|
name->emit(stream);
|
||||||
stream << "(";
|
stream << "(";
|
||||||
args->emit(stream);
|
args->emit(stream);
|
||||||
stream << ") {\n";
|
stream << ")";
|
||||||
body->emit(stream, indent + 1);
|
|
||||||
stream << "}\n\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Main::emit(std::ostream &stream, int indent) {
|
void Main::emit(std::ostream &stream, int indent) {
|
||||||
|
@ -209,6 +226,15 @@ void Program::emit(std::ostream &stream, int indent) {
|
||||||
stream << "#include <iostream>\n";
|
stream << "#include <iostream>\n";
|
||||||
stream << "#include <cstdlib>\n\n";
|
stream << "#include <cstdlib>\n\n";
|
||||||
|
|
||||||
|
for (Function *f: functions) {
|
||||||
|
f->emitSignature(stream);
|
||||||
|
stream << ";\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!functions.empty()) {
|
||||||
|
stream << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
for (Function *f: functions) {
|
for (Function *f: functions) {
|
||||||
f->emit(stream);
|
f->emit(stream);
|
||||||
}
|
}
|
||||||
|
|
55
Nodes.hpp
55
Nodes.hpp
|
@ -31,14 +31,18 @@ enum class Type {
|
||||||
CHAR,
|
CHAR,
|
||||||
FLOAT,
|
FLOAT,
|
||||||
BOOL,
|
BOOL,
|
||||||
DOUBLE
|
DOUBLE,
|
||||||
|
VOID
|
||||||
};
|
};
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream &stream, const Type &type);
|
std::ostream& operator<<(std::ostream &stream, const Type &type);
|
||||||
|
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
using Pointer = std::unique_ptr<T>;
|
class Pointer: public std::unique_ptr<T> {
|
||||||
|
public:
|
||||||
|
Pointer(T *p = nullptr): std::unique_ptr<T>(p) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class Emittable {
|
class Emittable {
|
||||||
|
@ -264,14 +268,23 @@ typedef PointerList<BranchCase> BranchCaseList;
|
||||||
|
|
||||||
class Branch: public Statement {
|
class Branch: public Statement {
|
||||||
public:
|
public:
|
||||||
Branch(Id *v, BranchCaseList *c, StatementList *e):
|
struct Body {
|
||||||
var(v), cases(c), els(e) {}
|
public:
|
||||||
|
Body(BranchCaseList *c, StatementList *e = nullptr): cases(c), els(e) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Pointer<BranchCaseList> cases;
|
||||||
|
Pointer<StatementList> els;
|
||||||
|
|
||||||
|
friend class Branch;
|
||||||
|
};
|
||||||
|
|
||||||
|
Branch(Id *v, Branch::Body *b): var(v), body(b) {}
|
||||||
virtual void emit(std::ostream &stream, int indent = 0);
|
virtual void emit(std::ostream &stream, int indent = 0);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Pointer<Id> var;
|
Pointer<Id> var;
|
||||||
Pointer<BranchCaseList> cases;
|
Pointer<Branch::Body> body;
|
||||||
Pointer<StatementList> els;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -285,20 +298,40 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Function: public Emittable {
|
class FunArg: public Emittable {
|
||||||
public:
|
public:
|
||||||
Function(Id *n, IdList *a, StatementList *b):
|
FunArg(Id *n, Type t, bool p): name(n), type(t), pointer(p) {}
|
||||||
name(n), args(a), body(b) {}
|
virtual ~FunArg() {}
|
||||||
virtual ~Function() {}
|
|
||||||
|
|
||||||
virtual void emit(std::ostream &stream, int indent = 0);
|
virtual void emit(std::ostream &stream, int indent = 0);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Pointer<Id> name;
|
Pointer<Id> name;
|
||||||
Pointer<IdList> args;
|
Type type;
|
||||||
|
bool pointer;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef ListEmittable<FunArg> FunArgList;
|
||||||
|
|
||||||
|
|
||||||
|
class Function: public Emittable {
|
||||||
|
public:
|
||||||
|
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);
|
||||||
|
void emitSignature(std::ostream &stream, int indent = 0);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Pointer<Id> name;
|
||||||
|
Type type;
|
||||||
|
Pointer<FunArgList> args;
|
||||||
Pointer<StatementList> body;
|
Pointer<StatementList> body;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Program: public Emittable {
|
class Program: public Emittable {
|
||||||
public:
|
public:
|
||||||
virtual void emit(std::ostream &stream, int indent = 0);
|
virtual void emit(std::ostream &stream, int indent = 0);
|
||||||
|
|
84
README.md
84
README.md
|
@ -34,7 +34,7 @@ Usage
|
||||||
subset of C++. For those of you who want to get to the code ASAP, the `examples/`
|
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.
|
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`.
|
input. Well, mostly with the beautified version of the input, `*.beauty.mc`.
|
||||||
|
|
||||||
The compiler reads from standard input and print result to standard output.
|
The compiler reads from standard input and print result to standard output.
|
||||||
|
@ -46,10 +46,14 @@ The compiler reads from standard input and print result to standard output.
|
||||||
Language overview
|
Language overview
|
||||||
=================
|
=================
|
||||||
|
|
||||||
The original specification can be found in `Specification.txt`, which
|
The original specification can be found in `Specification.txt`, and was
|
||||||
unfortunately is not complete. This project is an ongoing effort to implement
|
initially conceived by my colleagues and dear friends Alessandro Barenghi,
|
||||||
it, which means filling gaps and ambiguities. This file only documents
|
Michele Tartara and Nicola Vitucci, to whom goes my gratitude.
|
||||||
usable features of the language.
|
|
||||||
|
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
|
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
|
statement can be split across multiple lines and multiple statements can be
|
||||||
|
@ -58,6 +62,10 @@ words **cannot** be split on multiple lines.
|
||||||
|
|
||||||
A comma might be inserted after each statement, if it fits the sentence ;)
|
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
|
Main
|
||||||
----
|
----
|
||||||
|
|
||||||
|
@ -194,7 +202,7 @@ defined as follows:
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
voglio antani, Necchi come se fosse 10
|
voglio antani, Necchi come se fosse 10
|
||||||
stuzzica:
|
stuzzica
|
||||||
antani come fosse antani meno 1
|
antani come fosse antani meno 1
|
||||||
e brematura anche, se antani maggiore di 0
|
e brematura anche, se antani maggiore di 0
|
||||||
|
|
||||||
|
@ -285,10 +293,62 @@ where the `o tarapia tapioco` part is like the `default` block.
|
||||||
Functions
|
Functions
|
||||||
---------
|
---------
|
||||||
|
|
||||||
_Coming in a few releases..._.
|
**Note**: the alternate spelling `supercazzora` might be used in place
|
||||||
|
of `supercazzola` wherever the latter appears.
|
||||||
|
|
||||||
We can already parse and emit them, although there are some ambiguities
|
###Declaration
|
||||||
yet to be solved in the specification.
|
|
||||||
|
A function is declared with the `blinda la supercazzola` statement:
|
||||||
|
|
||||||
|
blinda la supercazzola [<type>] <name> [con <param> <type>[, <param> <type>...]] o scherziamo?
|
||||||
|
<statements>
|
||||||
|
|
||||||
|
Where `<type>` 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!
|
||||||
|
|
||||||
|
is a `void` function taking no arguments and becomes:
|
||||||
|
|
||||||
|
void antanizzata() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 <name> [con <expression>[, <expression>...] 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
|
Exceptions
|
||||||
----------
|
----------
|
||||||
|
@ -311,9 +371,11 @@ Comments
|
||||||
--------
|
--------
|
||||||
|
|
||||||
Any character after `bituma` is ignored until a line break is encountered. For
|
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
|
Comments are useful to fill the "supercazzola" and make it more readable, since
|
||||||
any word (including reserved words) can be inserted into it.
|
any word (including reserved words) can be inserted into it.
|
||||||
|
|
|
@ -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"
|
Proposte per la definizione di un linguaggio di programmazione esoterico "Monicelli"
|
||||||
|
|
||||||
Il "main" del programma inizia in corrispondenza di:
|
Il "main" del programma inizia in corrispondenza di:
|
||||||
|
|
12
examples/float.mc
Normal file
12
examples/float.mc
Normal file
|
@ -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
|
16
examples/hello-world.mc
Normal file
16
examples/hello-world.mc
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
# Author: Alessandro Pellegrini <alessandro@pellegrini.tk>
|
||||||
|
# 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!
|
|
@ -40,7 +40,7 @@ Lei ha clacsonato
|
||||||
vicesindaco come se fosse brematurata la supercazzola avanti con il vicesindaco o scherziamo,
|
vicesindaco come se fosse brematurata la supercazzola avanti con il vicesindaco o scherziamo,
|
||||||
vaffanzum 0!
|
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!
|
vaffanzum alfio meno 2!
|
||||||
|
|
||||||
bituma al finale?
|
bituma al finale?
|
||||||
|
|
|
@ -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
|
vicesindaco a posterdati, mi porga il vicesindaco, brematurata la supercazzola
|
||||||
tombale con alfio, serio o scherziamo? avvertite don ulrico, ho visto la signora!
|
tombale con alfio, serio o scherziamo? avvertite don ulrico, ho visto la signora!
|
||||||
vicesindaco come se fosse brematurata la supercazzola avanti con il vicesindaco
|
vicesindaco come se fosse brematurata la supercazzola avanti con il vicesindaco
|
||||||
o scherziamo, vaffanzum 0! blinda la supercazzola antanizzata con alfio o scherziamo?
|
o scherziamo, vaffanzum 0! blinda la supercazzola Necchi antanizzata con alfio
|
||||||
vaffanzum alfio meno 2! bituma al finale?
|
Mascetti o scherziamo? vaffanzum alfio meno 2! bituma al finale?
|
||||||
|
|
Reference in New Issue
Block a user