Anarres-Mud-Driver
view release on metacpan or search on metacpan
Compiler/parser.y view on Meta::CPAN
#define Z3 Z2, NULL
#define Z4 Z3, NULL
#define Z5 Z4, NULL
#define Z6 Z5, NULL
#define N_A0(t) yyparse_node(t, Z6)
#define N_A1(t,a0) yyparse_node(t,a0, Z5)
#define N_A2(t,a0,a1) yyparse_node(t,a0,a1, Z4)
#define N_A3(t,a0,a1,a2) yyparse_node(t,a0,a1,a2, Z3)
#define N_A4(t,a0,a1,a2,a3) yyparse_node(t,a0,a1,a2,a3, Z2)
#define N_A5(t,a0,a1,a2,a3,a4) yyparse_node(t,a0,a1,a2,a3,a4,Z1)
#define N_A0R(t,r) yyparse_node(t, Z5,r)
#define N_A1R(t,a0,r) yyparse_node(t,a0, Z4,r)
#define N_A2R(t,a0,a1,r) yyparse_node(t,a0,a1, Z3,r)
#define N_A3R(t,a0,a1,a2,r) yyparse_node(t,a0,a1,a2, Z2,r)
#define N_A4R(t,a0,a1,a2,a3,r) yyparse_node(t,a0,a1,a2,a3,Z1,r)
#define N_A5R(t,a0,a1,a2,a3,a4,r) yyparse_node(t,a0,a1,a2,a3,a4,r)
static SV *
yyparse_node(char *type,
SV *arg0, SV *arg1, SV *arg2, SV *arg3, SV *arg4,
AV *rest)
{
dSP;
int count;
SV *node;
char buf[512];
SV *class;
SV **svp;
int len;
int i;
strcpy(buf, _AMD "::Compiler::Node::");
strcat(buf, type);
class = sv_2mortal(newSVpv(buf, 0));
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(class);
/* This unconventional formatting pushes the first few of argN
* which are not NULL. */
if (arg0) { XPUSHs(arg0);
if (arg1) { XPUSHs(arg1);
if (arg2) { XPUSHs(arg2);
if (arg3) { XPUSHs(arg3);
if (arg4) { XPUSHs(arg4);
} } } } }
if (rest) {
len = av_len(rest);
for (i = 0; i <= len; i++) {
svp = av_fetch(rest, i, FALSE);
if (svp)
XPUSHs(*svp);
}
}
PUTBACK;
count = call_method("new", G_SCALAR);
SPAGAIN;
if (count != 1)
croak("Didn't get a return value from constructing %s\n", type);
node = POPs;
PUTBACK;
SvREFCNT_inc(node);
FREETMPS;
LEAVE;
// sv_2mortal(node); /* This segfaults it at the moment. */
return node;
}
/* We have to make sure that 'type' coming into here is PV not RV */
static SV *
yyparse_type(const char *type, SV *stars)
{
static SV *class = NULL;
SV *sv;
dSP;
int count;
SV *node;
if (!class) {
class = newSVpv(_AMD "::Compiler::Type", 0);
}
// fprintf(stderr, "Type is %s, stars is %s\n", type, SvPV_nolen(stars));
/* XXX It's quite likely that we own the only ref to 'stars' here.
*/
sv = newSVsv(stars);
sv_catpv(sv, type);
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(class);
XPUSHs(sv); /* Does this get freed? */
PUTBACK;
count = call_method("new", G_SCALAR);
SPAGAIN;
if (count != 1)
croak("Didn't get a return value from constructing Type\n");
node = POPs;
PUTBACK;
SvREFCNT_inc(node);
FREETMPS;
LEAVE;
/* In the outer scope. Let's hope this doesn't get dested. */
sv_2mortal(node);
return node;
#if 0
return sv_bless(newRV_noinc(stars),
gv_stashpv(_AMD "::Compiler::Type", TRUE));
#endif
}
/* Can I pass mods as a primitive integer, and not bother if they
* are zero? This applies to functions as well. */
static SV *
yyparse_variable(SV *name, const char *type, SV *stars, SV *mods)
{
static SV *class = NULL;
static SV *k_type = NULL;
static SV *k_name = NULL;
static SV *k_flags = NULL;
SV *newtype;
dSP;
int count;
SV *node;
if (!class) {
class = newSVpv(_AMD "::Program::Variable", 0);
k_type = newSVpv("Type", 0);
k_name = newSVpv("Name", 0);
k_flags = newSVpv("Flags", 0);
}
newtype = yyparse_type(type, stars);
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(class);
XPUSHs(k_type);
XPUSHs(newtype);
XPUSHs(k_name);
XPUSHs(name);
XPUSHs(k_flags);
XPUSHs(mods);
PUTBACK;
count = call_method("new", G_SCALAR);
SPAGAIN;
if (count != 1)
croak("Didn't get a return value from constructing Variable\n");
node = POPs;
PUTBACK;
SvREFCNT_inc(node);
FREETMPS;
LEAVE;
return node;
}
static SV *
yyparse_method(SV *name, const char *type, SV *stars,
SV *args, SV *mods)
{
static SV *class = NULL;
static SV *k_type = NULL;
static SV *k_name = NULL;
static SV *k_args = NULL;
static SV *k_flags = NULL;
SV *newtype;
dSP;
int count;
SV *node;
if (!class) {
class = newSVpv(_AMD "::Program::Method", 0);
k_type = newSVpv("Type", 0);
k_name = newSVpv("Name", 0);
k_args = newSVpv("Args", 0);
k_flags = newSVpv("Flags", 0);
}
newtype = yyparse_type(type, stars);
// printf("Start of yyparse_method\n");
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(class);
XPUSHs(k_type);
XPUSHs(newtype);
XPUSHs(k_name);
XPUSHs(name);
XPUSHs(k_args);
XPUSHs(args);
XPUSHs(k_flags);
XPUSHs(mods);
PUTBACK;
count = call_method("new", G_SCALAR);
SPAGAIN;
if (count != 1)
croak("Didn't get a return value from constructing Method\n");
node = POPs;
PUTBACK;
SvREFCNT_inc(node);
FREETMPS;
LEAVE;
// printf("End of yyparse_method\n");
return node;
}
static void
yyparse_method_add_code(SV *method, SV *code)
{
dSP;
int count;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(method);
XPUSHs(code);
PUTBACK;
count = call_method("code", G_DISCARD);
SPAGAIN;
if (count != 0)
croak("Got a return value from method->code()\n");
PUTBACK;
FREETMPS;
LEAVE;
}
static SV *
yyparse_program_apply(amd_parse_param_t *param,
const char *func, SV *arg0, SV *arg1)
{
dSP;
int count;
SV *node;
// printf("Apply %s\n", func);
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(param->program);
if (arg0) XPUSHs(arg0);
if (arg1) XPUSHs(arg1);
PUTBACK;
count = call_method(func, G_SCALAR);
SPAGAIN;
if (count != 1)
croak("No returned value from apply %s\n", func);
node = POPs;
SvREFCNT_inc(node);
PUTBACK;
FREETMPS;
LEAVE;
return node;
}
%}
%token L_BREAK L_CASE L_CATCH L_CLASS L_CONTINUE L_DEFAULT L_DO
%token L_EFUN L_ELSE L_FOR L_FOREACH L_IF L_IN L_INHERIT L_NEW
%token L_NIL L_RETURN L_RLIMITS L_SWITCH L_SSCANF L_TRY L_WHILE
%token L_MAP_START L_MAP_END
%token L_ARRAY_START L_ARRAY_END
%token L_FUNCTION_START L_FUNCTION_END
%token L_PARAMETER L_IDENTIFIER L_NIL L_STRING L_CHARACTER
%token L_INTEGER L_HEXINTEGER
%token L_BASIC_TYPE L_TYPE_MODIFIER L_STATIC
%token L_INHERIT L_COLONCOLON
%token L_IF L_DO L_WHILE L_FOR L_FOREACH L_IN L_RLIMITS
%token L_TRY L_CATCH
%token L_SWITCH L_CASE L_BREAK
%token L_CONTINUE L_RETURN L_ELSE
%token L_VOID L_ELLIPSIS
%token L_ARROW L_RANGE
%nonassoc LOWER_THAN_ELSE
%nonassoc L_ELSE
/* Strictly these can be %token */
%nonassoc L_PLUS_EQ L_MINUS_EQ L_DIV_EQ L_TIMES_EQ
%nonassoc L_MOD_EQ L_AND_EQ L_OR_EQ L_XOR_EQ L_DOT_EQ
/* Is this the right place? */
%nonassoc L_LOR_EQ L_LAND_EQ
/* %left CONST */
%right '?'
%left L_LOR
%left L_LAND
%left '|'
%left '^'
%left '&'
%left L_EQ L_NE
%left L_GE L_LE '<' '>'
%left L_LSH L_RSH
%left '.'
%left '+' '-'
%left '*' '%' '/'
%right '!' '~'
%nonassoc L_INC L_DEC
/* These aren't strictly necessary, but they help debugging. */
%token '{' '}' ',' ';' ':' '(' ')' '[' ']' '=' '$'
/* I should have a new type 'node' in here for blessed objects
* which are specifically parse nodes. */
/* It is very very tempting to expand this to say 12 bytes
( run in 0.498 second using v1.01-cache-2.11-cpan-ceb78f64989 )