Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package perl-XS-Parse-Keyword for openSUSE:Factory checked in at 2022-12-14 14:10:54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/perl-XS-Parse-Keyword (Old) and /work/SRC/openSUSE:Factory/.perl-XS-Parse-Keyword.new.1835 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "perl-XS-Parse-Keyword" Wed Dec 14 14:10:54 2022 rev:10 rq:1042728 version:0.30 Changes: -------- --- /work/SRC/openSUSE:Factory/perl-XS-Parse-Keyword/perl-XS-Parse-Keyword.changes 2022-11-09 12:56:40.200089005 +0100 +++ /work/SRC/openSUSE:Factory/.perl-XS-Parse-Keyword.new.1835/perl-XS-Parse-Keyword.changes 2022-12-14 14:11:08.391536946 +0100 @@ -1,0 +2,29 @@ +Sun Dec 4 03:10:55 UTC 2022 - Tina Müller <timueller+p...@suse.de> + +- updated to 0.30 + see /usr/share/doc/packages/perl-XS-Parse-Keyword/Changes + + 0.30 2022-12-03 + [CHANGES] + * Added XPK_STAGED_ANONSUB; inspired a bit by XS::Parse::Sublike for + customising the parsing of anonmethod + 0.29 2022-12-01 + [CHANGES] + * Added XPK_PREFIXED_TERMEXPR_ENTERLEAVE + [BUGFIXES] + * Don't try to call `SvPVX()` on a `newSV(0)` because -DDEBUGGING + perls get upset (RT145278) + * Remember to `break` out of switch block cases when testing for + `KEYWORD_PLUGIN_*` return values + 0.28 2022-11-25 + [CHANGES] + * Include a XSParseInfixClassification field in the XSParseInfixInfo + structure + * Do not permit mixed identifier/non characters in the names of + registered infix operators + * No longer supports XSParseInfix ABI version 0 + [BUGFIXES] + * When parsing an infix operator name, make sure not to be confused + by additional identifier characters immediately after it + +------------------------------------------------------------------- Old: ---- XS-Parse-Keyword-0.27.tar.gz New: ---- XS-Parse-Keyword-0.30.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ perl-XS-Parse-Keyword.spec ++++++ --- /var/tmp/diff_new_pack.pwRy9C/_old 2022-12-14 14:11:09.027540218 +0100 +++ /var/tmp/diff_new_pack.pwRy9C/_new 2022-12-14 14:11:09.031540238 +0100 @@ -18,7 +18,7 @@ %define cpan_name XS-Parse-Keyword Name: perl-XS-Parse-Keyword -Version: 0.27 +Version: 0.30 Release: 0 License: Artistic-1.0 OR GPL-1.0-or-later Summary: XS functions to assist in parsing keyword syntax ++++++ XS-Parse-Keyword-0.27.tar.gz -> XS-Parse-Keyword-0.30.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.27/Changes new/XS-Parse-Keyword-0.30/Changes --- old/XS-Parse-Keyword-0.27/Changes 2022-10-31 23:09:16.000000000 +0100 +++ new/XS-Parse-Keyword-0.30/Changes 2022-12-03 15:51:44.000000000 +0100 @@ -1,5 +1,32 @@ Revision history for XS-Parse-Keyword +0.30 2022-12-03 + [CHANGES] + * Added XPK_STAGED_ANONSUB; inspired a bit by XS::Parse::Sublike for + customising the parsing of anonmethod + +0.29 2022-12-01 + [CHANGES] + * Added XPK_PREFIXED_TERMEXPR_ENTERLEAVE + + [BUGFIXES] + * Don't try to call `SvPVX()` on a `newSV(0)` because -DDEBUGGING + perls get upset (RT145278) + * Remember to `break` out of switch block cases when testing for + `KEYWORD_PLUGIN_*` return values + +0.28 2022-11-25 + [CHANGES] + * Include a XSParseInfixClassification field in the XSParseInfixInfo + structure + * Do not permit mixed identifier/non characters in the names of + registered infix operators + * No longer supports XSParseInfix ABI version 0 + + [BUGFIXES] + * When parsing an infix operator name, make sure not to be confused + by additional identifier characters immediately after it + 0.27 2022-10-31 [CHANGES] * Updates to XS::Parse::Infix for latest `infix-plugin` perl5 branch diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.27/META.json new/XS-Parse-Keyword-0.30/META.json --- old/XS-Parse-Keyword-0.27/META.json 2022-10-31 23:09:16.000000000 +0100 +++ new/XS-Parse-Keyword-0.30/META.json 2022-12-03 15:51:44.000000000 +0100 @@ -40,19 +40,19 @@ "provides" : { "XS::Parse::Infix" : { "file" : "lib/XS/Parse/Infix.pm", - "version" : "0.27" + "version" : "0.30" }, "XS::Parse::Infix::Builder" : { "file" : "lib/XS/Parse/Infix/Builder.pm", - "version" : "0.27" + "version" : "0.30" }, "XS::Parse::Keyword" : { "file" : "lib/XS/Parse/Keyword.pm", - "version" : "0.27" + "version" : "0.30" }, "XS::Parse::Keyword::Builder" : { "file" : "lib/XS/Parse/Keyword/Builder.pm", - "version" : "0.27" + "version" : "0.30" } }, "release_status" : "stable", @@ -61,6 +61,6 @@ "http://dev.perl.org/licenses/" ] }, - "version" : "0.27", - "x_serialization_backend" : "JSON::PP version 4.06" + "version" : "0.30", + "x_serialization_backend" : "JSON::PP version 4.07" } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.27/META.yml new/XS-Parse-Keyword-0.30/META.yml --- old/XS-Parse-Keyword-0.27/META.yml 2022-10-31 23:09:16.000000000 +0100 +++ new/XS-Parse-Keyword-0.30/META.yml 2022-12-03 15:51:44.000000000 +0100 @@ -19,19 +19,19 @@ provides: XS::Parse::Infix: file: lib/XS/Parse/Infix.pm - version: '0.27' + version: '0.30' XS::Parse::Infix::Builder: file: lib/XS/Parse/Infix/Builder.pm - version: '0.27' + version: '0.30' XS::Parse::Keyword: file: lib/XS/Parse/Keyword.pm - version: '0.27' + version: '0.30' XS::Parse::Keyword::Builder: file: lib/XS/Parse/Keyword/Builder.pm - version: '0.27' + version: '0.30' requires: perl: '5.014' resources: license: http://dev.perl.org/licenses/ -version: '0.27' +version: '0.30' x_serialization_backend: 'CPAN::Meta::YAML version 0.018' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.27/README new/XS-Parse-Keyword-0.30/README --- old/XS-Parse-Keyword-0.27/README 2022-10-31 23:09:16.000000000 +0100 +++ new/XS-Parse-Keyword-0.30/README 2022-12-03 15:51:44.000000000 +0100 @@ -260,12 +260,67 @@ XPK_ANONSUB - atomic, emits op. + atomic, emits cv. A brace-delimited block of code is expected, and assembled into the body of a new anonymous subroutine. This will be passed as a protosub CV in the cv field. + XPK_STAGED_ANONSUB + + XPK_STAGED_ANONSUB(stages ...) + + structural, emits cv. + + A variant of XPK_ANONSUB which accepts additional function pointers to + be invoked at various points during parsing and compilation. These can + be used to interrupt the normal parsing in a manner similar to + XS::Parse::Sublike, though currently somewhat less flexibly. + + The stages list may contain elements of the following types. Not every + stage must be present, but any that are present must be in the + following order. Multiple copies of each stage are permitted; they are + invoked in the written order, with parser code happening inbetween. + + XPK_ANONSUB_PREPARE + + XPK_ANONSUB_PREPARE(&callback) + + atomic, emits nothing. + + Invokes the callback before start_subparse(). + + XPK_ANONSUB_START + + XPK_ANONSUB_START(&callback) + + atomic, emits nothing. + + Invokes the callback after block_start() but before parsing the + actual block contents. + + XPK_ANONSUB_END + + OP *op_wrapper_callback(pTHX_ OP *o, void *hookdata); + + XPK_ANONSUB_END(&op_wrapper_callback) + + atomic, emits nothing. + + Invokes the callback after parsing the block contents but before + calling block_end(). The callback may modify the optree if required + and return a new one. + + XPK_ANONSUB_WRAP + + XPK_ANONSUB_WRAP(&op_wrapper_callback) + + atomic, emits nothing. + + Invokes the callback after block_end() but before passing the optree + to newATTRSUB(). The callback may modify the optree if required and + return a new one. + XPK_ARITHEXPR atomic, emits op. @@ -294,6 +349,20 @@ Variants of XPK_TERMEXPR which puts the expression in void or scalar context. + XPK_PREFIXED_TERMEXPR_ENTERLEAVE + + XPK_PREFIXED_TERMEXPR_ENTERLEAVE(pieces ...) + + A variant of XPK_TERMEXPR which expects a sequence pieces first before + it parses a term expression, similar to how + XPK_PREFIXED_BLOCK_ENTERLEAVE works. The entire operation is wrapped in + an ENTER/LEAVE pair. + + This is intended just for use of XPK_SETUP pieces as prefixes. Any + other pieces which actually parse real input are likely to cause + overly-complex, subtle, or outright ambiguous grammars, and should be + avoided. + XPK_LISTEXPR atomic, emits op. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.27/XSParseInfix.h new/XS-Parse-Keyword-0.30/XSParseInfix.h --- old/XS-Parse-Keyword-0.27/XSParseInfix.h 2022-10-31 23:09:16.000000000 +0100 +++ new/XS-Parse-Keyword-0.30/XSParseInfix.h 2022-12-03 15:51:44.000000000 +0100 @@ -71,6 +71,8 @@ const struct XSParseInfixHooks *hooks; void *hookdata; + + enum XSParseInfixClassification cls; }; static bool (*parse_infix_func)(pTHX_ enum XSParseInfixSelection select, struct XSParseInfixInfo **infop); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.27/XSParseKeyword.h new/XS-Parse-Keyword-0.30/XSParseKeyword.h --- old/XS-Parse-Keyword-0.27/XSParseKeyword.h 2022-10-31 23:09:16.000000000 +0100 +++ new/XS-Parse-Keyword-0.30/XSParseKeyword.h 2022-12-03 15:51:44.000000000 +0100 @@ -7,10 +7,12 @@ struct XSParseKeywordPieceType { int type; union { - char c; /* LITERALCHAR */ - const char *str; /* LITERALSTR */ + char c; /* LITERALCHAR */ + const char *str; /* LITERALSTR */ const struct XSParseKeywordPieceType *pieces; /* SCOPEs */ - void (*callback)(pTHX_ void *hookdata); /* SETUP */ + void (*callback)(pTHX_ void *hookdata); /* SETUP, ANONSUB PREPARE+START */ + + OP *(*op_wrap_callback)(pTHX_ OP *o, void *hookdata); } u; }; @@ -46,6 +48,11 @@ 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 */ @@ -95,6 +102,14 @@ #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) @@ -107,6 +122,10 @@ #define XPK_LISTEXPR XPK_LISTEXPR_flags(0) #define XPK_LISTEXPR_LISTCTX XPK_LISTEXPR_flags(XPK_TYPEFLAG_G_LIST) +#define XPK_PREFIXED_TERMEXPR_flags(flags,...) \ + {.type = XS_PARSE_KEYWORD_TERMEXPR|(flags), .u.pieces = (const struct XSParseKeywordPieceType []){ __VA_ARGS__, {0} }} +#define XPK_PREFIXED_TERMEXPR_ENTERLEAVE(...) XPK_PREFIXED_TERMEXPR_flags(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 } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.27/lib/XS/Parse/Infix/Builder.pm new/XS-Parse-Keyword-0.30/lib/XS/Parse/Infix/Builder.pm --- old/XS-Parse-Keyword-0.27/lib/XS/Parse/Infix/Builder.pm 2022-10-31 23:09:16.000000000 +0100 +++ new/XS-Parse-Keyword-0.30/lib/XS/Parse/Infix/Builder.pm 2022-12-03 15:51:44.000000000 +0100 @@ -3,7 +3,7 @@ # # (C) Paul Evans, 2021 -- leon...@leonerd.org.uk -package XS::Parse::Infix::Builder 0.27; +package XS::Parse::Infix::Builder 0.30; use v5.14; use warnings; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.27/lib/XS/Parse/Infix/Builder_data.pm.PL new/XS-Parse-Keyword-0.30/lib/XS/Parse/Infix/Builder_data.pm.PL --- old/XS-Parse-Keyword-0.27/lib/XS/Parse/Infix/Builder_data.pm.PL 2022-10-31 23:09:16.000000000 +0100 +++ new/XS-Parse-Keyword-0.30/lib/XS/Parse/Infix/Builder_data.pm.PL 2022-12-03 15:51:44.000000000 +0100 @@ -28,7 +28,7 @@ <$in_h> } ); __DATA__ -package XS::Parse::Infix::Builder_data 0.27; +package XS::Parse::Infix::Builder_data 0.30; use v5.14; use warnings; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.27/lib/XS/Parse/Infix.pm new/XS-Parse-Keyword-0.30/lib/XS/Parse/Infix.pm --- old/XS-Parse-Keyword-0.27/lib/XS/Parse/Infix.pm 2022-10-31 23:09:16.000000000 +0100 +++ new/XS-Parse-Keyword-0.30/lib/XS/Parse/Infix.pm 2022-12-03 15:51:44.000000000 +0100 @@ -3,7 +3,7 @@ # # (C) Paul Evans, 2021-2022 -- leon...@leonerd.org.uk -package XS::Parse::Infix 0.27; +package XS::Parse::Infix 0.30; use v5.14; use warnings; @@ -72,6 +72,8 @@ bool parse_infix(enum XSParseInfixSelection select, struct XSParseInfixInfo **infop); +I<Since version 0.27.> + This function attempts to parse syntax for an infix operator from the current parser position. If it is successful, it fills in the variable pointed to by I<infop> with a pointer to the actual information structure and returns @@ -109,6 +111,8 @@ struct XSParseInfixHooks *hooks; void *hookdata; + + enum XSParseInfixClassification cls; /* since version 0.28 */ }; If the operator name contains any non-ASCII characters they are presumed to be diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.27/lib/XS/Parse/Keyword/Builder.pm new/XS-Parse-Keyword-0.30/lib/XS/Parse/Keyword/Builder.pm --- old/XS-Parse-Keyword-0.27/lib/XS/Parse/Keyword/Builder.pm 2022-10-31 23:09:16.000000000 +0100 +++ new/XS-Parse-Keyword-0.30/lib/XS/Parse/Keyword/Builder.pm 2022-12-03 15:51:44.000000000 +0100 @@ -3,7 +3,7 @@ # # (C) Paul Evans, 2021 -- leon...@leonerd.org.uk -package XS::Parse::Keyword::Builder 0.27; +package XS::Parse::Keyword::Builder 0.30; use v5.14; use warnings; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.27/lib/XS/Parse/Keyword/Builder_data.pm.PL new/XS-Parse-Keyword-0.30/lib/XS/Parse/Keyword/Builder_data.pm.PL --- old/XS-Parse-Keyword-0.27/lib/XS/Parse/Keyword/Builder_data.pm.PL 2022-10-31 23:09:16.000000000 +0100 +++ new/XS-Parse-Keyword-0.30/lib/XS/Parse/Keyword/Builder_data.pm.PL 2022-12-03 15:51:44.000000000 +0100 @@ -28,7 +28,7 @@ <$in_h> } ); __DATA__ -package XS::Parse::Keyword::Builder_data 0.27; +package XS::Parse::Keyword::Builder_data 0.30; use v5.14; use warnings; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.27/lib/XS/Parse/Keyword.pm new/XS-Parse-Keyword-0.30/lib/XS/Parse/Keyword.pm --- old/XS-Parse-Keyword-0.27/lib/XS/Parse/Keyword.pm 2022-10-31 23:09:16.000000000 +0100 +++ new/XS-Parse-Keyword-0.30/lib/XS/Parse/Keyword.pm 2022-12-03 15:51:44.000000000 +0100 @@ -3,7 +3,7 @@ # # (C) Paul Evans, 2021-2022 -- leon...@leonerd.org.uk -package XS::Parse::Keyword 0.27; +package XS::Parse::Keyword 0.30; use v5.14; use warnings; @@ -277,12 +277,71 @@ =head2 XPK_ANONSUB -I<atomic, emits op.> +I<atomic, emits cv.> A brace-delimited block of code is expected, and assembled into the body of a new anonymous subroutine. This will be passed as a protosub CV in the I<cv> field. +=head2 XPK_STAGED_ANONSUB + + XPK_STAGED_ANONSUB(stages ...) + +I<structural, emits cv.> + +A variant of C<XPK_ANONSUB> which accepts additional function pointers to be +invoked at various points during parsing and compilation. These can be used to +interrupt the normal parsing in a manner similar to L<XS::Parse::Sublike>, +though currently somewhat less flexibly. + +The I<stages> list may contain elements of the following types. Not every +stage must be present, but any that are present must be in the following +order. Multiple copies of each stage are permitted; they are invoked in the +written order, with parser code happening inbetween. + +=over 4 + +=item XPK_ANONSUB_PREPARE + + XPK_ANONSUB_PREPARE(&callback) + +I<atomic, emits nothing.> + +Invokes the callback before C<start_subparse()>. + +=item XPK_ANONSUB_START + + XPK_ANONSUB_START(&callback) + +I<atomic, emits nothing.> + +Invokes the callback after C<block_start()> but before parsing the actual +block contents. + +=item XPK_ANONSUB_END + + OP *op_wrapper_callback(pTHX_ OP *o, void *hookdata); + + XPK_ANONSUB_END(&op_wrapper_callback) + +I<atomic, emits nothing.> + +Invokes the callback after parsing the block contents but before calling +C<block_end()>. The callback may modify the optree if required and return a +new one. + +=item XPK_ANONSUB_WRAP + + XPK_ANONSUB_WRAP(&op_wrapper_callback) + +I<atomic, emits nothing.> + +Invokes the callback after C<block_end()> but before passing the optree to +C<newATTRSUB()>. The callback may modify the optree if required and return a +new one. + +=back + =head2 XPK_ARITHEXPR I<atomic, emits op.> @@ -309,6 +368,18 @@ Variants of C<XPK_TERMEXPR> which puts the expression in void or scalar context. +=head2 XPK_PREFIXED_TERMEXPR_ENTERLEAVE + + XPK_PREFIXED_TERMEXPR_ENTERLEAVE(pieces ...) + +A variant of C<XPK_TERMEXPR> which expects a sequence pieces first before it +parses a term expression, similar to how C<XPK_PREFIXED_BLOCK_ENTERLEAVE> +works. The entire operation is wrapped in an C<ENTER>/C<LEAVE> pair. + +This is intended just for use of C<XPK_SETUP> pieces as prefixes. Any other +pieces which actually parse real input are likely to cause overly-complex, +subtle, or outright ambiguous grammars, and should be avoided. + =head2 XPK_LISTEXPR I<atomic, emits op.> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.27/lib/XS/Parse/Keyword.xs new/XS-Parse-Keyword-0.30/lib/XS/Parse/Keyword.xs --- old/XS-Parse-Keyword-0.27/lib/XS/Parse/Keyword.xs 2022-10-31 23:09:16.000000000 +0100 +++ new/XS-Parse-Keyword-0.30/lib/XS/Parse/Keyword.xs 2022-12-03 15:51:44.000000000 +0100 @@ -16,39 +16,6 @@ #include "keyword.h" #include "infix.h" -/* v0 hooks lacked wrapper_func_name */ -struct XSParseInfixHooks_v0 { - U32 flags; - enum XSParseInfixClassification cls; - - const char *permit_hintkey; - bool (*permit) (pTHX_ void *hookdata); - - OP *(*new_op)(pTHX_ U32 flags, OP *lhs, OP *rhs, void *hookdata); - OP *(*ppaddr)(pTHX); -}; - -static void XSParseInfix_register_v0(pTHX_ const char *opname, const struct XSParseInfixHooks_v0 *hooks_v0, void *hookdata) -{ - warn("XSParseInfix ABI version 0 is deprecated and will soon be removed"); - - struct XSParseInfixHooks *hooks; - Newx(hooks, 1, struct XSParseInfixHooks); - - hooks->flags = hooks_v0->flags | (1<<15); /* NO_PARSEDATA */ - hooks->cls = hooks_v0->cls; - - hooks->wrapper_func_name = NULL; - - hooks->permit_hintkey = hooks_v0->permit_hintkey; - hooks->permit = hooks_v0->permit; - hooks->new_op = (OP *(*)(pTHX_ U32, OP *, OP *, SV **, void *))hooks_v0->new_op; - hooks->ppaddr = hooks_v0->ppaddr; - hooks->parse = NULL; - - XSParseInfix_register(aTHX_ opname, hooks, hookdata); -} - /* v1 hooks.newop did not pass parsedata */ struct XSParseInfixHooks_v1 { U16 flags; @@ -108,12 +75,11 @@ XSParseKeyword_boot(aTHX); - sv_setiv(*hv_fetchs(PL_modglobal, "XS::Parse::Infix/ABIVERSION_MIN", 1), 0); + sv_setiv(*hv_fetchs(PL_modglobal, "XS::Parse::Infix/ABIVERSION_MIN", 1), 1); sv_setiv(*hv_fetchs(PL_modglobal, "XS::Parse::Infix/ABIVERSION_MAX", 1), XSPARSEINFIX_ABI_VERSION); sv_setuv(*hv_fetchs(PL_modglobal, "XS::Parse::Infix/parse()@2", 1), PTR2UV(&XSParseInfix_parse)); sv_setuv(*hv_fetchs(PL_modglobal, "XS::Parse::Infix/new_op()@0", 1), PTR2UV(&XSParseInfix_new_op)); - sv_setuv(*hv_fetchs(PL_modglobal, "XS::Parse::Infix/register()@0", 1), PTR2UV(&XSParseInfix_register_v0)); sv_setuv(*hv_fetchs(PL_modglobal, "XS::Parse::Infix/register()@1", 1), PTR2UV(&XSParseInfix_register_v1)); sv_setuv(*hv_fetchs(PL_modglobal, "XS::Parse::Infix/register()@2", 1), PTR2UV(&XSParseInfix_register)); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.27/src/infix.c new/XS-Parse-Keyword-0.30/src/infix.c --- old/XS-Parse-Keyword-0.27/src/infix.c 2022-10-31 23:09:16.000000000 +0100 +++ new/XS-Parse-Keyword-0.30/src/infix.c 2022-12-03 15:51:44.000000000 +0100 @@ -136,13 +136,13 @@ struct XSParseInfixInfo info; STRLEN oplen; - enum XSParseInfixClassification cls; struct HooksAndData hd; STRLEN permit_hintkey_len; int opname_is_WIDE : 1; + int opname_is_ident : 1; }; static struct Registration *registrations; @@ -345,8 +345,11 @@ continue; if(!strnEQ(buf, reg->info.opname, reg->oplen)) continue; - - if(!(selection & (1 << reg->cls))) + /* If the operator name is an identifer then we don't want to capture a + * longer identifier from the incoming source of which this is just a + * prefix + */ + if(reg->opname_is_ident && isIDCONT_utf8_safe(buf + reg->oplen, PL_parser->bufend)) continue; if(reg->hd.hooks && reg->hd.hooks->permit_hintkey && @@ -357,6 +360,12 @@ !(*reg->hd.hooks->permit)(aTHX_ reg->hd.data)) continue; + /* At this point we're committed to this being the best match of operator. + * Is it selected by the filter? + */ + if(!(selection & (1 << reg->info.cls))) + return FALSE; + *infop = ®->info; lex_read_to(PL_parser->bufptr + reg->oplen); @@ -636,9 +645,9 @@ reg->info.opname = savepv(opname); reg->info.opcode = opcode; reg->info.hooks = NULL; + reg->info.cls = cls; reg->oplen = strlen(opname); - reg->cls = cls; reg->hd.hooks = NULL; reg->hd.data = NULL; @@ -653,6 +662,27 @@ void XSParseInfix_register(pTHX_ const char *opname, const struct XSParseInfixHooks *hooks, void *hookdata) { + STRLEN oplen = strlen(opname); + const char *opname_end = opname + oplen; + bool opname_is_ident = isIDFIRST_utf8_safe(opname, opname_end); + + { + const char *s = opname; + s += UTF8SKIP(s); + + while(s < opname_end) { + if(opname_is_ident) { + if(!isIDCONT_utf8_safe(s, opname_end)) + croak("Infix operator name that starts with an identifier may not have non-identifier characters in it"); + } + else { + if(isIDFIRST_utf8_safe(s, opname_end)) + croak("Infix operator name that does not start with an identifer may not have identifier characters in it"); + } + s += UTF8SKIP(s); + } + } + switch(hooks->flags) { case (1<<15): /* undocumented internal flag to indicate v1-compatible ->new_op hook function */ @@ -730,9 +760,10 @@ reg->info.opcode = OP_CUSTOM; reg->info.hooks = hooks; reg->info.hookdata = hookdata; + reg->info.cls = hooks->cls; - reg->oplen = strlen(opname); - reg->cls = hooks->cls; + reg->oplen = oplen; + reg->opname_is_ident = opname_is_ident; reg->hd.hooks = hooks; reg->hd.data = hookdata; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.27/src/keyword.c new/XS-Parse-Keyword-0.30/src/keyword.c --- old/XS-Parse-Keyword-0.27/src/keyword.c 2022-10-31 23:09:16.000000000 +0100 +++ new/XS-Parse-Keyword-0.30/src/keyword.c 2022-12-03 15:51:44.000000000 +0100 @@ -342,15 +342,36 @@ croak("TODO: probe_piece on type=%d\n", type); } +static void parse_prefix_pieces(pTHX_ SV *argsv, size_t *argidx, const struct XSParseKeywordPieceType *pieces, void *hookdata) +{ + while(pieces->type) { + if(pieces->type == XS_PARSE_KEYWORD_SETUP) + (pieces->u.callback)(aTHX_ hookdata); + else { + parse_piece(aTHX_ argsv, argidx, pieces, hookdata); + lex_read_space(0); + } + + pieces++; + } + + intro_my(); /* in case any of the pieces was XPK_LEXVAR_MY */ +} + static void parse_piece(pTHX_ SV *argsv, size_t *argidx, const struct XSParseKeywordPieceType *piece, void *hookdata) { int argi = *argidx; - if(argi >= (SvLEN(argsv) / sizeof(XSParseKeywordPiece))) - SvGROW(argsv, SvLEN(argsv) * 2); +#define CHECK_GROW_ARGSV \ + do { \ + if(argi >= (SvLEN(argsv) / sizeof(XSParseKeywordPiece))) \ + SvGROW(argsv, SvLEN(argsv) * 2); \ + } while(0) #define THISARG ((XSParseKeywordPiece *)SvPVX(argsv))[argi] + CHECK_GROW_ARGSV; + THISARG.line = #if HAVE_PERL_VERSION(5, 20, 0) /* on perl 5.20 onwards, CopLINE(PL_curcop) is only set at runtime; during @@ -399,27 +420,11 @@ I32 save_ix = block_start(1); if(piece->u.pieces) { - /* The prefix pieces */ - const struct XSParseKeywordPieceType *pieces = piece->u.pieces; - - while(pieces->type) { - if(pieces->type == XS_PARSE_KEYWORD_SETUP) - (pieces->u.callback)(aTHX_ hookdata); - else { - parse_piece(aTHX_ argsv, argidx, pieces, hookdata); - lex_read_space(0); - } - - pieces++; - } + parse_prefix_pieces(aTHX_ argsv, argidx, piece->u.pieces, hookdata); if(*argidx > argi) { argi = *argidx; - - if(argi >= (SvLEN(argsv) / sizeof(XSParseKeywordPiece))) - SvGROW(argsv, SvLEN(argsv) * 2); - - intro_my(); /* in case any of the pieces was XPK_LEXVAR_MY */ + CHECK_GROW_ARGSV; } } @@ -448,16 +453,39 @@ case XS_PARSE_KEYWORD_ANONSUB: { + const struct XSParseKeywordPieceType *stages = piece->u.pieces; + + while(stages && stages->type == XS_PARSE_KEYWORD_ANONSUB_PREPARE) { + (*stages->u.callback)(aTHX_ hookdata); + stages++; + } + I32 floor_ix = start_subparse(FALSE, CVf_ANON); SAVEFREESV(PL_compcv); I32 save_ix = block_start(0); + + while(stages && stages->type == XS_PARSE_KEYWORD_ANONSUB_START) { + (*stages->u.callback)(aTHX_ hookdata); + stages++; + } + OP *body = parse_block(0); CHECK_PARSEFAIL; + while(stages && stages->type == XS_PARSE_KEYWORD_ANONSUB_END) { + body = (*stages->u.op_wrap_callback)(aTHX_ body, hookdata); + stages++; + } + SvREFCNT_inc(PL_compcv); body = block_end(save_ix, body); + while(stages && stages->type == XS_PARSE_KEYWORD_ANONSUB_WRAP) { + body = (*stages->u.op_wrap_callback)(aTHX_ body, hookdata); + stages++; + } + THISARG.cv = newATTRSUB(floor_ix, NULL, NULL, NULL, body); (*argidx)++; return; @@ -465,6 +493,19 @@ case XS_PARSE_KEYWORD_ARITHEXPR: case XS_PARSE_KEYWORD_TERMEXPR: + { + if(is_enterleave) + ENTER; + + if(piece->u.pieces) { + parse_prefix_pieces(aTHX_ argsv, argidx, piece->u.pieces, hookdata); + + if(*argidx > argi) { + argi = *argidx; + CHECK_GROW_ARGSV; + } + } + /* TODO: This auto-parens behaviour ought to be tuneable, depend on how * many args, open at i=0 and close at i=MAX, etc... */ @@ -495,7 +536,12 @@ THISARG.op = op_contextualize(THISARG.op, want); (*argidx)++; + + if(is_enterleave) + LEAVE; + return; + } case XS_PARSE_KEYWORD_LISTEXPR: THISARG.op = parse_listexpr(0); @@ -787,9 +833,13 @@ if(hooks->build) { /* build function takes an array of pointers to piece structs, so we can * add new fields to the end of them without breaking back-compat. */ - SV *ptrssv = newSV(argidx * sizeof(XSParseKeywordPiece *)); - XSParseKeywordPiece **argptrs = (XSParseKeywordPiece **)SvPVX(ptrssv); - SAVEFREESV(ptrssv); + XSParseKeywordPiece **argptrs = NULL; + if(argidx) { + SV *ptrssv = newSV(argidx * sizeof(XSParseKeywordPiece *)); + SAVEFREESV(ptrssv); + + argptrs = (XSParseKeywordPiece **)SvPVX(ptrssv); + } int i; for(i = 0; i < argidx; i++) @@ -813,11 +863,13 @@ if(ret && (ret != KEYWORD_PLUGIN_EXPR)) yycroakf("Expected parse function for '%s' keyword to return KEYWORD_PLUGIN_EXPR but it did not", reg->kwname); + break; case XPK_FLAG_STMT: if(ret && (ret != KEYWORD_PLUGIN_STMT)) yycroakf("Expected parse function for '%s' keyword to return KEYWORD_PLUGIN_STMT but it did not", reg->kwname); + break; } return ret; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.27/t/32pieces-anonsub.t new/XS-Parse-Keyword-0.30/t/32pieces-anonsub.t --- old/XS-Parse-Keyword-0.27/t/32pieces-anonsub.t 2022-10-31 23:09:16.000000000 +0100 +++ new/XS-Parse-Keyword-0.30/t/32pieces-anonsub.t 2022-12-03 15:51:44.000000000 +0100 @@ -16,4 +16,13 @@ is( $ret->(), "sub value", 'result of invoking' ); } +{ + my $ret = piecestagedanonsub { return "$VAR, world" }; + + is( ref $ret, "CODE", 'result of piecestagedanonsub is CODE reference' ); + is( $ret->(), "Hello, world", 'result of invoking' ); + + is( $::STAGES, "PREPARE,START,END,WRAP", 'All ANONSUB stages were invoked' ); +} + done_testing; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.27/t/33pieces-termexpr.t new/XS-Parse-Keyword-0.30/t/33pieces-termexpr.t --- old/XS-Parse-Keyword-0.27/t/33pieces-termexpr.t 2022-10-31 23:09:16.000000000 +0100 +++ new/XS-Parse-Keyword-0.30/t/33pieces-termexpr.t 2022-12-03 15:51:44.000000000 +0100 @@ -35,4 +35,9 @@ is( $ret, "(x)y", 'termexpr treats (PARENS) as entire expression' ); } +{ + $ret = pieceprefixedtermexpr_VAR $VAR . ", world!"; + is( $ret, "(Hello, world!)", 'result of pieceprefixedtermexpr_VAR' ); +} + done_testing; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/XS-Parse-Keyword-0.27/t/pieces.xs new/XS-Parse-Keyword-0.30/t/pieces.xs --- old/XS-Parse-Keyword-0.27/t/pieces.xs 2022-10-31 23:09:16.000000000 +0100 +++ new/XS-Parse-Keyword-0.30/t/pieces.xs 2022-12-03 15:51:44.000000000 +0100 @@ -134,6 +134,40 @@ sv_setpvs(PAD_SVl(padix), "Hello"); } +static void callback_catpv_stages(pTHX_ const char *pv) +{ + SV *sv = get_sv("main::STAGES", GV_ADD); + if(!SvPOK(sv)) + sv_setpvs(sv, ""); + + if(SvCUR(sv)) + sv_catpvs(sv, ","); + + sv_catpv(sv, pv); +} + +static void callback_PREPARE(pTHX_ void *hookdata) +{ + callback_catpv_stages(aTHX_ "PREPARE"); +} + +static void callback_START(pTHX_ void *hookdata) +{ + callback_catpv_stages(aTHX_ "START"); +} + +static OP *callback_END(pTHX_ OP *o, void *hookdata) +{ + callback_catpv_stages(aTHX_ "END"); + return o; +} + +static OP *callback_WRAP(pTHX_ OP *o, void *hookdata) +{ + callback_catpv_stages(aTHX_ "WRAP"); + return o; +} + static const struct XSParseKeywordHooks hooks_block = { .permit_hintkey = hintkey, @@ -177,6 +211,19 @@ .build1 = &build_anonsub, }; +static const struct XSParseKeywordHooks hooks_stagedanonsub = { + .permit_hintkey = hintkey, + + .piece1 = XPK_STAGED_ANONSUB( + XPK_ANONSUB_PREPARE(&callback_PREPARE), + XPK_ANONSUB_START(&callback_START), + XPK_ANONSUB_START(&setup_block_VAR), + XPK_ANONSUB_END(&callback_END), + XPK_ANONSUB_WRAP(&callback_WRAP) + ), + .build1 = &build_anonsub, +}; + static const struct XSParseKeywordHooks hooks_arithexpr = { .permit_hintkey = hintkey, @@ -191,6 +238,13 @@ .build1 = &build_expr, }; +static const struct XSParseKeywordHooks hooks_prefixedtermexpr_VAR = { + .permit_hintkey = hintkey, + + .piece1 = XPK_PREFIXED_TERMEXPR_ENTERLEAVE( XPK_SETUP(&setup_block_VAR) ), + .build1 = &build_expr, +}; + static const struct XSParseKeywordHooks hooks_listexpr = { .permit_hintkey = hintkey, @@ -312,10 +366,15 @@ register_xs_parse_keyword("pieceprefixedblock_VAR", &hooks_prefixedblock_VAR, "$VAR"); register_xs_parse_keyword("pieceanonsub", &hooks_anonsub, NULL); + + register_xs_parse_keyword("piecestagedanonsub", &hooks_stagedanonsub, "$VAR"); + register_xs_parse_keyword("piecearithexpr", &hooks_arithexpr, NULL); register_xs_parse_keyword("piecetermexpr", &hooks_termexpr, NULL); register_xs_parse_keyword("piecelistexpr", &hooks_listexpr, NULL); + register_xs_parse_keyword("pieceprefixedtermexpr_VAR", &hooks_prefixedtermexpr_VAR, "$VAR"); + register_xs_parse_keyword("pieceident", &hooks_ident, NULL); register_xs_parse_keyword("pieceident_opt", &hooks_ident_opt, NULL); register_xs_parse_keyword("piecepkg", &hooks_packagename, NULL);