{"id":567,"date":"2009-11-20T17:31:30","date_gmt":"2009-11-21T01:31:30","guid":{"rendered":"http:\/\/boost-spirit.com\/home\/?page_id=567"},"modified":"2010-08-18T15:07:27","modified_gmt":"2010-08-18T22:07:27","slug":"creating-your-own-parser-component-for-spirit-qi","status":"publish","type":"page","link":"http:\/\/boost-spirit.com\/home\/articles\/qi-example\/creating-your-own-parser-component-for-spirit-qi\/","title":{"rendered":"Creating Your Own Parser Component for Spirit.Qi"},"content":{"rendered":"<p>Several people have been asking the question of how it would be possible to access the current iterator position from an semantic action. Different solutions have been proposed, all of them somehow abusing the predefined <em>Qi<\/em> directive <span style=\"font-family: courier new;\"><a href=\"http:\/\/www.boost.org\/doc\/libs\/1_41_0\/libs\/spirit\/doc\/html\/spirit\/qi\/reference\/directive\/raw.html\" target=\"_blank\">raw[]<\/a><\/span> which normally exposes as its attribute the pair of iterators pointing to the range in the input stream matched by the embedded parser. I thought this to be a nice incentive to write about how you can create your own parser components.<\/p>\n<p><em>Spirit<\/em> is a very modular library. It has been designed with full extensibility in mind, so writing additional components is fairly straight forward. Let\u2019s write a parser component for <em>Qi<\/em> called <span style=\"font-family: courier new;\">iter_pos<\/span> which exposes the current iterator position as its attribute. In the end we will have implemented a parser primitive usable in the same way as any of the predefined parsers, nicely integrated with <em>Qi\u2019s<\/em> predefined attribute propagation and merging rules.<\/p>\n<p>The new parser primitive will have the following expression semantics: <span style=\"font-family: courier new;\">iter_pos<\/span> will create a new parser which never matches anything while always succeeding (very much like the <span style=\"font-family: courier new;\"><a href=\"http:\/\/www.boost.org\/doc\/libs\/1_41_0\/libs\/spirit\/doc\/html\/spirit\/qi\/reference\/auxiliary\/eps.html\" target=\"_blank\">eps<\/a><\/span> parser). It\u2019s attribute type is <span style=\"font-family: courier new;\">iterator_type<\/span>, the type of the iterator used to access the underlying input stream.<\/p>\n<p>In order to create a custom parser component we need to perform 4 easy steps as outlined below.<\/p>\n<h4>Defining the Placeholder<\/h4>\n<p>The first step is to define the placeholder representing our new component when building parser expressions (that\u2019s the <span style=\"font-family: courier new;\">iter_pos<\/span><span style=\"font-family: trebuchet ms;\"> symbol). This can<\/span> can be done by using the predefined macro BOOST_SPIRIT_TERMINAL:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\"> namespace custom_parser { BOOST_SPIRIT_TERMINAL(iter_pos); } <\/pre>\n<p>which can be placed in any namespace. We assume our custom parser component will be created in the namespace <span style=\"font-family: Courier New;\">custom_parser<\/span>. This macro defines two types and a <span style=\"font-family: courier new;\">const<\/span> instance of one of the types. It essentially expands to:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nnamespace custom_parser\r\n{\r\n    namespace tag { struct iter_pos{}; } \/\/ tag identifying placeholder\r\n    typedef unspecified&lt;tag::iter_pos&gt; iter_pos_type;\r\n    iter_pos_type const iter_pos = {};   \/\/ placeholder itself\r\n}\r\n<\/pre>\n<p>We will use the type <span style=\"font-family: courier new;\">tag::iter_pos<\/span> later to identify our component, whereas the variable <span style=\"font-family: courier new;\">iter_pos<\/span> is the one to be used as the placeholder representing our parser component in more complex grammars.<\/p>\n<h4>Implementing the Enabler<\/h4>\n<p>The placeholder needs to be associated with the appropriate extension mechanism (<em>Spirit<\/em> has separate extension points for primitive parsers, parser directives, operators, etc.). We need to implement an enabler for the custom parser in a way allowing the library to recognize <span style=\"font-family: courier new;\">iter_pos<\/span> as a simple terminal only, as we don\u2019t want it to be valid if used as a directive, etc. The extension point used for simple terminals is <span style=\"font-family: courier new;\">boost::spirit::use_terminal&lt;&gt;<\/span>. We enable our custom parser by providing a specialization of this extension point, which has to be placed in the namespace <span style=\"font-family: Courier New;\">boost::spirit<\/span>:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nnamespace boost { namespace spirit\r\n{\r\n    \/\/ We want custom_parser::iter_pos to be usable as a terminal only,\r\n    \/\/ and only for parser expressions (qi::domain).\r\n    template &lt;&gt;\r\n    struct use_terminal&lt;qi::domain, custom_parser::tag::iter_pos&gt;\r\n      : mpl::true_\r\n    {};\r\n}}\r\n<\/pre>\n<p><em>Spirit<\/em> will pick up this template specialization whenever it sees our placeholder <span style=\"font-family: courier new;\">custom_parser::iter_pos<\/span> while compiling a parser expression (that\u2019s why the <span style=\"font-family: courier new;\">qi::domain<\/span>).<\/p>\n<h4>Implementing the Parser itself<\/h4>\n<p>So far, everything we saw was scaffolding allowing to integrate our new parser with the component framework of <em>Spirit<\/em>. This step describes the actual interface to be implemented in order to expose the required functionality as a parser component. Here is the full code, please note we are placing this code into our own namespace:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nnamespace custom_parser\r\n{\r\n    struct iter_pos_parser\r\n      : boost::spirit::qi::primitive_parser&lt;iter_pos_parser&gt;\r\n    {\r\n        \/\/ Define the attribute type exposed by this parser component\r\n        template &lt;typename Context, typename Iterator&gt;\r\n        struct attribute\r\n        {\r\n            typedef Iterator type;\r\n        };\r\n\r\n        \/\/ This function is called during the actual parsing process\r\n        template &lt;typename Iterator, typename Context\r\n          , typename Skipper, typename Attribute&gt;\r\n        bool parse(Iterator&amp; first, Iterator const&amp; last\r\n          , Context&amp;, Skipper const&amp; skipper, Attribute&amp; attr) const\r\n        {\r\n            boost::spirit::qi::skip_over(first, last, skipper);\r\n            boost::spirit::traits::assign_to(first, attr);\r\n            return true;\r\n        }\r\n\r\n        \/\/ This function is called during error handling to create\r\n        \/\/ a human readable string for the error context.\r\n        template &lt;typename Context&gt;\r\n        boost::spirit::info what(Context&amp;) const\r\n        {\r\n            return boost::spirit::info(&quot;iter_pos&quot;);\r\n        }\r\n    };\r\n}\r\n<\/pre>\n<p>The code above shows 4 notable details any parser component needs to implement, all of them are based on conceptual requirements for parsers (for more information see the Spirit documentation about this <a href=\"http:\/\/www.boost.org\/doc\/libs\/1_41_0\/libs\/spirit\/doc\/html\/spirit\/qi\/reference\/parser_concepts.html\" target=\"_blank\">here<\/a>).<\/p>\n<p>We derive our parser implementation from <span style=\"font-family: Courier New;\">boost::spirit::qi::primitive_parser&lt;&gt;<\/span> to associate our component with the correct parser concept, in this case a <span style=\"font-family: Courier New; color: #000000;\"><a href=\"http:\/\/www.boost.org\/doc\/libs\/1_41_0\/libs\/spirit\/doc\/html\/spirit\/qi\/reference\/parser_concepts\/primitiveparser.html\" target=\"_blank\">PrimitiveParser<\/a><\/span>.<\/p>\n<p>The embedded meta function <span style=\"font-family: Courier New;\">attribute<\/span> is a template which will be instantiated with a <span style=\"font-family: Courier New;\">Context<\/span> type (we can ignore this for our small example) and with the type of the <span style=\"font-family: Courier New;\">Iterator<\/span> the parser component is\u00a0being used with. It needs to have defined an embedded type definition <span style=\"font-family: Courier New;\">type<\/span>. This will be interpreted as the attribute type exposed by the parser component. Obviously, we expose the supplied <span style=\"font-family: Courier New;\">Iterator<\/span> type as our attribute.<\/p>\n<p>The member function <span style=\"font-family: Courier New;\">parse()<\/span> is where the actual parsing takes place. It will be invoked with a pair of iterators <span style=\"font-family: Courier New;\">(first, last)<\/span>, an instance of the Context (which we will ignore), the reference to the used skipper\u00a0instance <span style=\"font-family: Courier New;\">(skipper)<\/span>, and the reference to the attribute instance where the parser is supposed to store its result <span style=\"font-family: Courier New;\">(attr)<\/span>. If no skipper is used to invoke this parser the <span style=\"font-family: Courier New;\">Skipper<\/span> will be of the type <span style=\"font-family: Courier New;\">unused_type<\/span>. Similarily, if no attribute needs to be extracted the <span style=\"font-family: Courier New;\">Attribute<\/span> will be of the type <span style=\"font-family: Courier New;\">unused_type<\/span>. As we are designing a parser representing the <span style=\"font-family: Courier New; color: #000000;\"><a href=\"http:\/\/www.boost.org\/doc\/libs\/1_41_0\/libs\/spirit\/doc\/html\/spirit\/qi\/reference\/parser_concepts\/primitiveparser.html\" target=\"_blank\">PrimitiveParser<\/a><\/span> concept we need to perform a pre-skip operation on function entry by calling the function <span style=\"font-family: Courier New;\">qi::skip_over<\/span>. Our <span style=\"font-family: Courier New;\">iter_pos<\/span> parser is not performing any real parsing, but is supposed to return the current iterator position as it\u2019s attribute. We achieve this by assigning the iterator <span style=\"font-family: Courier New;\">first<\/span> (which pints to the current position in the input stream) to the attribute. For this assignment to take place we invoke the customization point <a href=\"http:\/\/www.boost.org\/doc\/libs\/1_41_0\/libs\/spirit\/doc\/html\/spirit\/advanced\/customize\/assign_to\/assign_to_attribute_from_value.html\" target=\"_blank\"><span style=\"font-family: Courier New;\">assign_to<\/span><\/a>, allowing us not to worry about whether\u00a0an attribute has been supplied or not. The parse function needs to return whether it succeeded, in our case it will always return <span style=\"font-family: Courier New;\">true<\/span>.<\/p>\n<p>The function <span style=\"font-family: Courier New;\">what()<\/span> is invoked by the library whenever a human readable string is needed identifying this parser. This is\u00a0most notably used for error handling, allowing to generate a nicely formatted description about the error context.<\/p>\n<p>This part is clearly the most complex step required to write a parser component, but I believe it is not too complex to understand. As mentioned above, <em>Spirit<\/em> has been designed with extensibility in mind, and we wanted to make it as simple as possible to be extended.<\/p>\n<h4>Instantiating the Parser<\/h4>\n<p>The last required piece of code is a parser generator function object which will be used by the library to instantiate a new instance of our parser component. Non-surprisingly, the name of the function object we need to specialize is <span style=\"font-family: Courier New;\">make_primitive<\/span>, and since we were using <span style=\"font-family: Courier New;\">qi::domain<\/span> in the first step above, we now need to place this specialization into the namespace <span style=\"font-family: Courier New;\">boost::spirit::qi<\/span>.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">namespace boost { namespace spirit { namespace qi\r\n{\r\n    \/\/ This is the factory function object invoked in order to create\r\n    \/\/ an instance of our iter_pos_parser.\r\n    template &lt;typename Modifiers&gt;\r\n    struct make_primitive&lt;custom_parser::tag::iter_pos, Modifiers&gt;\r\n    {\r\n        typedef custom_parser::iter_pos_parser result_type;\r\n\r\n        result_type operator()(unused_type, unused_type) const\r\n        {\r\n            return result_type();\r\n        }\r\n    };\r\n}}}\r\n<\/pre>\n<p>You can think of this function object as of a factory for our parser object. Our specialization is again based on the <span style=\"font-family: Courier New;\">tag::iter_pos<\/span> as defined above. This identifies our parser component. The function object <span style=\"font-family: Courier New;\">make_primitive<\/span> has to expose the type of the component it creates as its embedded type definition <span style=\"font-family: Courier New;\">result_type<\/span>. Additionally it exposes a function operator as the actual factory function. You probably already realized that <span style=\"font-family: Courier New;\">unused_type<\/span> is <em>Spirits<\/em> fancy way of saying: \u2018I don\u2019t care\u2019, and as we don\u2019t care about the two (required) parameters we use <span style=\"font-family: Courier New;\">unused_type<\/span> instead (ok, if you insist to know the details: the first parameter is a reference to the <span style=\"font-family: Courier New;\">iter_pos<\/span> placeholder instance resulting in this factory being invoked, and the second parameter is a reference to an object instance of the type <span style=\"font-family: Courier New;\">Modifiers<\/span>, which is needed only for directives like <a href=\"http:\/\/www.boost.org\/doc\/libs\/1_41_0\/libs\/spirit\/doc\/html\/spirit\/qi\/reference\/directive\/no_case.html\" target=\"_blank\">no_case[]<\/a>).<\/p>\n<h4>Using the <span style=\"font-family: Courier New;\">iter_pos<\/span> Parser Component<\/h4>\n<p>The only things left to show is how to use our newly created parser. As I mentioned before, the <span style=\"font-family: Courier New;\">iter_pos<\/span> component is usable like any other predefined parser.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n    std::string prefix, suffix;           \/\/ attributes receiving the\r\n    std::string::iterator position;       \/\/ parsed values\r\n\r\n    std::string input(&quot;prefix1234567&quot;);\r\n    std::string::iterator first = input.begin();\r\n    bool result =\r\n        qi::parse(first, input.end()\r\n          , +qi::alpha &gt;&gt; custom_parser::iter_pos &gt;&gt; +qi::digit\r\n          , prefix, position, suffix);\r\n<\/pre>\n<p>This code snippet utilizes the new parser component to retrieve the position in the input at which the letters end and the digits start. If the parse is successful, <span style=\"font-family: Courier New;\">prefix<\/span> will hold <span style=\"font-family: Courier New;\">\u201cprefix\u201d<\/span>, <span style=\"font-family: Courier New;\">suffix<\/span> will hold <span style=\"font-family: Courier New;\">\u201c1234567\u201d<\/span>, and <span style=\"font-family: Courier New;\">position<\/span> will point to the 7th character after the beginning of the input string.<\/p>\n<h4>Conclusion<\/h4>\n<p>The methodology as outlined above is applicable for simple components not exposing any additional functionality, parameterization, or member functions on its own. But since most of <em>Spirits<\/em> predefined parsers are written using this technique I assume it will allow you to go a long way before you need to apply more powerful tools. For now, I leave the description of how to implement one of those more complex parsers for a future article. Stay tuned!<\/p>\n<p>If you are interested in learning more about this topic, <a href=\"http:\/\/www.boost.org\/doc\/libs\/1_41_0\/libs\/spirit\/doc\/html\/spirit\/advanced\/indepth\/parsers_indepth.html\" target=\"_blank\">here<\/a> you can find more material about this in the main Spirit documentation. The complete source code for this example can be found in the <a href=\"http:\/\/www.boost.org\/\">Boost<\/a> SVN. It consists of two files, the header file <span style=\"font-family: Courier New;\"><a href=\"http:\/\/svn.boost.org\/svn\/boost\/trunk\/boost\/spirit\/repository\/home\/qi\/primitive\/iter_pos.hpp\" target=\"_blank\">iter_pos.hpp<\/a><\/span>, which is self contained and ready to be reused in your projects, and the example source file <span style=\"font-family: Courier New; color: #000000;\"><a href=\"http:\/\/svn.boost.org\/svn\/boost\/trunk\/libs\/spirit\/repository\/example\/qi\/iter_pos_parser.cpp\" target=\"_blank\">iter_pos_parser.cpp<\/a><\/span>.<\/p>\n<div class=\"sharedaddy sd-sharing-enabled\"><div class=\"robots-nocontent sd-block sd-social sd-social-icon-text sd-sharing\"><h3 class=\"sd-title\">Share this:<\/h3><div class=\"sd-content\"><ul><li><a href=\"#\" class=\"sharing-anchor sd-button share-more\"><span>Share<\/span><\/a><\/li><li class=\"share-end\"><\/li><\/ul><div class=\"sharing-hidden\"><div class=\"inner\" style=\"display: none;\"><ul><li class=\"share-facebook\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-facebook-567\" class=\"share-facebook sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/articles\/qi-example\/creating-your-own-parser-component-for-spirit-qi\/?share=facebook\" target=\"_blank\" title=\"Click to share on Facebook\" ><span>Facebook<\/span><\/a><\/li><li class=\"share-twitter\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-twitter-567\" class=\"share-twitter sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/articles\/qi-example\/creating-your-own-parser-component-for-spirit-qi\/?share=twitter\" target=\"_blank\" title=\"Click to share on Twitter\" ><span>Twitter<\/span><\/a><\/li><li class=\"share-end\"><\/li><li class=\"share-pinterest\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-pinterest-567\" class=\"share-pinterest sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/articles\/qi-example\/creating-your-own-parser-component-for-spirit-qi\/?share=pinterest\" target=\"_blank\" title=\"Click to share on Pinterest\" ><span>Pinterest<\/span><\/a><\/li><li class=\"share-linkedin\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-linkedin-567\" class=\"share-linkedin sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/articles\/qi-example\/creating-your-own-parser-component-for-spirit-qi\/?share=linkedin\" target=\"_blank\" title=\"Click to share on LinkedIn\" ><span>LinkedIn<\/span><\/a><\/li><li class=\"share-end\"><\/li><li class=\"share-reddit\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"\" class=\"share-reddit sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/articles\/qi-example\/creating-your-own-parser-component-for-spirit-qi\/?share=reddit\" target=\"_blank\" title=\"Click to share on Reddit\" ><span>Reddit<\/span><\/a><\/li><li class=\"share-tumblr\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"\" class=\"share-tumblr sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/articles\/qi-example\/creating-your-own-parser-component-for-spirit-qi\/?share=tumblr\" target=\"_blank\" title=\"Click to share on Tumblr\" ><span>Tumblr<\/span><\/a><\/li><li class=\"share-end\"><\/li><li class=\"share-end\"><\/li><\/ul><\/div><\/div><\/div><\/div><\/div>","protected":false},"excerpt":{"rendered":"<p>Several people have been asking the question of how it would be possible to access the current iterator position from an semantic action. Different solutions have been proposed, all of them somehow abusing the predefined Qi directive raw[] which normally exposes as its attribute the pair of iterators pointing to the range in the input [&hellip;]<\/p>\n<div class=\"sharedaddy sd-sharing-enabled\"><div class=\"robots-nocontent sd-block sd-social sd-social-icon-text sd-sharing\"><h3 class=\"sd-title\">Share this:<\/h3><div class=\"sd-content\"><ul><li><a href=\"#\" class=\"sharing-anchor sd-button share-more\"><span>Share<\/span><\/a><\/li><li class=\"share-end\"><\/li><\/ul><div class=\"sharing-hidden\"><div class=\"inner\" style=\"display: none;\"><ul><li class=\"share-facebook\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-facebook-567\" class=\"share-facebook sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/articles\/qi-example\/creating-your-own-parser-component-for-spirit-qi\/?share=facebook\" target=\"_blank\" title=\"Click to share on Facebook\" ><span>Facebook<\/span><\/a><\/li><li class=\"share-twitter\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-twitter-567\" class=\"share-twitter sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/articles\/qi-example\/creating-your-own-parser-component-for-spirit-qi\/?share=twitter\" target=\"_blank\" title=\"Click to share on Twitter\" ><span>Twitter<\/span><\/a><\/li><li class=\"share-end\"><\/li><li class=\"share-pinterest\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-pinterest-567\" class=\"share-pinterest sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/articles\/qi-example\/creating-your-own-parser-component-for-spirit-qi\/?share=pinterest\" target=\"_blank\" title=\"Click to share on Pinterest\" ><span>Pinterest<\/span><\/a><\/li><li class=\"share-linkedin\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-linkedin-567\" class=\"share-linkedin sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/articles\/qi-example\/creating-your-own-parser-component-for-spirit-qi\/?share=linkedin\" target=\"_blank\" title=\"Click to share on LinkedIn\" ><span>LinkedIn<\/span><\/a><\/li><li class=\"share-end\"><\/li><li class=\"share-reddit\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"\" class=\"share-reddit sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/articles\/qi-example\/creating-your-own-parser-component-for-spirit-qi\/?share=reddit\" target=\"_blank\" title=\"Click to share on Reddit\" ><span>Reddit<\/span><\/a><\/li><li class=\"share-tumblr\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"\" class=\"share-tumblr sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/articles\/qi-example\/creating-your-own-parser-component-for-spirit-qi\/?share=tumblr\" target=\"_blank\" title=\"Click to share on Tumblr\" ><span>Tumblr<\/span><\/a><\/li><li class=\"share-end\"><\/li><li class=\"share-end\"><\/li><\/ul><\/div><\/div><\/div><\/div><\/div>","protected":false},"author":3,"featured_media":0,"parent":384,"menu_order":4,"comment_status":"open","ping_status":"open","template":"article-page.php","meta":{"_s2mail":"","spay_email":""},"jetpack_shortlink":"https:\/\/wp.me\/PIHdZ-99","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/pages\/567"}],"collection":[{"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/comments?post=567"}],"version-history":[{"count":21,"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/pages\/567\/revisions"}],"predecessor-version":[{"id":583,"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/pages\/567\/revisions\/583"}],"up":[{"embeddable":true,"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/pages\/384"}],"wp:attachment":[{"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/media?parent=567"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}