{"id":66,"date":"2015-05-29T18:35:37","date_gmt":"2015-05-29T23:35:37","guid":{"rendered":"http:\/\/www.playwithlua.com\/?p=66"},"modified":"2015-05-29T18:45:42","modified_gmt":"2015-05-29T23:45:42","slug":"making-a-toy-programming-language-in-lua-part-1","status":"publish","type":"post","link":"http:\/\/www.playwithlua.com\/?p=66","title":{"rendered":"Making a toy programming language in Lua, part 1"},"content":{"rendered":"<p>In this post, and the following posts in this series, I aim to fix something that&#8217;s bothered me for a while: writing a parser in Lua isn&#8217;t very approachable. In C you have the excellent chapter in <em><a onclick=\"javascript:pageTracker._trackPageview('\/outgoing\/amzn.to\/1HMIXJQ');\"  href=\"http:\/\/amzn.to\/1HMIXJQ\">The Unix Programming Environment<\/a><\/em> (probably the best book on programming ever written) about how to use Lex and Yacc. For Ruby there&#8217;s the excellent Dhaka gem, as well as Racc, both of which work a lot like Yacc \/ Bison. There&#8217;s also Antlr, which seems to speak to every language <em>except<\/em> Lua.<\/p>\n<p>Meanwhile Lua has <a onclick=\"javascript:pageTracker._trackPageview('\/outgoing\/www.inf.puc-rio.br\/~roberto\/lpeg\/');\"  href=\"http:\/\/www.inf.puc-rio.br\/~roberto\/lpeg\/\">LPeg<\/a>, which is used nothing like Yacc, and tutorials are thin on the ground. So, I want to change that. This is going to be about how to make a toy programming language in Lua, in three parts. I&#8217;m going to loosely follow what the Lex \/ Yacc chapters of <em><a onclick=\"javascript:pageTracker._trackPageview('\/outgoing\/amzn.to\/1HMIXJQ');\"  href=\"http:\/\/amzn.to\/1HMIXJQ\">The Unix Programming Environment<\/a><\/em> do, and we&#8217;ll end up with the same language.<\/p>\n<p>Let&#8217;s begin.<br \/>\n<!--more--><\/p>\n<h2>Getting started with LPeg<\/h2>\n<p>Covering how to build and install LPeg is going to be impossible to do for every system, and out of scope anyway, so let&#8217;s just assume you have already installed it somehow. You can verify that you have it like this:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">lpeg <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #0000aa;\">require<\/span> <span style=\"color: #ff6666;\">'lpeg'<\/span>\n<span style=\"color: #0000aa;\">print<\/span><span style=\"color: #66cc66;\">&#40;<\/span> <span style=\"color: #0000aa;\">type<\/span><span style=\"color: #66cc66;\">&#40;<\/span>lpeg<span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #ff6666;\">'table'<\/span><span style=\"color: #66cc66;\">&#41;<\/span><\/pre><\/div><\/div><\/div>\n\n<p>Now that we have it loaded, let&#8217;s start making a parser. Parsers are made up of <em>patterns<\/em>, which are objects (userdata) that <em>match<\/em> certain things in strings. Each pattern has a set of things that it will match, and a <code>match<\/code> method that takes a string and returns whether it matches or not.<\/p>\n<p>The simplest possible pattern is one that matches a literal string:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">p <span style=\"color: #66cc66;\">=<\/span> lpeg<span style=\"color: #66cc66;\">.<\/span>P<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;apple&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span><\/pre><\/div><\/div><\/div>\n\n<p>This pattern will match the string &#8220;apple&#8221; and nothing else:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">p<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;bob&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #808080; font-style: italic;\">-- nil<\/span>\np<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;apple&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #808080; font-style: italic;\">-- 6<\/span><\/pre><\/div><\/div><\/div>\n\n<p>We get a nil back if it doesn&#8217;t match, and a 6 back if it does, because 6 is the index in the string immediately following the match. This pattern will also match anything that starts with &#8220;apple&#8221;:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">p<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;appletree&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #808080; font-style: italic;\">-- 6<\/span><\/pre><\/div><\/div><\/div>\n\n<p>It knows how to parse &#8220;apple&#8221; but what comes after it it doesn&#8217;t match, so it leaves it alone.<\/p>\n<p>You can also combine patterns together:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">p <span style=\"color: #66cc66;\">=<\/span> lpeg<span style=\"color: #66cc66;\">.<\/span>P<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;apple&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span> lpeg<span style=\"color: #66cc66;\">.<\/span>P<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;tree&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span><\/pre><\/div><\/div><\/div>\n\n<p>&#8220;Multiplying&#8221; two patterns means &#8220;match this pattern, followed by this one.&#8221; So, this would match &#8220;apple&#8221; followed by &#8220;tree&#8221;. &#8220;Adding&#8221; them means to match either one or the other, so this matches either &#8220;apple&#8221; or &#8220;tree&#8221;:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">p <span style=\"color: #66cc66;\">=<\/span> lpeg<span style=\"color: #66cc66;\">.<\/span>P<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;apple&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">+<\/span> lpeg<span style=\"color: #66cc66;\">.<\/span>P<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;tree&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\np<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'apple'<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #808080; font-style: italic;\">-- 6<\/span>\np<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'tree'<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #808080; font-style: italic;\">-- 5<\/span>\np<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'bob'<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #808080; font-style: italic;\">-- nil<\/span>\np<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'appletree'<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #808080; font-style: italic;\">-- 6<\/span><\/pre><\/div><\/div><\/div>\n\n<p>The last one matches because the &#8220;tree&#8221; part is treated as unrecognized input, just as above. If we want it to not match, we have to say &#8220;match &#8216;apple&#8217; or &#8216;tree&#8217; followed by the end of the string.&#8221; We can do that easily, because <code>lpeg.P<\/code> can also take a number, and interprets it as &#8220;match exactly this many characters, no matter what they are.&#8221; If you pass it -1, it matches the end of the string:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">p <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #66cc66;\">&#40;<\/span>lpeg<span style=\"color: #66cc66;\">.<\/span>P<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;apple&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">+<\/span> lpeg<span style=\"color: #66cc66;\">.<\/span>P<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;tree&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span> lpeg<span style=\"color: #66cc66;\">.<\/span>P<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #66cc66;\">-<\/span><span style=\"color: #cc66cc;\">1<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\np<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'appletree'<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #808080; font-style: italic;\">-- nil<\/span><\/pre><\/div><\/div><\/div>\n\n<p>Finally, &#8220;exponentiating&#8221; a pattern with a number matches repetitions of that pattern:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\"><span style=\"color: #808080; font-style: italic;\">-- match at least 3 'a' characters, followed by a 'b', then end of string:<\/span>\np <span style=\"color: #66cc66;\">=<\/span> lpeg<span style=\"color: #66cc66;\">.<\/span>P<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;a&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">^<\/span><span style=\"color: #cc66cc;\">3<\/span> <span style=\"color: #66cc66;\">*<\/span> <span style=\"color: #ff6666;\">&quot;b&quot;<\/span> <span style=\"color: #66cc66;\">*<\/span> <span style=\"color: #66cc66;\">-<\/span><span style=\"color: #cc66cc;\">1<\/span>\np<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'ab'<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #808080; font-style: italic;\">-- nil<\/span>\np<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'aaab'<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #808080; font-style: italic;\">-- 5<\/span>\np<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'aaabc'<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #808080; font-style: italic;\">-- nil<\/span><\/pre><\/div><\/div><\/div>\n\n<p>(note that we can use literal strings and numbers, and it&#8217;s just as if we called <code>lpeg.P<\/code>.<\/p>\n<h2>More complicated patterns<\/h2>\n<p>So far there&#8217;s nothing we can&#8217;t do with ordinary string expressions. But, patterns can be combined in other ways. Here&#8217;s a pattern that matches a number:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">number <span style=\"color: #66cc66;\">=<\/span> lpeg<span style=\"color: #66cc66;\">.<\/span>P<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'-'<\/span><span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">^-<\/span><span style=\"color: #cc66cc;\">1<\/span> <span style=\"color: #66cc66;\">*<\/span>\n         lpeg<span style=\"color: #66cc66;\">.<\/span>R<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'09'<\/span><span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">^<\/span><span style=\"color: #cc66cc;\">0<\/span> <span style=\"color: #66cc66;\">*<\/span>\n         <span style=\"color: #66cc66;\">&#40;<\/span>\n             lpeg<span style=\"color: #66cc66;\">.<\/span>P<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'.'<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span>\n             lpeg<span style=\"color: #66cc66;\">.<\/span>R<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'09'<\/span><span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">^<\/span><span style=\"color: #cc66cc;\">0<\/span>\n         <span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">^-<\/span><span style=\"color: #cc66cc;\">1<\/span> <span style=\"color: #66cc66;\">*<\/span>\n         <span style=\"color: #66cc66;\">-<\/span><span style=\"color: #cc66cc;\">1<\/span><\/pre><\/div><\/div><\/div>\n\n<p>I&#8217;ve split it into multiple lines to make it clearer. Let&#8217;s walk through this: we start by having &#8220;-&#8221; matched at most 1 time (exponentiating by a negative means &#8220;repeated at most,&#8221; exponentiating by a positive or 0 means &#8220;repeated at least&#8221;). This allows us to have negative numbers. Then, we have at least 0 repetitions of <code>lpeg.R('09')<\/code>: this is a &#8220;range&#8221; pattern, which matches any character between the two, so, any digit. This is the integer part of the number.<\/p>\n<p>Then there&#8217;s a block wrapped up in parentheses: <code>( ... )^-1<\/code>. Again, we&#8217;re repeating this portion at most one time, and that portion is a &#8220;.&#8221; followed by another series of digits. Finally, we match end-of-string.<\/p>\n<p>So, testing this, we see that it matches various numbers:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">number<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'53'<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\nnumber<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'-17'<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\nnumber<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'5.02'<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\nnumber<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'.3'<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\nnumber<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'7.'<\/span><span style=\"color: #66cc66;\">&#41;<\/span><\/pre><\/div><\/div><\/div>\n\n<h2>Captures<\/h2>\n<p>Up until now, we&#8217;ve been concerned with seeing whether a given string matches a pattern. But that&#8217;s something we could do (with this example anyway) using a regular expression. In order to make any sort of useful parser we&#8217;ll need to extract portions of the string, while recognizing what they are. In this case, we&#8217;ll want to extract the integer part of the number, the fractional part, and whether there&#8217;s a negative sign.<\/p>\n<p>We do this with an LPeg concept called <em>captures<\/em>. The simplest capture is to just have the pattern return, instead of a string index, some portion of the string:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">number <span style=\"color: #66cc66;\">=<\/span> lpeg<span style=\"color: #66cc66;\">.<\/span>C<span style=\"color: #66cc66;\">&#40;<\/span> lpeg<span style=\"color: #66cc66;\">.<\/span>P<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'-'<\/span><span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">^-<\/span><span style=\"color: #cc66cc;\">1<\/span> <span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span>\n         lpeg<span style=\"color: #66cc66;\">.<\/span>C<span style=\"color: #66cc66;\">&#40;<\/span> lpeg<span style=\"color: #66cc66;\">.<\/span>R<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'09'<\/span><span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">^<\/span><span style=\"color: #cc66cc;\">0<\/span> <span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span>\n         <span style=\"color: #66cc66;\">&#40;<\/span>\n             lpeg<span style=\"color: #66cc66;\">.<\/span>P<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'.'<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span>\n             lpeg<span style=\"color: #66cc66;\">.<\/span>C<span style=\"color: #66cc66;\">&#40;<\/span> lpeg<span style=\"color: #66cc66;\">.<\/span>R<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'09'<\/span><span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">^<\/span><span style=\"color: #cc66cc;\">0<\/span> <span style=\"color: #66cc66;\">&#41;<\/span>\n         <span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">^-<\/span><span style=\"color: #cc66cc;\">1<\/span> <span style=\"color: #66cc66;\">*<\/span>\n         <span style=\"color: #66cc66;\">-<\/span><span style=\"color: #cc66cc;\">1<\/span><\/pre><\/div><\/div><\/div>\n\n<p>You&#8217;ll notice we&#8217;ve wrapped three portions of our pattern in <code>lpeg.C<\/code>. This creates a capture, by adding whatever is wrapped in <code>lpeg.C<\/code> to the return values of <code>match<\/code>. It makes more sense if you try it:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">sign<span style=\"color: #66cc66;\">,<\/span> ipart<span style=\"color: #66cc66;\">,<\/span> fpart <span style=\"color: #66cc66;\">=<\/span> number<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;-37.7&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span><\/pre><\/div><\/div><\/div>\n\n<p><code>sign<\/code>, <code>ipart<\/code>, and <code>fpart<\/code> are now &#8220;-&#8220;, &#8220;37&#8221;, and &#8220;7&#8221; respectively: instead of returning 6 (the index right after the match), a pattern with captures returns the captures.<\/p>\n<p>The other handy thing we can do here is to use a <em>function capture:<\/em> &#8220;dividing&#8221; the pattern by a function will pass all the captures to that function, and then return what the function returns:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\"><span style=\"color: #aa9900; font-weight: bold;\">function<\/span> parse_num<span style=\"color: #66cc66;\">&#40;<\/span>sign<span style=\"color: #66cc66;\">,<\/span> ipart<span style=\"color: #66cc66;\">,<\/span> fpart<span style=\"color: #66cc66;\">&#41;<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> <span style=\"color: #66cc66;\">&#123;<\/span> negative <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #66cc66;\">&#40;<\/span>sign<span style=\"color: #66cc66;\">==<\/span><span style=\"color: #ff6666;\">'-'<\/span><span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">,<\/span>\n             ipart <span style=\"color: #66cc66;\">=<\/span> ipart<span style=\"color: #66cc66;\">,<\/span>\n             fpart <span style=\"color: #66cc66;\">=<\/span> fpart <span style=\"color: #66cc66;\">&#125;<\/span>\n<span style=\"color: #aa9900; font-weight: bold;\">end<\/span>\n&nbsp;\nnumber <span style=\"color: #66cc66;\">=<\/span> lpeg<span style=\"color: #66cc66;\">.<\/span>C<span style=\"color: #66cc66;\">&#40;<\/span> lpeg<span style=\"color: #66cc66;\">.<\/span>P<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'-'<\/span><span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">^-<\/span><span style=\"color: #cc66cc;\">1<\/span> <span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span>\n         lpeg<span style=\"color: #66cc66;\">.<\/span>C<span style=\"color: #66cc66;\">&#40;<\/span> lpeg<span style=\"color: #66cc66;\">.<\/span>R<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'09'<\/span><span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">^<\/span><span style=\"color: #cc66cc;\">0<\/span> <span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span>\n         <span style=\"color: #66cc66;\">&#40;<\/span>\n             lpeg<span style=\"color: #66cc66;\">.<\/span>P<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'.'<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span>\n             lpeg<span style=\"color: #66cc66;\">.<\/span>C<span style=\"color: #66cc66;\">&#40;<\/span> lpeg<span style=\"color: #66cc66;\">.<\/span>R<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'09'<\/span><span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">^<\/span><span style=\"color: #cc66cc;\">0<\/span> <span style=\"color: #66cc66;\">&#41;<\/span>\n         <span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">^-<\/span><span style=\"color: #cc66cc;\">1<\/span> <span style=\"color: #66cc66;\">*<\/span>\n         <span style=\"color: #66cc66;\">-<\/span><span style=\"color: #cc66cc;\">1<\/span> <span style=\"color: #66cc66;\">\/<\/span>\n         parse_num\n&nbsp;\nnumber<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;-7.2&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #808080; font-style: italic;\">-- {negative=true, ipart=&quot;7&quot;, fpart=&quot;2&quot;}<\/span><\/pre><\/div><\/div><\/div>\n\n<p>Or, we could do it a little more simply by using <code>tonumber<\/code>:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">number <span style=\"color: #66cc66;\">=<\/span> lpeg<span style=\"color: #66cc66;\">.<\/span>C<span style=\"color: #66cc66;\">&#40;<\/span>\n           lpeg<span style=\"color: #66cc66;\">.<\/span>P<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'-'<\/span><span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">^-<\/span><span style=\"color: #cc66cc;\">1<\/span> <span style=\"color: #66cc66;\">*<\/span>\n           lpeg<span style=\"color: #66cc66;\">.<\/span>R<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'09'<\/span><span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">^<\/span><span style=\"color: #cc66cc;\">0<\/span> <span style=\"color: #66cc66;\">*<\/span>\n           <span style=\"color: #66cc66;\">&#40;<\/span>\n               lpeg<span style=\"color: #66cc66;\">.<\/span>P<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'.'<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span>\n               lpeg<span style=\"color: #66cc66;\">.<\/span>R<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'09'<\/span><span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">^<\/span><span style=\"color: #cc66cc;\">0<\/span>\n           <span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">^-<\/span><span style=\"color: #cc66cc;\">1<\/span> <span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">\/<\/span>\n         <span style=\"color: #0000aa;\">tonumber<\/span>\n&nbsp;\nnumber<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;-7.2&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #808080; font-style: italic;\">-- -7.2<\/span><\/pre><\/div><\/div><\/div>\n\n<p>This will capture the whole thing at once, and feed it to a function that happens to be in the standard library that turns a string into a number.<\/p>\n<h2>Parsing simple expressions<\/h2>\n<p>Let&#8217;s make a calculator. For this first step, we&#8217;ll parse simple expressions consisting of two numbers and an operator: &#8220;2+2&#8221;, &#8220;3*-7.5&#8221;, and the like. Here&#8217;s a pattern that matches an expression, using the <code>number<\/code> pattern from above:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">spc <span style=\"color: #66cc66;\">=<\/span> lpeg<span style=\"color: #66cc66;\">.<\/span>S<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot; <span style=\"color: #000099; font-weight: bold;\">\\t<\/span><span style=\"color: #000099; font-weight: bold;\">\\n<\/span>&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">^<\/span><span style=\"color: #cc66cc;\">0<\/span>\nexpr <span style=\"color: #66cc66;\">=<\/span> spc <span style=\"color: #66cc66;\">*<\/span> number <span style=\"color: #66cc66;\">*<\/span> spc <span style=\"color: #66cc66;\">*<\/span> lpeg<span style=\"color: #66cc66;\">.<\/span>C<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'+'<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span> spc <span style=\"color: #66cc66;\">*<\/span> number <span style=\"color: #66cc66;\">*<\/span> spc <span style=\"color: #66cc66;\">*<\/span> <span style=\"color: #66cc66;\">-<\/span><span style=\"color: #cc66cc;\">1<\/span> <span style=\"color: #66cc66;\">+<\/span>\n       spc <span style=\"color: #66cc66;\">*<\/span> number <span style=\"color: #66cc66;\">*<\/span> spc <span style=\"color: #66cc66;\">*<\/span> lpeg<span style=\"color: #66cc66;\">.<\/span>C<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'-'<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span> spc <span style=\"color: #66cc66;\">*<\/span> number <span style=\"color: #66cc66;\">*<\/span> spc <span style=\"color: #66cc66;\">*<\/span> <span style=\"color: #66cc66;\">-<\/span><span style=\"color: #cc66cc;\">1<\/span> <span style=\"color: #66cc66;\">+<\/span>\n       spc <span style=\"color: #66cc66;\">*<\/span> number <span style=\"color: #66cc66;\">*<\/span> spc <span style=\"color: #66cc66;\">*<\/span> lpeg<span style=\"color: #66cc66;\">.<\/span>C<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'*'<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span> spc <span style=\"color: #66cc66;\">*<\/span> number <span style=\"color: #66cc66;\">*<\/span> spc <span style=\"color: #66cc66;\">*<\/span> <span style=\"color: #66cc66;\">-<\/span><span style=\"color: #cc66cc;\">1<\/span> <span style=\"color: #66cc66;\">+<\/span>\n       spc <span style=\"color: #66cc66;\">*<\/span> number <span style=\"color: #66cc66;\">*<\/span> spc <span style=\"color: #66cc66;\">*<\/span> lpeg<span style=\"color: #66cc66;\">.<\/span>C<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'\/'<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span> spc <span style=\"color: #66cc66;\">*<\/span> number <span style=\"color: #66cc66;\">*<\/span> spc <span style=\"color: #66cc66;\">*<\/span> <span style=\"color: #66cc66;\">-<\/span><span style=\"color: #cc66cc;\">1<\/span><\/pre><\/div><\/div><\/div>\n\n<p>This has a few things in it we haven&#8217;t explained. First, the <code>spc<\/code> pattern I&#8217;ve written will match whitespace but create no captures, so we can put random whitespace in the string to separate tokens. The <code>spc<\/code> pattern uses <code>lpeg.S<\/code>, which means &#8220;match any one of the characters in this string.&#8221;<\/p>\n<p>If we feed a string to this, we&#8217;ll see it capture the two numbers and the operator:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">expr<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;2 * 3&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #808080; font-style: italic;\">-- 2, '*', 3<\/span><\/pre><\/div><\/div><\/div>\n\n<p>Now it&#8217;s easy enough to make a function to evaluate these:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\"><span style=\"color: #aa9900; font-weight: bold;\">function<\/span> eval<span style=\"color: #66cc66;\">&#40;<\/span>num1<span style=\"color: #66cc66;\">,<\/span> operator<span style=\"color: #66cc66;\">,<\/span> num2<span style=\"color: #66cc66;\">&#41;<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">if<\/span> operator <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #ff6666;\">'+'<\/span> <span style=\"color: #aa9900; font-weight: bold;\">then<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> num1 <span style=\"color: #66cc66;\">+<\/span> num2\n    <span style=\"color: #aa9900; font-weight: bold;\">elseif<\/span> operator <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #ff6666;\">'-'<\/span> <span style=\"color: #aa9900; font-weight: bold;\">then<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> num1 <span style=\"color: #66cc66;\">-<\/span> num2\n    <span style=\"color: #aa9900; font-weight: bold;\">elseif<\/span> operator <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #ff6666;\">'*'<\/span> <span style=\"color: #aa9900; font-weight: bold;\">then<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> num1 <span style=\"color: #66cc66;\">*<\/span> num2\n    <span style=\"color: #aa9900; font-weight: bold;\">elseif<\/span> operator <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #ff6666;\">'\/'<\/span> <span style=\"color: #aa9900; font-weight: bold;\">then<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> num1 <span style=\"color: #66cc66;\">\/<\/span> num2\n    <span style=\"color: #aa9900; font-weight: bold;\">else<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> num1\n    <span style=\"color: #aa9900; font-weight: bold;\">end<\/span>\n<span style=\"color: #aa9900; font-weight: bold;\">end<\/span><\/pre><\/div><\/div><\/div>\n\n<p>And then, a REPL:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\"><span style=\"color: #aa9900; font-weight: bold;\">function<\/span> repl<span style=\"color: #66cc66;\">&#40;<\/span>file<span style=\"color: #66cc66;\">&#41;<\/span>\n    file <span style=\"color: #66cc66;\">=<\/span> file <span style=\"color: #aa9900; font-weight: bold;\">or<\/span> <span style=\"color: #0000aa;\">io.input<\/span><span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n    parser <span style=\"color: #66cc66;\">=<\/span> expr <span style=\"color: #66cc66;\">\/<\/span> eval\n    <span style=\"color: #aa9900; font-weight: bold;\">for<\/span> line <span style=\"color: #aa9900; font-weight: bold;\">in<\/span> file<span style=\"color: #66cc66;\">:<\/span>lines<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #aa9900; font-weight: bold;\">do<\/span>\n        <span style=\"color: #0000aa;\">print<\/span><span style=\"color: #66cc66;\">&#40;<\/span>parser<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span>line<span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">end<\/span>\n<span style=\"color: #aa9900; font-weight: bold;\">end<\/span><\/pre><\/div><\/div><\/div>\n\n<p>Call this on a filehandle (defaults to stdin) to read, evaluate, and print simple <code>expr<\/code>s.<\/p>\n<h2>Recursive grammars<\/h2>\n<p>Of course, these are <em>very<\/em> simple expressions: two terms and one operator. It would be a lot better if we could put in more complex expressions like &#8220;2 * 3 + 5&#8221;. We can do that by making the pattern recursive: an <code>expr<\/code> can be defined as a pattern that contains another <code>expr<\/code>. But in order to do that, we need to use something LPeg calls a <em>grammar:<\/em><\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">expr <span style=\"color: #66cc66;\">=<\/span> lpeg<span style=\"color: #66cc66;\">.<\/span>P<span style=\"color: #66cc66;\">&#123;<\/span>\n    <span style=\"color: #ff6666;\">&quot;EXPR&quot;<\/span><span style=\"color: #66cc66;\">;<\/span>\n    EXPR <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #66cc66;\">&#40;<\/span> lpeg<span style=\"color: #66cc66;\">.<\/span>V<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;TERM&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span> lpeg<span style=\"color: #66cc66;\">.<\/span>C<span style=\"color: #66cc66;\">&#40;<\/span> lpeg<span style=\"color: #66cc66;\">.<\/span>S<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'+-'<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span> lpeg<span style=\"color: #66cc66;\">.<\/span>V<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;EXPR&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">+<\/span>\n             lpeg<span style=\"color: #66cc66;\">.<\/span>V<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;TERM&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">\/<\/span> eval<span style=\"color: #66cc66;\">,<\/span>\n    TERM <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #66cc66;\">&#40;<\/span> lpeg<span style=\"color: #66cc66;\">.<\/span>V<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;FACT&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span> lpeg<span style=\"color: #66cc66;\">.<\/span>C<span style=\"color: #66cc66;\">&#40;<\/span> lpeg<span style=\"color: #66cc66;\">.<\/span>S<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'\/*'<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span> lpeg<span style=\"color: #66cc66;\">.<\/span>V<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;TERM&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">+<\/span>\n             lpeg<span style=\"color: #66cc66;\">.<\/span>V<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;FACT&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">\/<\/span> eval<span style=\"color: #66cc66;\">,<\/span>\n    FACT <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #66cc66;\">&#40;<\/span> spc <span style=\"color: #66cc66;\">*<\/span> <span style=\"color: #ff6666;\">&quot;(&quot;<\/span> <span style=\"color: #66cc66;\">*<\/span> lpeg<span style=\"color: #66cc66;\">.<\/span>V<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;EXPR&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span> <span style=\"color: #ff6666;\">&quot;)&quot;<\/span> <span style=\"color: #66cc66;\">*<\/span> spc <span style=\"color: #66cc66;\">+<\/span>\n             number <span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">\/<\/span> eval\n<span style=\"color: #66cc66;\">&#125;<\/span><\/pre><\/div><\/div><\/div>\n\n<p>A grammar is made by passing a table to <code>lpeg.P<\/code>. The first element in the table is the name of a <em>nonterminal,<\/em> and it&#8217;s what we start by trying to match. All the rest define nonterminals. In order to reference a nonterminal, we use <code>lpeg.V<\/code>.<\/p>\n<p>So, this says:<\/p>\n<blockquote><p>\nStart trying to match an EXPR. An EXPR is either a TERM plus-or-minus an EXPR, or it&#8217;s just a TERM by itself. When you see an EXPR, send it to <code>eval<\/code>.<\/p>\n<p>A TERM is either a FACT multiply-or-divide a TERM, or a FACT by itself. Send these to <code>eval<\/code> also.<\/p>\n<p>A FACT is either an EXPR in parentheses, or a number. These, too, get sent to <code>eval<\/code>.\n<\/p><\/blockquote>\n<p>When we match a string like &#8220;2 * (3 + 4)&#8221;, LPeg will parse it like this:<\/p>\n<img src=\"http:\/\/www.playwithlua.com\/wp-content\/tfo-graphviz\/822a75d447e4f7a19c5935e47ff7ac8b.png\" class=\"graphviz\" \/>\n<p>The reason we separate out EXPR, TERM, and FACT (expression, term, and factor) is that LPeg has no other way of assigning operator precedence: if an EXPR&#8217;s middle operator could be either a plus or a multiply, then &#8220;2+3*4&#8221; would generate the same tree structure as &#8220;2*3+4&#8221;. So, we have some extra internal nodes in there. If we wanted, we could eliminate a lot of them by having the rules not be recursive: EXPR could be a series of TERMs with operators, instead of a single TERM followed by an EXPR. That&#8217;s what the LPeg example has. However, I&#8217;m trying to closely follow what <em>The Unix Programming Environment<\/em> does, and demonstrate that recursion works.<\/p>\n<h2>Trying it out<\/h2>\n<p>Here are a few test cases that should prove this is parsing correctly:<\/p>\n<pre>\r\n1\r\n(2)\r\n1+2\r\n2*3\r\n2*3+1\r\n2*(3+1)\r\n<\/pre>\n<p>If you try this out using the same <code>repl<\/code> function as before you&#8217;ll see they all work.<\/p>\n<h2>Next steps<\/h2>\n<p>At this point we have something about like the first version of the calculator in <em>The Unix Programming Environment.<\/em> The next step, which will be in the next post, will be to add variables and control structures.<\/p>\n<p>As always, you can get the code from this post (for the final version of this parser) <a onclick=\"javascript:pageTracker._trackPageview('\/outgoing\/gist.github.com\/randrews\/3348d96cd35e5b154741');\"  href=\"https:\/\/gist.github.com\/randrews\/3348d96cd35e5b154741\">here<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this post, and the following posts in this series, I aim to fix something that&#8217;s bothered me for a while: writing a parser in Lua isn&#8217;t very approachable. In C you have the excellent chapter in The Unix Programming Environment (probably the best book on programming ever written) about how to use Lex and [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[],"_links":{"self":[{"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=\/wp\/v2\/posts\/66"}],"collection":[{"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=66"}],"version-history":[{"count":0,"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=\/wp\/v2\/posts\/66\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=66"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=66"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=66"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}