2012-08-16 01:00:30 +01:00
|
|
|
%{
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "compile.h"
|
|
|
|
%}
|
|
|
|
|
|
|
|
%locations
|
|
|
|
%define api.pure
|
|
|
|
%union {
|
2012-09-02 16:31:59 +01:00
|
|
|
jv literal;
|
2012-08-16 01:00:30 +01:00
|
|
|
block blk;
|
|
|
|
}
|
|
|
|
|
|
|
|
%parse-param {block* answer}
|
|
|
|
%parse-param {yyscan_t lexer}
|
|
|
|
%lex-param {yyscan_t lexer}
|
|
|
|
|
|
|
|
|
2012-09-02 16:31:59 +01:00
|
|
|
%token <literal> IDENT
|
|
|
|
%token <literal> LITERAL
|
2012-08-16 01:00:30 +01:00
|
|
|
|
2012-08-21 18:14:13 +01:00
|
|
|
/* revolting hack */
|
|
|
|
%left ';'
|
|
|
|
|
2012-08-16 01:00:30 +01:00
|
|
|
%left '|'
|
|
|
|
%left ','
|
|
|
|
%token EQ "=="
|
2012-09-04 15:34:34 +01:00
|
|
|
%token DEFINEDOR "//"
|
2012-08-16 01:00:30 +01:00
|
|
|
%token AS "as"
|
2012-08-21 18:14:13 +01:00
|
|
|
%token DEF "def"
|
2012-08-27 10:11:55 +01:00
|
|
|
%token SETPIPE "|="
|
2012-09-04 15:34:34 +01:00
|
|
|
%token IF "if"
|
|
|
|
%token THEN "then"
|
|
|
|
%token ELSE "else"
|
2012-09-04 16:05:24 +01:00
|
|
|
%token ELSE_IF "elif"
|
2012-09-04 15:34:34 +01:00
|
|
|
%token END "end"
|
2012-09-04 20:38:59 +01:00
|
|
|
%token AND "and"
|
|
|
|
%token OR "or"
|
2012-09-04 20:43:40 +01:00
|
|
|
%token NOT "not"
|
2012-09-04 15:34:34 +01:00
|
|
|
%right "//"
|
2012-08-27 10:11:55 +01:00
|
|
|
%nonassoc '=' SETPIPE
|
2012-08-16 01:00:30 +01:00
|
|
|
%nonassoc EQ
|
2012-09-04 20:38:59 +01:00
|
|
|
%left OR
|
|
|
|
%left AND
|
2012-08-16 01:00:30 +01:00
|
|
|
%left '+'
|
|
|
|
|
2012-09-04 15:34:34 +01:00
|
|
|
|
2012-09-04 16:05:24 +01:00
|
|
|
%type <blk> Exp Term MkDict MkDictPair ExpD ElseBody
|
2012-08-16 01:00:30 +01:00
|
|
|
|
|
|
|
%{
|
|
|
|
#include "lexer.yy.h"
|
|
|
|
void yyerror(YYLTYPE* loc, block* answer, yyscan_t lexer, const char *s){
|
|
|
|
printf("ERROR: %s\n", s);
|
|
|
|
}
|
|
|
|
|
|
|
|
static block gen_dictpair(block k, block v) {
|
|
|
|
block b = gen_subexp(k);
|
|
|
|
block_append(&b, gen_subexp(v));
|
|
|
|
block_append(&b, gen_op_simple(INSERT));
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
|
|
|
static block gen_index(block obj, block key) {
|
|
|
|
return block_join(obj, block_join(gen_subexp(key), gen_op_simple(INDEX)));
|
|
|
|
}
|
|
|
|
|
|
|
|
%}
|
|
|
|
|
|
|
|
%%
|
|
|
|
program: Exp { *answer = $1; }
|
|
|
|
|
|
|
|
Exp:
|
2012-08-21 18:14:13 +01:00
|
|
|
"def" IDENT ':' Exp ';' Exp {
|
|
|
|
block body = block_join($4, gen_op_simple(RET));
|
2012-09-02 16:31:59 +01:00
|
|
|
$$ = block_bind(gen_op_block_defn(CLOSURE_CREATE, jv_string_value($2), body),
|
|
|
|
$6, OP_IS_CALL_PSEUDO);
|
|
|
|
jv_free($2);
|
2012-08-21 18:14:13 +01:00
|
|
|
} |
|
|
|
|
|
2012-08-26 14:25:56 +01:00
|
|
|
"def" IDENT '(' IDENT ')' ':' Exp ';' Exp {
|
2012-09-02 16:31:59 +01:00
|
|
|
block body = block_bind(gen_op_block_unbound(CLOSURE_PARAM, jv_string_value($4)), block_join($7, gen_op_simple(RET)), OP_IS_CALL_PSEUDO);
|
|
|
|
$$ = block_bind(gen_op_block_defn(CLOSURE_CREATE, jv_string_value($2), body), $9, OP_IS_CALL_PSEUDO);
|
|
|
|
jv_free($2);
|
|
|
|
jv_free($4);
|
2012-08-26 14:25:56 +01:00
|
|
|
} |
|
|
|
|
|
2012-08-16 01:00:30 +01:00
|
|
|
Term "as" '$' IDENT '|' Exp {
|
|
|
|
$$ = gen_op_simple(DUP);
|
|
|
|
block_append(&$$, $1);
|
2012-09-02 16:31:59 +01:00
|
|
|
block_append(&$$, block_bind(gen_op_var_unbound(STOREV, jv_string_value($4)), $6, OP_HAS_VARIABLE));
|
|
|
|
jv_free($4);
|
2012-08-16 01:00:30 +01:00
|
|
|
} |
|
|
|
|
|
2012-09-04 16:05:24 +01:00
|
|
|
"if" Exp "then" Exp ElseBody {
|
|
|
|
$$ = gen_cond($2, $4, $5);
|
2012-09-04 15:34:34 +01:00
|
|
|
} |
|
|
|
|
|
2012-08-27 10:11:55 +01:00
|
|
|
Exp '=' Exp {
|
|
|
|
block assign = gen_op_simple(DUP);
|
|
|
|
block_append(&assign, $3);
|
|
|
|
block_append(&assign, gen_op_simple(SWAP));
|
|
|
|
block_append(&assign, $1);
|
|
|
|
block_append(&assign, gen_op_simple(SWAP));
|
|
|
|
$$ = gen_assign(assign);
|
|
|
|
} |
|
|
|
|
|
2012-09-04 20:38:59 +01:00
|
|
|
Exp "or" Exp {
|
|
|
|
$$ = gen_or($1, $3);
|
|
|
|
} |
|
|
|
|
|
|
|
|
Exp "and" Exp {
|
|
|
|
$$ = gen_and($1, $3);
|
|
|
|
} |
|
|
|
|
|
2012-09-04 20:43:40 +01:00
|
|
|
"not" Exp {
|
|
|
|
$$ = gen_not($2);
|
|
|
|
} |
|
|
|
|
|
2012-09-04 15:34:34 +01:00
|
|
|
Exp "//" Exp {
|
|
|
|
$$ = gen_definedor($1, $3);
|
|
|
|
} |
|
|
|
|
|
2012-08-27 10:11:55 +01:00
|
|
|
Exp "|=" Exp {
|
|
|
|
block assign = $1;
|
|
|
|
block_append(&assign, gen_op_simple(DUP));
|
|
|
|
block_append(&assign, $3);
|
|
|
|
$$ = gen_assign(assign);
|
|
|
|
} |
|
|
|
|
|
2012-08-16 01:00:30 +01:00
|
|
|
Exp '|' Exp {
|
|
|
|
$$ = block_join($1, $3);
|
|
|
|
} |
|
|
|
|
|
|
|
|
Exp ',' Exp {
|
|
|
|
$$ = gen_both($1, $3);
|
|
|
|
} |
|
|
|
|
|
2012-08-16 01:16:08 +01:00
|
|
|
Exp '+' Exp {
|
|
|
|
$$ = gen_noop();
|
|
|
|
block_append(&$$, gen_subexp($1));
|
|
|
|
block_append(&$$, gen_subexp($3));
|
2012-08-27 11:19:42 +01:00
|
|
|
block_append(&$$, gen_op_call(CALL_1_1, gen_op_block_unbound(CLOSURE_REF, "_plus")));
|
2012-08-16 01:16:08 +01:00
|
|
|
} |
|
|
|
|
|
2012-08-16 01:00:30 +01:00
|
|
|
Term {
|
|
|
|
$$ = $1;
|
|
|
|
}
|
|
|
|
|
2012-09-04 16:05:24 +01:00
|
|
|
ElseBody:
|
|
|
|
"elif" Exp "then" Exp ElseBody {
|
|
|
|
$$ = gen_cond($2, $4, $5);
|
|
|
|
} |
|
|
|
|
"else" Exp "end" {
|
|
|
|
$$ = $2;
|
|
|
|
}
|
|
|
|
|
2012-08-16 01:00:30 +01:00
|
|
|
|
|
|
|
ExpD:
|
|
|
|
ExpD '|' ExpD {
|
|
|
|
$$ = block_join($1, $3);
|
|
|
|
} |
|
|
|
|
|
|
|
|
Term {
|
|
|
|
$$ = $1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Term:
|
|
|
|
'.' {
|
|
|
|
$$ = gen_noop();
|
|
|
|
} |
|
|
|
|
Term '.' IDENT {
|
2012-09-02 16:31:59 +01:00
|
|
|
$$ = gen_index($1, gen_op_const(LOADK, $3));
|
2012-08-16 01:00:30 +01:00
|
|
|
} |
|
|
|
|
'.' IDENT {
|
2012-09-02 16:31:59 +01:00
|
|
|
$$ = gen_index(gen_noop(), gen_op_const(LOADK, $2));
|
2012-08-16 01:00:30 +01:00
|
|
|
} |
|
|
|
|
/* FIXME: string literals */
|
|
|
|
Term '[' Exp ']' {
|
|
|
|
$$ = gen_index($1, $3);
|
|
|
|
} |
|
|
|
|
Term '[' ']' {
|
|
|
|
$$ = block_join($1, gen_op_simple(EACH));
|
|
|
|
} |
|
2012-09-02 16:31:59 +01:00
|
|
|
LITERAL {
|
|
|
|
$$ = gen_op_const(LOADK, $1);
|
2012-08-16 01:00:30 +01:00
|
|
|
} |
|
|
|
|
'(' Exp ')' {
|
|
|
|
$$ = $2;
|
|
|
|
} |
|
|
|
|
'[' Exp ']' {
|
|
|
|
$$ = gen_collect($2);
|
|
|
|
} |
|
|
|
|
'[' ']' {
|
2012-09-02 16:31:59 +01:00
|
|
|
$$ = gen_op_const(LOADK, jv_array());
|
2012-08-16 01:00:30 +01:00
|
|
|
} |
|
|
|
|
'{' MkDict '}' {
|
2012-09-02 16:31:59 +01:00
|
|
|
$$ = gen_subexp(gen_op_const(LOADK, jv_object()));
|
2012-08-16 01:00:30 +01:00
|
|
|
block_append(&$$, $2);
|
|
|
|
block_append(&$$, gen_op_simple(POP));
|
|
|
|
} |
|
|
|
|
'$' IDENT {
|
2012-09-02 16:31:59 +01:00
|
|
|
$$ = gen_op_var_unbound(LOADV, jv_string_value($2));
|
|
|
|
jv_free($2);
|
2012-08-21 18:14:13 +01:00
|
|
|
} |
|
2012-08-27 11:19:42 +01:00
|
|
|
IDENT {
|
2012-09-02 16:31:59 +01:00
|
|
|
$$ = gen_op_call(CALL_1_1, gen_op_block_unbound(CLOSURE_REF, jv_string_value($1)));
|
|
|
|
jv_free($1);
|
2012-08-26 14:25:56 +01:00
|
|
|
} |
|
2012-08-27 11:19:42 +01:00
|
|
|
IDENT '(' Exp ')' {
|
2012-08-26 14:25:56 +01:00
|
|
|
$$ = gen_op_call(CALL_1_1,
|
2012-09-02 16:31:59 +01:00
|
|
|
block_join(gen_op_block_unbound(CLOSURE_REF, jv_string_value($1)),
|
2012-08-26 14:25:56 +01:00
|
|
|
block_bind(gen_op_block_defn(CLOSURE_CREATE,
|
|
|
|
"lambda",
|
2012-08-27 11:19:42 +01:00
|
|
|
block_join($3, gen_op_simple(RET))),
|
2012-08-26 14:25:56 +01:00
|
|
|
gen_noop(), OP_IS_CALL_PSEUDO)));
|
2012-09-02 16:31:59 +01:00
|
|
|
jv_free($1);
|
2012-08-16 01:00:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
MkDict:
|
|
|
|
{
|
|
|
|
$$=gen_noop();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
MkDictPair
|
|
|
|
{ $$ = $1; }
|
|
|
|
| MkDictPair ',' MkDict { $$=block_join($1, $3); }
|
|
|
|
|
|
|
|
MkDictPair
|
|
|
|
: IDENT ':' ExpD {
|
2012-09-02 16:31:59 +01:00
|
|
|
$$ = gen_dictpair(gen_op_const(LOADK, $1), $3);
|
2012-08-16 01:00:30 +01:00
|
|
|
}
|
2012-09-03 13:36:12 +01:00
|
|
|
| LITERAL ':' ExpD {
|
|
|
|
assert(jv_get_kind($1) == JV_KIND_STRING);
|
|
|
|
$$ = gen_dictpair(gen_op_const(LOADK, $1), $3);
|
|
|
|
}
|
2012-08-16 01:00:30 +01:00
|
|
|
| IDENT {
|
2012-09-02 16:31:59 +01:00
|
|
|
$$ = gen_dictpair(gen_op_const(LOADK, jv_copy($1)),
|
|
|
|
gen_index(gen_noop(), gen_op_const(LOADK, $1)));
|
2012-08-16 01:00:30 +01:00
|
|
|
}
|
|
|
|
| '(' Exp ')' ':' ExpD {
|
|
|
|
$$ = gen_dictpair($2, $5);
|
|
|
|
}
|
|
|
|
%%
|
|
|
|
|
|
|
|
block compile(const char* str) {
|
|
|
|
yyscan_t scanner;
|
|
|
|
YY_BUFFER_STATE buf;
|
|
|
|
block answer = gen_noop();
|
|
|
|
yylex_init(&scanner);
|
|
|
|
buf = yy_scan_string(str, scanner);
|
|
|
|
yyparse(&answer, scanner);
|
|
|
|
yy_delete_buffer(buf, scanner);
|
|
|
|
yylex_destroy(scanner);
|
|
|
|
return answer;
|
|
|
|
}
|