1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
|
#ifndef __XS_PARSE_KEYWORD_H__
#define __XS_PARSE_KEYWORD_H__
#define XSPARSEKEYWORD_ABI_VERSION 2
struct XSParseKeywordPieceType;
struct XSParseKeywordPieceType {
int type;
union {
char c; /* LITERALCHAR */
const char *str; /* LITERALSTR */
const struct XSParseKeywordPieceType *pieces; /* containers */
void (*callback)(pTHX_ void *hookdata); /* SETUP, ANONSUB PREPARE+START */
OP *(*op_wrap_callback)(pTHX_ OP *o, void *hookdata);
} u;
};
enum {
XPK_FLAG_EXPR = (1<<0),
XPK_FLAG_STMT = (1<<1),
XPK_FLAG_AUTOSEMI = (1<<2),
XPK_FLAG_BLOCKSCOPE = (1<<3),
XPK_FLAG_PERMIT_LEXICAL = (1<<4),
};
enum {
/* skip zero */
/* emits */
XS_PARSE_KEYWORD_LITERALCHAR = 1, /* nothing */
XS_PARSE_KEYWORD_LITERALSTR, /* nothing */
XS_PARSE_KEYWORD_AUTOSEMI, /* nothing */
XS_PARSE_KEYWORD_WARNING = 0x0e, /* nothing */
XS_PARSE_KEYWORD_FAILURE, /* nothing */
XS_PARSE_KEYWORD_BLOCK = 0x10, /* op */
XS_PARSE_KEYWORD_ANONSUB, /* cv */
XS_PARSE_KEYWORD_ARITHEXPR, /* op */
XS_PARSE_KEYWORD_TERMEXPR, /* op */
XS_PARSE_KEYWORD_LISTEXPR, /* op */
/* TODO: XS_PARSE_KEYWORD_FULLEXPR = 0x15 */
XS_PARSE_KEYWORD_IDENT = 0x16, /* sv */
XS_PARSE_KEYWORD_PACKAGENAME, /* sv */
XS_PARSE_KEYWORD_LEXVARNAME, /* sv */
XS_PARSE_KEYWORD_LEXVAR, /* padix */
XS_PARSE_KEYWORD_ATTRS, /* i / {attr.name + attr.val} */
XS_PARSE_KEYWORD_VSTRING, /* sv */
XS_PARSE_KEYWORD_INFIX = 0x40, /* infix */
XS_PARSE_KEYWORD_INTRO_MY = 0x60, /* emits nothing */
XS_PARSE_KEYWORD_SETUP = 0x70, /* invokes callback, emits nothing */
XS_PARSE_KEYWORD_ANONSUB_PREPARE, /* invokes callback, emits nothing */
XS_PARSE_KEYWORD_ANONSUB_START, /* invokes callback, emits nothing */
XS_PARSE_KEYWORD_ANONSUB_END, /* invokes op_wrap_callback, emits nothing */
XS_PARSE_KEYWORD_ANONSUB_WRAP, /* invokes op_wrap_callback, emits nothing */
XS_PARSE_KEYWORD_SEQUENCE = 0x80, /* contained */
XS_PARSE_KEYWORD_REPEATED, /* i, contained */
XS_PARSE_KEYWORD_CHOICE, /* i, contained */
XS_PARSE_KEYWORD_TAGGEDCHOICE, /* i, contained */
XS_PARSE_KEYWORD_SEPARATEDLIST, /* i, contained */
XS_PARSE_KEYWORD_PARENS = 0xb0, /* contained */
XS_PARSE_KEYWORD_BRACKETS, /* contained */
XS_PARSE_KEYWORD_BRACES, /* contained */
XS_PARSE_KEYWORD_CHEVRONS, /* contained */
};
enum {
XPK_LEXVAR_SCALAR = (1<<0),
XPK_LEXVAR_ARRAY = (1<<1),
XPK_LEXVAR_HASH = (1<<2),
XPK_LEXVAR_ANY = XPK_LEXVAR_SCALAR|XPK_LEXVAR_ARRAY|XPK_LEXVAR_HASH,
};
enum {
XPK_TYPEFLAG_OPT = (1<<16),
XPK_TYPEFLAG_SPECIAL = (1<<17), /* on XPK_LITERALSTR: keyword
on XPK_BLOCK: scoped
on XPK_LEXVAR: my */
/* These three are shifted versions of perl's G_VOID, G_SCALAR, G_LIST */
XPK_TYPEFLAG_G_VOID = (1<<18),
XPK_TYPEFLAG_G_SCALAR = (2<<18),
XPK_TYPEFLAG_G_LIST = (3<<18),
XPK_TYPEFLAG_ENTERLEAVE = (1<<20), /* wrap ENTER/LEAVE pair around the item */
XPK_TYPEFLAG_MAYBEPARENS = (1<<21), /* parens themselves are optional on PARENS */
};
#define XPK_PREFIXED(typecode,...) \
{.type = typecode, .u.pieces = (const struct XSParseKeywordPieceType []){ __VA_ARGS__, {0} }}
#define XPK_BLOCK_flags(flags) {.type = XS_PARSE_KEYWORD_BLOCK|(flags), .u.pieces = NULL}
#define XPK_BLOCK XPK_BLOCK_flags(0)
#define XPK_BLOCK_VOIDCTX XPK_BLOCK_flags(XPK_TYPEFLAG_SPECIAL|XPK_TYPEFLAG_G_VOID)
#define XPK_BLOCK_SCALARCTX XPK_BLOCK_flags(XPK_TYPEFLAG_SPECIAL|XPK_TYPEFLAG_G_SCALAR)
#define XPK_BLOCK_LISTCTX XPK_BLOCK_flags(XPK_TYPEFLAG_SPECIAL|XPK_TYPEFLAG_G_LIST)
#define XPK_PREFIXED_BLOCK(...) XPK_PREFIXED(XS_PARSE_KEYWORD_BLOCK, __VA_ARGS__)
#define XPK_PREFIXED_BLOCK_ENTERLEAVE(...) XPK_PREFIXED(XS_PARSE_KEYWORD_BLOCK|XPK_TYPEFLAG_ENTERLEAVE, __VA_ARGS__)
#define XPK_SETUP(setup) {.type = XS_PARSE_KEYWORD_SETUP, .u.callback = setup}
#define XPK_ANONSUB {.type = XS_PARSE_KEYWORD_ANONSUB}
#define XPK_ANONSUB_PREPARE(func) {.type = XS_PARSE_KEYWORD_ANONSUB_PREPARE, .u.callback = func}
#define XPK_ANONSUB_START(func) {.type = XS_PARSE_KEYWORD_ANONSUB_START, .u.callback = func}
#define XPK_ANONSUB_END(func) {.type = XS_PARSE_KEYWORD_ANONSUB_END, .u.op_wrap_callback = func}
#define XPK_ANONSUB_WRAP(func) {.type = XS_PARSE_KEYWORD_ANONSUB_WRAP, .u.op_wrap_callback = func}
#define XPK_STAGED_ANONSUB(...) \
{.type = XS_PARSE_KEYWORD_ANONSUB, .u.pieces = (const struct XSParseKeywordPieceType []){ __VA_ARGS__, {0} }}
#define XPK_ARITHEXPR_flags(flags) {.type = XS_PARSE_KEYWORD_ARITHEXPR|(flags)}
#define XPK_ARITHEXPR XPK_ARITHEXPR_flags(0)
#define XPK_ARITHEXPR_VOIDCTX XPK_ARITHEXPR_flags(XPK_TYPEFLAG_G_VOID)
#define XPK_ARITHEXPR_SCALARCTX XPK_ARITHEXPR_flags(XPK_TYPEFLAG_G_SCALAR)
#define XPK_ARITHEXPR_OPT XPK_ARITHEXPR_flags(XPK_TYPEFLAG_OPT)
#define XPK_ARITHEXPR_VOIDCTX_OPT XPK_ARITHEXPR_flags(XPK_TYPEFLAG_G_VOID|XPK_TYPEFLAG_OPT)
#define XPK_ARITHEXPR_SCALARCTX_OPT XPK_ARITHEXPR_flags(XPK_TYPEFLAG_G_SCALAR|XPK_TYPEFLAG_OPT)
#define XPK_TERMEXPR_flags(flags) {.type = XS_PARSE_KEYWORD_TERMEXPR|(flags)}
#define XPK_TERMEXPR XPK_TERMEXPR_flags(0)
#define XPK_TERMEXPR_VOIDCTX XPK_TERMEXPR_flags(XPK_TYPEFLAG_G_VOID)
#define XPK_TERMEXPR_SCALARCTX XPK_TERMEXPR_flags(XPK_TYPEFLAG_G_SCALAR)
#define XPK_TERMEXPR_OPT XPK_TERMEXPR_flags(XPK_TYPEFLAG_OPT)
#define XPK_TERMEXPR_VOIDCTX_OPT XPK_TERMEXPR_flags(XPK_TYPEFLAG_G_VOID|XPK_TYPEFLAG_OPT)
#define XPK_TERMEXPR_SCALARCTX_OPT XPK_TERMEXPR_flags(XPK_TYPEFLAG_G_SCALAR|XPK_TYPEFLAG_OPT)
#define XPK_PREFIXED_TERMEXPR_ENTERLEAVE(...) XPK_PREFIXED(XS_PARSE_KEYWORD_TERMEXPR|XPK_TYPEFLAG_ENTERLEAVE, __VA_ARGS__)
#define XPK_LISTEXPR_flags(flags) {.type = XS_PARSE_KEYWORD_LISTEXPR|(flags)}
#define XPK_LISTEXPR XPK_LISTEXPR_flags(0)
#define XPK_LISTEXPR_LISTCTX XPK_LISTEXPR_flags(XPK_TYPEFLAG_G_LIST)
#define XPK_LISTEXPR_OPT XPK_LISTEXPR_flags(XPK_TYPEFLAG_OPT)
#define XPK_LISTEXPR_LISTCTX_OPT XPK_LISTEXPR_flags(XPK_TYPEFLAG_G_LIST|XPK_TYPEFLAG_OPT)
#define XPK_PREFIXED_LISTEXPR_ENTERLEAVE(...) XPK_PREFIXED(XS_PARSE_KEYWORD_LISTEXPR|XPK_TYPEFLAG_ENTERLEAVE, __VA_ARGS__)
#define XPK_IDENT {.type = XS_PARSE_KEYWORD_IDENT }
#define XPK_IDENT_OPT {.type = XS_PARSE_KEYWORD_IDENT |XPK_TYPEFLAG_OPT}
#define XPK_PACKAGENAME {.type = XS_PARSE_KEYWORD_PACKAGENAME }
#define XPK_PACKAGENAME_OPT {.type = XS_PARSE_KEYWORD_PACKAGENAME|XPK_TYPEFLAG_OPT}
#define XPK_LEXVARNAME(kind) {.type = XS_PARSE_KEYWORD_LEXVARNAME, .u.c = kind}
#define XPK_LEXVAR(kind) {.type = XS_PARSE_KEYWORD_LEXVAR, .u.c = kind}
#define XPK_LEXVAR_MY(kind) {.type = XS_PARSE_KEYWORD_LEXVAR|XPK_TYPEFLAG_SPECIAL, .u.c = kind}
#define XPK_ATTRIBUTES {.type = XS_PARSE_KEYWORD_ATTRS}
#define XPK_VSTRING {.type = XS_PARSE_KEYWORD_VSTRING}
#define XPK_VSTRING_OPT {.type = XS_PARSE_KEYWORD_VSTRING|XPK_TYPEFLAG_OPT}
#define XPK_COMMA {.type = XS_PARSE_KEYWORD_LITERALCHAR, .u.c = ','}
#define XPK_COLON {.type = XS_PARSE_KEYWORD_LITERALCHAR, .u.c = ':'}
#define XPK_EQUALS {.type = XS_PARSE_KEYWORD_LITERALCHAR, .u.c = '='}
#define XPK_LITERAL(s) {.type = XS_PARSE_KEYWORD_LITERALSTR, .u.str = (const char *)s}
#define XPK_STRING(s) XPK_LITERAL(s)
#define XPK_AUTOSEMI {.type = XS_PARSE_KEYWORD_AUTOSEMI}
#define XPK_KEYWORD(s) {.type = XS_PARSE_KEYWORD_LITERALSTR|XPK_TYPEFLAG_SPECIAL, .u.str = (const char *)s}
#define XPK_INFIX(select) {.type = XS_PARSE_KEYWORD_INFIX, .u.c = select}
#define XPK_INFIX_RELATION XPK_INFIX(XPI_SELECT_RELATION)
#define XPK_INFIX_EQUALITY XPK_INFIX(XPI_SELECT_EQUALITY)
#define XPK_INFIX_MATCH_NOSMART XPK_INFIX(XPI_SELECT_MATCH_NOSMART)
#define XPK_INFIX_MATCH_SMART XPK_INFIX(XPI_SELECT_MATCH_SMART)
#define XPK_INTRO_MY {.type = XS_PARSE_KEYWORD_INTRO_MY}
#define XPK_SEQUENCE_pieces(p) {.type = XS_PARSE_KEYWORD_SEQUENCE, .u.pieces = p}
#define XPK_SEQUENCE(...) XPK_SEQUENCE_pieces(((const struct XSParseKeywordPieceType []){ __VA_ARGS__, {0} }))
/* First piece of these must be something probe-able */
#define XPK_OPTIONAL_pieces(p) {.type = XS_PARSE_KEYWORD_SEQUENCE|XPK_TYPEFLAG_OPT, .u.pieces = p}
#define XPK_OPTIONAL(...) XPK_OPTIONAL_pieces(((const struct XSParseKeywordPieceType []){ __VA_ARGS__, {0} }))
#define XPK_REPEATED_pieces(p) {.type = XS_PARSE_KEYWORD_REPEATED, .u.pieces = p}
#define XPK_REPEATED(...) XPK_REPEATED_pieces(((const struct XSParseKeywordPieceType []){ __VA_ARGS__, {0} }))
/* Every piece must be probeable */
#define XPK_CHOICE_pieces(p) {.type = XS_PARSE_KEYWORD_CHOICE, .u.pieces = p}
#define XPK_CHOICE(...) XPK_CHOICE_pieces(((const struct XSParseKeywordPieceType []){ __VA_ARGS__, {0} }))
/* Every piece must be probeable, and followed by XPK_TAG */
#define XPK_TAGGEDCHOICE_pieces(p) {.type = XS_PARSE_KEYWORD_TAGGEDCHOICE, .u.pieces = p}
#define XPK_TAGGEDCHOICE(...) XPK_TAGGEDCHOICE_pieces(((const struct XSParseKeywordPieceType []){ __VA_ARGS__, {0}, {0} }))
#define XPK_TAG(val) {.type = val}
#define XPK_COMMALIST(...) \
{.type = XS_PARSE_KEYWORD_SEPARATEDLIST, .u.pieces = (const struct XSParseKeywordPieceType []){ \
{.type = XS_PARSE_KEYWORD_LITERALCHAR, .u.c = ','}, __VA_ARGS__, {0}}}
#define XPK_WARNING_bit(bit,s) {.type = (XS_PARSE_KEYWORD_WARNING|(bit << 24)), .u.str = (const char *)s}
#define XPK_WARNING(s) XPK_WARNING_bit(0,s)
#define XPK_WARNING_AMBIGUOUS(s) XPK_WARNING_bit(WARN_AMBIGUOUS, s)
#define XPK_WARNING_DEPRECATED(s) XPK_WARNING_bit(WARN_DEPRECATED, s)
#define XPK_WARNING_EXPERIMENTAL(s) XPK_WARNING_bit(WARN_EXPERIMENTAL,s)
#define XPK_WARNING_PRECEDENCE(s) XPK_WARNING_bit(WARN_PRECEDENCE, s)
#define XPK_WARNING_SYNTAX(s) XPK_WARNING_bit(WARN_SYNTAX, s)
#define XPK_FAILURE(s) {.type = XS_PARSE_KEYWORD_FAILURE, .u.str = (const char *)s}
#define XPK_PARENS_pieces(p) {.type = XS_PARSE_KEYWORD_PARENS, .u.pieces = p}
#define XPK_PARENS(...) XPK_PARENS_pieces(((const struct XSParseKeywordPieceType []){ __VA_ARGS__, {0} }))
#define XPK_PARENS_OPT(...) \
{.type = XS_PARSE_KEYWORD_PARENS|XPK_TYPEFLAG_OPT, .u.pieces = (const struct XSParseKeywordPieceType []){ __VA_ARGS__, {0} }}
#define XPK_ARGS_pieces(p) {.type = XS_PARSE_KEYWORD_PARENS|XPK_TYPEFLAG_MAYBEPARENS, .u.pieces = p}
#define XPK_ARGS(...) XPK_ARGS_pieces(((const struct XSParseKeywordPieceType []){ __VA_ARGS__, {0} }))
#define XPK_BRACKETS_pieces(p) {.type = XS_PARSE_KEYWORD_BRACKETS, .u.pieces = p}
#define XPK_BRACKETS(...) XPK_BRACKETS_pieces(((const struct XSParseKeywordPieceType []){ __VA_ARGS__, {0} }))
#define XPK_BRACKETS_OPT(...) \
{.type = XS_PARSE_KEYWORD_BRACKETS|XPK_TYPEFLAG_OPT, .u.pieces = (const struct XSParseKeywordPieceType []){ __VA_ARGS__, {0} }}
#define XPK_BRACES_pieces(p) {.type = XS_PARSE_KEYWORD_BRACES, .u.pieces = p}
#define XPK_BRACES(...) XPK_BRACES_pieces(((const struct XSParseKeywordPieceType []){ __VA_ARGS__, {0} }))
#define XPK_BRACES_OPT(...) \
{.type = XS_PARSE_KEYWORD_BRACES|XPK_TYPEFLAG_OPT, .u.pieces = (const struct XSParseKeywordPieceType []){ __VA_ARGS__, {0} }}
#define XPK_CHEVRONS_pieces(p) {.type = XS_PARSE_KEYWORD_CHEVRONS, .u.pieces = p}
#define XPK_CHEVRONS(...) XPK_CHEVRONS_pieces(((const struct XSParseKeywordPieceType []){ __VA_ARGS__, {0} }))
#define XPK_CHEVRONS_OPT(...) \
{.type = XS_PARSE_KEYWORD_CHEVRONS|XPK_TYPEFLAG_OPT, .u.pieces = (const struct XSParseKeywordPieceType []){ __VA_ARGS__, {0} }}
/* back-compat for older names */
#define XPK_PARENSCOPE_pieces XPK_PARENS_pieces
#define XPK_PARENSCOPE XPK_PARENS
#define XPK_PARENSCOPE_OPT XPK_PARENS_OPT
#define XPK_ARGSCOPE_pieces XPK_ARGS_pieces
#define XPK_ARGSCOPE XPK_ARGS
#define XPK_BRACKETSCOPE_pieces XPK_BRACKETS_pieces
#define XPK_BRACKETSCOPE XPK_BRACKETS
#define XPK_BRACKETSCOPE_OPT XPK_BRACKETS_OPT
#define XPK_BRACESCOPE_pieces XPK_BRACES_pieces
#define XPK_BRACESCOPE XPK_BRACES
#define XPK_BRACESCOPE_OPT XPK_BRACES_OPT
#define XPK_CHEVRONSCOPE_pieces XPK_CHEVRONS_pieces
#define XPK_CHEVRONSCOPE XPK_CHEVRONS
#define XPK_CHEVRONSCOPE_OPT XPK_CHEVRONS_OPT
/* This type defined in XSParseInfix.h */
typedef struct XSParseInfixInfo XSParseInfixInfo;
typedef struct {
union {
OP *op;
CV *cv;
SV *sv;
int i;
struct { SV *name; SV *value; } attr;
PADOFFSET padix;
XSParseInfixInfo *infix;
};
int line;
} XSParseKeywordPiece;
struct XSParseKeywordHooks {
U32 flags;
/* used by build1 */
struct XSParseKeywordPieceType piece1;
/* alternatively, used by build */
const struct XSParseKeywordPieceType *pieces;
/* These two hooks are ANDed together; both must pass, if present */
const char *permit_hintkey;
bool (*permit) (pTHX_ void *hookdata);
void (*check)(pTHX_ void *hookdata);
/* These are alternatives; the first one defined is used */
int (*parse)(pTHX_ OP **opp, void *hookdata);
int (*build)(pTHX_ OP **out, XSParseKeywordPiece *args[], size_t nargs, void *hookdata);
int (*build1)(pTHX_ OP **out, XSParseKeywordPiece *arg0, void *hookdata);
};
static void (*register_xs_parse_keyword_func)(pTHX_ const char *kwname, const struct XSParseKeywordHooks *hooks, void *hookdata);
#define register_xs_parse_keyword(kwname, hooks, hookdata) S_register_xs_parse_keyword(aTHX_ kwname, hooks, hookdata)
static void S_register_xs_parse_keyword(pTHX_ const char *kwname, const struct XSParseKeywordHooks *hooks, void *hookdata)
{
if(!register_xs_parse_keyword_func)
croak("Must call boot_xs_parse_keyword() first");
(*register_xs_parse_keyword_func)(aTHX_ kwname, hooks, hookdata);
}
#define boot_xs_parse_keyword(ver) S_boot_xs_parse_keyword(aTHX_ ver)
static void S_boot_xs_parse_keyword(pTHX_ double ver) {
SV **svp;
SV *versv = ver ? newSVnv(ver) : NULL;
load_module(PERL_LOADMOD_NOIMPORT, newSVpvs("XS::Parse::Keyword"), versv, NULL);
svp = hv_fetchs(PL_modglobal, "XS::Parse::Keyword/ABIVERSION_MIN", 0);
if(!svp)
croak("XS::Parse::Keyword ABI minimum version missing");
int abi_ver = SvIV(*svp);
if(abi_ver > XSPARSEKEYWORD_ABI_VERSION)
croak("XS::Parse::Keyword ABI version mismatch - library supports >= %d, compiled for %d",
abi_ver, XSPARSEKEYWORD_ABI_VERSION);
svp = hv_fetchs(PL_modglobal, "XS::Parse::Keyword/ABIVERSION_MAX", 0);
abi_ver = SvIV(*svp);
if(abi_ver < XSPARSEKEYWORD_ABI_VERSION)
croak("XS::Parse::Keyword ABI version mismatch - library supports <= %d, compiled for %d",
abi_ver, XSPARSEKEYWORD_ABI_VERSION);
register_xs_parse_keyword_func = INT2PTR(void (*)(pTHX_ const char *, const struct XSParseKeywordHooks *, void *),
SvUV(*hv_fetchs(PL_modglobal, "XS::Parse::Keyword/register()@2", 0)));
}
#endif
|