#include "EXTERN.h"
#include "perl.h"
#include "callparser1.h"
#include "XSUB.h"
#ifndef cv_clone
#define cv_clone(a) Perl_cv_clone(aTHX_ a)
#endif
static SV *parser_fn(OP *(fn)(pTHX_ U32), bool named)
{
I32 floor;
CV *code;
U8 errors;
ENTER;
PL_curcop = &PL_compiling;
SAVEVPTR(PL_op);
SAVEI8(PL_parser->error_count);
PL_parser->error_count = 0;
floor = start_subparse(0, named ? 0 : CVf_ANON);
code = newATTRSUB(floor, NULL, NULL, NULL, fn(aTHX_ 0));
errors = PL_parser->error_count;
LEAVE;
if (errors) {
++PL_parser->error_count;
return newSV(0);
}
else {
if (CvCLONE(code)) {
code = cv_clone(code);
}
return newRV_inc((SV*)code);
}
}
static OP *parser_callback(pTHX_ GV *namegv, SV *psobj, U32 *flagsp)
{
dSP;
SV *args_generator;
SV *statement = NULL;
I32 count;
/* call the parser callback
* it should take no arguments and return a coderef which, when called,
* produces the arguments to the keyword function
* the optree we want to generate is for something like
* mykeyword($code->())
* where $code is the thing returned by the parser function
*/
PUSHMARK(SP);
mXPUSHp(GvNAME(namegv), GvNAMELEN(namegv));
PUTBACK;
count = call_sv(psobj, G_ARRAY);
SPAGAIN;
if (count > 1) {
statement = POPs;
}
args_generator = SvREFCNT_inc(POPs);
PUTBACK;
if (!SvROK(args_generator) || SvTYPE(SvRV(args_generator)) != SVt_PVCV) {
croak("The parser function for %s must return a coderef, not %"SVf,
GvNAME(namegv), args_generator);
}
if (SvTRUE(statement)) {
*flagsp |= CALLPARSER_STATEMENT;
}
return newUNOP(OP_ENTERSUB, OPf_STACKED,
newCVREF(0, newSVOP(OP_CONST, 0, args_generator)));
}
/* TODO:
* - "parse a variable name"
* - "parse a quoted string"
* - "create a new lexical variable" (maybe?)
*/
MODULE = Parse::Keyword PACKAGE = Parse::Keyword
PROTOTYPES: DISABLE
void
install_keyword_handler(keyword, handler)
SV *keyword
SV *handler
CODE:
cv_set_call_parser((CV*)SvRV(keyword), parser_callback, handler);
SV *
lex_peek(len = 1)
UV len
CODE:
PL_curcop = &PL_compiling;
/* XXX before 5.19.2, lex_next_chunk when we aren't at the end of a line
* just breaks things entirely (the parser no longer sees the text that is
* read in). this is (i think inadvertently) fixed in 5.19.2 (21791330a),
* but it still screws up the line numbers of everything that follows. so,
* the workaround is just to not call lex_next_chunk unless we're at the
* end of a line. this is a bit limiting, but should rarely come up in
* practice.
*/
/*
while (PL_parser->bufend - PL_parser->bufptr < len) {
if (!lex_next_chunk(0)) {
break;
}
}
*/
if (PL_parser->bufptr == PL_parser->bufend) {
lex_next_chunk(0);
}
if (PL_parser->bufend - PL_parser->bufptr < len) {
len = PL_parser->bufend - PL_parser->bufptr;
}
RETVAL = newSVpvn(PL_parser->bufptr, len); /* XXX unicode? */
OUTPUT:
RETVAL
void
lex_read(len = 1)
UV len
CODE:
PL_curcop = &PL_compiling;
lex_read_to(PL_parser->bufptr + len);
void
lex_read_space()
CODE:
PL_curcop = &PL_compiling;
lex_read_space(0);
void
lex_stuff(str)
SV *str
CODE:
PL_curcop = &PL_compiling;
lex_stuff_sv(str, 0);
SV *
parse_block(named = FALSE)
bool named
CODE:
RETVAL = parser_fn(Perl_parse_block, named);
OUTPUT:
RETVAL
SV *
parse_stmtseq(named = FALSE)
bool named
CODE:
RETVAL = parser_fn(Perl_parse_stmtseq, named);
OUTPUT:
RETVAL
SV *
parse_fullstmt(named = FALSE)
bool named
CODE:
RETVAL = parser_fn(Perl_parse_fullstmt, named);
OUTPUT:
RETVAL
SV *
parse_barestmt(named = FALSE)
bool named
CODE:
RETVAL = parser_fn(Perl_parse_barestmt, named);
OUTPUT:
RETVAL
SV *
parse_fullexpr(named = FALSE)
bool named
CODE:
RETVAL = parser_fn(Perl_parse_fullexpr, named);
OUTPUT:
RETVAL
SV *
parse_listexpr(named = FALSE)
bool named
CODE:
RETVAL = parser_fn(Perl_parse_listexpr, named);
OUTPUT:
RETVAL
SV *
parse_termexpr(named = FALSE)
bool named
CODE:
RETVAL = parser_fn(Perl_parse_termexpr, named);
OUTPUT:
RETVAL
SV *
parse_arithexpr(named = FALSE)
bool named
CODE:
RETVAL = parser_fn(Perl_parse_arithexpr, named);
OUTPUT:
RETVAL
SV *
compiling_package()
CODE:
RETVAL = newSVsv(PL_curstname);
OUTPUT:
RETVAL