NAME

    XS::Parse::Sublike - XS functions to assist in parsing sub-like syntax

DESCRIPTION

    This module provides some XS functions to assist in writing parsers for
    sub-like syntax, primarily for authors of keyword plugins using the
    PL_keyword_plugin hook mechanism. It is unlikely to be of much use to
    anyone else; and highly unlikely to be any use when writing perl code
    using these. Unless you are writing a keyword plugin using XS, this
    module is not for you.

    This module is also currently experimental, and the design is still
    evolving and subject to change. Later versions may break ABI
    compatibility, requiring changes or at least a rebuild of any module
    that depends on it.

XS FUNCTIONS

 boot_xs_parse_sublike

      void boot_xs_parse_sublike(double ver)

    Call this function from your BOOT section in order to initialise the
    module and parsing hooks.

    ver should either be 0 or a decimal number for the module version
    requirement; e.g.

       boot_xs_parse_sublike(0.04);

 xs_parse_sublike

       int xs_parse_sublike(const struct XSParseSublikeHooks *hooks, OP **op_ptr)

    This function performs the actual parsing of a sub-like keyword. It
    expects the lexer to be at a position just after the introduction
    keyword has been consumed, and will proceed to parse an optional name,
    list of attributes, signature (if enabled by use feature 'signatures'),
    and code body. The return value and op_ptr can be used directly from
    the keyword plugin function. It is intended this function be invoked
    from it, and the result returned directly.

    For a more automated handling of keywords, see
    "register_xs_parse_sublike".

    hooks should be a structure that can provide optional function pointers
    used to customise the parsing process at various stages.

 register_xs_parse_sublike

       void register_xs_parse_sublike(const char *keyword,
         const struct XSParseSublikeHooks *hooks)

    This function installs a set of parsing hooks to be associated with the
    given keyword. Such a keyword will then be handled automatically by a
    keyword parser installed by XS::Parse::Sublike itself.

    When the keyword is encountered, the hook's permit function is first
    tested to see if the keyword is permitted at this point. If the
    function returns true then the keyword is consumed and parsed as per
    "xs_parse_sublike".

 xs_parse_sublike_any

       int xs_parse_sublike_any(const struct XSParseSublikeHooks *hooks, OP **op_ptr)

    This function expects to consume an introduction keyword at the lexer
    position which is either sub or the name of another sub-like keyword,
    which has been previously registered using "register_xs_parse_sublike".
    It then proceeds to parse the subsequent syntax similar to how it would
    have parsed if encountered by the module's own keyword parser plugin,
    except that the second set of hooks given here also take effect.

    If a regular sub is encountered, then this is parsed using the hooks in
    a similar way to xs_parse_sublike().

    If a different registered sub-like keyword is encountered, then parsing
    is performed using both sets of hooks - the ones given to this function
    as well as the ones registered with the keyword. This allows their
    effects to combined. The hooks given by the hooks argument are
    considered to be on the "outside" from those of the registered keyword
    "inside". The outside ones run first for all stages, except
    pre_blockend which runs them inside-out.

PARSE CONTEXT

    The various hook stages all share state about the ongoing parse process
    using various fields of the XSParseSublikeContext structure.

       struct XSParseSublikeContext {
          SV *name;
          OP *attrs;
          OP *body;
          CV *cv;
       }

PARSE HOOKS

    The XSParseSublikeHooks structure provides the following hook stages,
    which are invoked in the given order.

    The structure has a flags field, which controls various optional parts
    of operation. The following flags are defined.

    XS_PARSE_SUBLIKE_FLAG_FILTERATTRS

      If set, the optional filter_attr stage will be invoked.

    In addition there are two U8 fields named require_parts and skip_parts
    which control the behaviour of various parts of the syntax which are
    usually optional. Any parts with bits set in require_parts become
    non-optional, and an error if they are missing. Any parts with bits set
    in skip_parts will skip the relevant part of the parsing process.

    When two sets of hooks are combined by the xs_parse_sublike_any
    function, these bitmasks are accumulated together with inclusive or.
    Any part required by either set of hooks will still be required; any
    step skipped by either will be skipped entirely.

    If the same bit is set in both fields then the relevant parsing step
    will not be performed but it will still be an error for that section to
    be missing. This is likely not useful.

    Note that for skipped parts, only the actual parsing steps are skipped.
    A hook function can still set the relevant fields in the context
    structure anyway to force a particular value for those parts.

    XS_PARSE_SUBLIKE_PART_NAME

      The name of the function.

    XS_PARSE_SUBLIKE_PART_ATTRS

      The attributes of the function.

      This part can be skipped, but the bit is ignored when in
      require_parts. It is always permitted to not provide any additional
      attributes to a function definition.

    XS_PARSE_SUBLIKE_PART_SIGNATURE

      The attributes of the function.

      This part can be skipped, but the bit is ignored when in
      require_parts. It is always permitted not to provide a signature for
      a function definition, because such syntax only applies when use
      feature 'signatures' is in effect, and only on supporting perl
      versions.

 The permit Stage

       bool (*permit)(pTHX)

    Called by the installed keyword parser hook which is used to handle
    keywords registered by "register_xs_parse_sublike". This hook stage
    should inspect whether the keyword is permitted at this time (typically
    by inspecting the hints hash GvHV(PL_hintgv) for some imported key) and
    return true only if the keyword is permitted.

 Parse Name

    At this point, the optional name is parsed and filled into the name
    field of the context.

 The pre_subparse Stage

       void (*pre_subparse)(pTHX_ struct XSParseSublikeContext *ctx)

    Invoked just before start_subparse() is called.

 Parse Attrs

    At this point the optional sub attributes are parsed and filled into
    the attrs field of the context, then block_start() is called.

 The optional filter_attr Stage

       bool (*filter_attr)(pTHX_ struct XSParseSublikeContext *ctx,
          SV *attr, SV *val);

    If the flags field includes XS_PARSE_SUBLIKE_FLAG_FILTERATTRS then each
    individual attribute is passed through this optional filter function
    immediately as each is parsed. attr will be a string SV containing the
    name of the attribute, and val will either be NULL, or a string SV
    containing the contents of the parens after its name (without the
    parens themselves).

    If the filter returns true, it indicates that it has in some way
    handled the attribute and it should not be added to the list given to
    newATTRSUB(). If the filter returns false it will be handled in the
    usual way; equivalent to the case where the filter function did not
    exist.

 The post_blockstart Stage

       void (*post_blockstart)(pTHX_ struct XSParseSublikeContext *ctx)

    Invoked after the block_start() function has been called. This hook
    stage may wish to perform any alterations of PL_compcv or related,
    inspect or alter the lexical pad, provide hints hash values, or any
    other tasks before the signature and code body are parsed.

 Parse Body

    At this point, the main body of the function is parsed and the optree
    is stored in the body field of the context. If the perl version
    supports sub signatures and they are enabled and found, the body will
    be prefixed with the signature ops as well.

 The pre_blockend Stage

       void (*pre_blockend)(pTHX_ struct XSParseSublikeContext *ctx)

    Invoked just before the block_end() function is invoked. The hook stage
    may wish to inspect or alter the optree stored in the body context
    field.

 The post_newcv Stage

       void (*post_newcv)(pTHX_ struct XSParseSublikeContext *ctx)

    Invoked just after newATTRSUB() has been invoked on the optree. The
    hook stage may wish to inspect or alter the CV stored in the cv context
    field.

AUTHOR

    Paul Evans <leonerd@leonerd.org.uk>