{"id":68,"date":"2015-06-05T09:46:14","date_gmt":"2015-06-05T14:46:14","guid":{"rendered":"http:\/\/www.playwithlua.com\/?p=68"},"modified":"2015-06-05T09:46:14","modified_gmt":"2015-06-05T14:46:14","slug":"making-a-toy-programming-language-in-lua-part-2","status":"publish","type":"post","link":"http:\/\/www.playwithlua.com\/?p=68","title":{"rendered":"Making a toy programming language in Lua, part 2"},"content":{"rendered":"<p>This is part two of my series on writing a toy programming language using <a onclick=\"javascript:pageTracker._trackPageview('\/outgoing\/www.inf.puc-rio.br\/~roberto\/lpeg\/');\"  href=\"http:\/\/www.inf.puc-rio.br\/~roberto\/lpeg\/\">LPeg<\/a>. You should first read part one <a href=\"http:\/\/www.playwithlua.com\/?p=66\">here<\/a>.<\/p>\n<p>Last time, we made an interpreter for a simple calculator: it would read in mathematical expressions and evaluate them, printing the result. This time, we&#8217;re going to add two new features: variables and arrays. First though, we&#8217;ll refactor our parser some.<br \/>\n<!--more--><\/p>\n<h2>Cleaning up the parser<\/h2>\n<p>Here&#8217;s the grammar we ended up with last time:<\/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>\n&nbsp;\nnumber <span style=\"color: #66cc66;\">=<\/span> spc <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> 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> spc <span style=\"color: #66cc66;\">\/<\/span>\n         <span style=\"color: #0000aa;\">tonumber<\/span>\n&nbsp;\nexpr <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>The first annoying thing here is that &#8220;lpeg&#8221; is repeated everywhere. If we add the <code>lpeg<\/code> table to our environment, we won&#8217;t have to do that:<\/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: #0000aa;\">setmetatable<\/span><span style=\"color: #66cc66;\">&#40;<\/span>_ENV<span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #66cc66;\">&#123;<\/span> __index<span style=\"color: #66cc66;\">=<\/span>lpeg <span style=\"color: #66cc66;\">&#125;<\/span><span style=\"color: #66cc66;\">&#41;<\/span><\/pre><\/div><\/div><\/div>\n\n<p>Next is whitespace being matched everywhere. Let&#8217;s try to remove a few of those: we&#8217;ll say that most patterns can be <em>followed<\/em> by <code>spc<\/code> but that whitespace before them should be matched by whatever token preceded them (in most cases). We&#8217;ll also factor out a few helper patterns like <code>digit<\/code>.<\/p>\n<p>Finally, let&#8217;s change where we call <code>eval<\/code>. Right now each nonterminal is sent to <code>eval<\/code>, instead let&#8217;s specify that each <em>production<\/em> of a nonterminal will be sent there. That will make it easier to call different functions for different productions later: if we want to send EXPRs that are just one term to a different function than EXPRs that recurse, say.<\/p>\n<p>With all those changes, the new grammar looks like this:<\/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> 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>\n&nbsp;\ndigit <span style=\"color: #66cc66;\">=<\/span> R<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'09'<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\nnumber <span style=\"color: #66cc66;\">=<\/span> C<span style=\"color: #66cc66;\">&#40;<\/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                digit<span style=\"color: #66cc66;\">^<\/span><span style=\"color: #cc66cc;\">0<\/span> <span style=\"color: #66cc66;\">*<\/span>\n                <span style=\"color: #66cc66;\">&#40;<\/span> P<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'.'<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span> digit<span style=\"color: #66cc66;\">^<\/span><span style=\"color: #cc66cc;\">0<\/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> <span style=\"color: #0000aa;\">tonumber<\/span> <span style=\"color: #66cc66;\">*<\/span> spc\n&nbsp;\nlparen <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #ff6666;\">&quot;(&quot;<\/span> <span style=\"color: #66cc66;\">*<\/span> spc\nrparen <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #ff6666;\">&quot;)&quot;<\/span> <span style=\"color: #66cc66;\">*<\/span> spc\nexpr_op <span style=\"color: #66cc66;\">=<\/span> C<span style=\"color: #66cc66;\">&#40;<\/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> spc\nterm_op <span style=\"color: #66cc66;\">=<\/span> C<span style=\"color: #66cc66;\">&#40;<\/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> spc\n&nbsp;\nexpr <span style=\"color: #66cc66;\">=<\/span> spc <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>\n        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> expr_op <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> eval <span style=\"color: #66cc66;\">+<\/span>\n        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> eval<span style=\"color: #66cc66;\">,<\/span>\n    TERM <span style=\"color: #66cc66;\">=<\/span>\n        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> term_op <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> eval <span style=\"color: #66cc66;\">+<\/span>\n        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> eval<span style=\"color: #66cc66;\">,<\/span>\n    FACT <span style=\"color: #66cc66;\">=<\/span>\n        lparen <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> rparen <span style=\"color: #66cc66;\">\/<\/span> eval <span style=\"color: #66cc66;\">+<\/span>\n        number <span style=\"color: #66cc66;\">\/<\/span> eval\n<span style=\"color: #66cc66;\">&#125;<\/span><\/pre><\/div><\/div><\/div>\n\n<p>With all these changes it&#8217;s easy to accidentally break one part of the parser while fixing another, so we&#8217;ll also write a quick function to ensure we didn&#8217;t create a regression:<\/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> test<span style=\"color: #66cc66;\">&#40;<\/span>expr<span style=\"color: #66cc66;\">&#41;<\/span>\n    <span style=\"color: #0000aa;\">assert<\/span><span style=\"color: #66cc66;\">&#40;<\/span>expr<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot; 1 + 2 &quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #cc66cc;\">3<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n    <span style=\"color: #0000aa;\">assert<\/span><span style=\"color: #66cc66;\">&#40;<\/span>expr<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;1+2+3+4+5&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #cc66cc;\">15<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n    <span style=\"color: #0000aa;\">assert<\/span><span style=\"color: #66cc66;\">&#40;<\/span>expr<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;2*3*4 + 5*6*7&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #cc66cc;\">234<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n    <span style=\"color: #0000aa;\">assert<\/span><span style=\"color: #66cc66;\">&#40;<\/span>expr<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot; 1 * 2 + 3&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #cc66cc;\">5<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n    <span style=\"color: #0000aa;\">assert<\/span><span style=\"color: #66cc66;\">&#40;<\/span>expr<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;( 2 +2) *6&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #cc66cc;\">24<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n<span style=\"color: #aa9900; font-weight: bold;\">end<\/span><\/pre><\/div><\/div><\/div>\n\n<h2>Eliminating recursion<\/h2>\n<p>Finally, we can now make the parser even simpler by eliminating some of the recursive rules. Instead of saying an EXPR is a TERM followed by an EXPR, let&#8217;s say an EXPR is a list of repeated TERMs:<\/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> spc <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> 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> <span style=\"color: #66cc66;\">&#40;<\/span> expr_op <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><span style=\"color: #cc66cc;\">0<\/span> <span style=\"color: #66cc66;\">\/<\/span> eval<span style=\"color: #66cc66;\">,<\/span>\n    TERM <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> <span style=\"color: #66cc66;\">&#40;<\/span> term_op <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><span style=\"color: #cc66cc;\">0<\/span> <span style=\"color: #66cc66;\">\/<\/span> eval<span style=\"color: #66cc66;\">,<\/span>\n    FACT <span style=\"color: #66cc66;\">=<\/span>\n        lparen <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> rparen <span style=\"color: #66cc66;\">\/<\/span> eval <span style=\"color: #66cc66;\">+<\/span>\n        number <span style=\"color: #66cc66;\">\/<\/span> eval\n<span style=\"color: #66cc66;\">&#125;<\/span><\/pre><\/div><\/div><\/div>\n\n<p>This will also require some changes in <code>eval<\/code>, since it&#8217;s going to get a variable-length argument list, instead of rolling up the expression one operation at a time. Instead of <code>eval(2, '+', eval(4, '+', 3))<\/code>, we&#8217;re now effectively calling <code>eval(2, '+', 4, '+', 3)<\/code>. So, here&#8217;s the new <code>eval<\/code>:<\/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><span style=\"color: #66cc66;\">...<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">local<\/span> args <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #66cc66;\">&#123;<\/span><span style=\"color: #66cc66;\">...<\/span><span style=\"color: #66cc66;\">&#125;<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">local<\/span> accum <span style=\"color: #66cc66;\">=<\/span> args<span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #cc66cc;\">1<\/span><span style=\"color: #66cc66;\">&#93;<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">for<\/span> i <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #cc66cc;\">2<\/span><span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #66cc66;\">#<\/span>args<span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #cc66cc;\">2<\/span> <span style=\"color: #aa9900; font-weight: bold;\">do<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">local<\/span> operator <span style=\"color: #66cc66;\">=<\/span> args<span style=\"color: #66cc66;\">&#91;<\/span>i<span style=\"color: #66cc66;\">&#93;<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">local<\/span> num2 <span style=\"color: #66cc66;\">=<\/span> args<span style=\"color: #66cc66;\">&#91;<\/span>i<span style=\"color: #66cc66;\">+<\/span><span style=\"color: #cc66cc;\">1<\/span><span style=\"color: #66cc66;\">&#93;<\/span>\n&nbsp;\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            accum <span style=\"color: #66cc66;\">=<\/span> accum <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            accum <span style=\"color: #66cc66;\">=<\/span> accum <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            accum <span style=\"color: #66cc66;\">=<\/span> accum <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            accum <span style=\"color: #66cc66;\">=<\/span> accum <span style=\"color: #66cc66;\">\/<\/span> num2\n        <span style=\"color: #aa9900; font-weight: bold;\">end<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">end<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> accum\n<span style=\"color: #aa9900; font-weight: bold;\">end<\/span><\/pre><\/div><\/div><\/div>\n\n<p>Now we have a much nicer and cleaner-looking grammar.<\/p>\n<h2>Variables<\/h2>\n<p>So let&#8217;s add in variables. Here&#8217;s what we&#8217;d like to be able to do: we should first of all be able to assign values to variables with <code>=<\/code>:<\/p>\n<pre>a = 5\r\n\r\n<\/pre>\n<p>Next, we&#8217;d like to be able to use variables in expressions:<\/p>\n<pre>b = (a+3) \/ 2\r\n\r\n<\/pre>\n<p>So to start off with, let&#8217;s think about how this will affect the grammar. The most obvious thing is that we&#8217;ll need a way to match a variable name:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">letter <span style=\"color: #66cc66;\">=<\/span> R<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'AZ'<\/span><span style=\"color: #66cc66;\">,<\/span><span style=\"color: #ff6666;\">'az'<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\nname <span style=\"color: #66cc66;\">=<\/span> C<span style=\"color: #66cc66;\">&#40;<\/span> letter <span style=\"color: #66cc66;\">*<\/span> <span style=\"color: #66cc66;\">&#40;<\/span>digit<span style=\"color: #66cc66;\">+<\/span>letter<span style=\"color: #66cc66;\">+<\/span><span style=\"color: #ff6666;\">&quot;_&quot;<\/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> spc<\/pre><\/div><\/div><\/div>\n\n<p>This makes variables be some sequence of letters, digits, and underscores, that starts with a letter.<\/p>\n<p>Next is, right now, we&#8217;re matching EXPRs only; we&#8217;ll need a new type of statement that can be either an assignment or an EXPR. Let&#8217;s call it a STMT:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">stmt <span style=\"color: #66cc66;\">=<\/span> spc <span style=\"color: #66cc66;\">*<\/span> P<span style=\"color: #66cc66;\">&#123;<\/span>\n    <span style=\"color: #ff6666;\">&quot;STMT&quot;<\/span><span style=\"color: #66cc66;\">;<\/span>\n    STMT <span style=\"color: #66cc66;\">=<\/span>\n        name <span style=\"color: #66cc66;\">*<\/span> <span style=\"color: #ff6666;\">&quot;=&quot;<\/span> <span style=\"color: #66cc66;\">*<\/span> spc <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> assign <span style=\"color: #66cc66;\">+<\/span>\n        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    EXPR <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> <span style=\"color: #66cc66;\">&#40;<\/span> expr_op <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><span style=\"color: #cc66cc;\">0<\/span> <span style=\"color: #66cc66;\">\/<\/span> eval<span style=\"color: #66cc66;\">,<\/span>\n    TERM <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> <span style=\"color: #66cc66;\">&#40;<\/span> term_op <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><span style=\"color: #cc66cc;\">0<\/span> <span style=\"color: #66cc66;\">\/<\/span> eval<span style=\"color: #66cc66;\">,<\/span>\n    FACT <span style=\"color: #66cc66;\">=<\/span>\n        lparen <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> rparen <span style=\"color: #66cc66;\">\/<\/span> eval <span style=\"color: #66cc66;\">+<\/span>\n        number <span style=\"color: #66cc66;\">\/<\/span> eval\n<span style=\"color: #66cc66;\">&#125;<\/span><\/pre><\/div><\/div><\/div>\n\n<p>STMT is now the first thing we match, and STMTs can&#8217;t be part of EXPRs (though EXPRs are part of STMTs). Also, we don&#8217;t send STMTs to <code>eval<\/code>, we send them to a new function, <code>assign<\/code>:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">VARS <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #66cc66;\">&#123;<\/span><span style=\"color: #66cc66;\">&#125;<\/span>\n<span style=\"color: #aa9900; font-weight: bold;\">function<\/span> assign<span style=\"color: #66cc66;\">&#40;<\/span>name<span style=\"color: #66cc66;\">,<\/span> value<span style=\"color: #66cc66;\">&#41;<\/span>\n    VARS<span style=\"color: #66cc66;\">&#91;<\/span>name<span style=\"color: #66cc66;\">&#93;<\/span> <span style=\"color: #66cc66;\">=<\/span> value\n    <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> value\n<span style=\"color: #aa9900; font-weight: bold;\">end<\/span><\/pre><\/div><\/div><\/div>\n\n<p>We&#8217;re storing all the variables in a <code>VARS<\/code> table. We return the value on the right-hand side of the assign not because we need it for anything, but because if we don&#8217;t return something then LPeg will just produce the next string index (just as if we hadn&#8217;t captured anything).<\/p>\n<p>Now we need a way to reference variables. A variable can be used anywhere a number can, so let&#8217;s make them another production of FACT:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">FACT <span style=\"color: #66cc66;\">=<\/span>\n    name <span style=\"color: #66cc66;\">\/<\/span> VARS <span style=\"color: #66cc66;\">+<\/span>\n    lparen <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> rparen <span style=\"color: #66cc66;\">\/<\/span> eval <span style=\"color: #66cc66;\">+<\/span>\n    number <span style=\"color: #66cc66;\">\/<\/span> eval<\/pre><\/div><\/div><\/div>\n\n<p>Notice that what we&#8217;re passing <code>name<\/code>s to isn&#8217;t a function, but our table of variables: looking up names in a table is a common-enough task that LPeg lets you use a table as a capture handler instead of a function.<\/p>\n<p>Also, the order of these is somewhat tricky: it only works if <code>name<\/code> goes before <code>number<\/code>. This is because <code>number<\/code> will try to match anything: if it starts with a minus sign or a digit it works, otherwise it fails <em>and fails the entire FACT match<\/em> because LPeg does no backtracking. If you want, you can either use <code>number-name<\/code> (&#8220;match number as long as name doesn&#8217;t match&#8221;) in place of <code>number<\/code>, or change <code>number<\/code> to this, to make the order irrelevant:<\/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> C<span style=\"color: #66cc66;\">&#40;<\/span> <span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'-'<\/span> <span style=\"color: #66cc66;\">+<\/span> digit<span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span>\n                digit<span style=\"color: #66cc66;\">^<\/span><span style=\"color: #cc66cc;\">0<\/span> <span style=\"color: #66cc66;\">*<\/span>\n                <span style=\"color: #66cc66;\">&#40;<\/span> P<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">'.'<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span> digit<span style=\"color: #66cc66;\">^<\/span><span style=\"color: #cc66cc;\">0<\/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> <span style=\"color: #0000aa;\">tonumber<\/span> <span style=\"color: #66cc66;\">*<\/span> spc<\/pre><\/div><\/div><\/div>\n\n<p>In general you should avoid having a pattern begin with an optional element (any element raised to a negative power), to avoid tricky backtracking issues like this.<\/p>\n<p>New we can add a few lines into our <code>test<\/code> function to make sure variables work:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">stmt<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;a=3&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">;<\/span> <span style=\"color: #0000aa;\">assert<\/span><span style=\"color: #66cc66;\">&#40;<\/span>VARS<span style=\"color: #66cc66;\">.<\/span>a <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #cc66cc;\">3<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n<span style=\"color: #0000aa;\">assert<\/span><span style=\"color: #66cc66;\">&#40;<\/span>stmt<span style=\"color: #66cc66;\">:<\/span>match<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;\">&#41;<\/span>\n<span style=\"color: #0000aa;\">assert<\/span><span style=\"color: #66cc66;\">&#40;<\/span>stmt<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;a * 5&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #cc66cc;\">15<\/span><span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">;<\/span> VARS<span style=\"color: #66cc66;\">.<\/span>a<span style=\"color: #66cc66;\">=<\/span><span style=\"color: #aa9900;\">nil<\/span><\/pre><\/div><\/div><\/div>\n\n<h2>Arrays<\/h2>\n<p>Having single variables is nice, but we should also allow for arrays. Here&#8217;s the syntax we&#8217;ll use:<\/p>\n<ul>\n<li>An array can be specified literally with brackets, like &#8220;[1, 2, 3]&#8221;<\/li>\n<li>Arrays can be subscripted with brackets, like &#8220;arr[2]&#8221;<\/li>\n<li>Arrays can be nested inside of arrays<\/li>\n<\/ul>\n<p>Let&#8217;s add some productions to our grammar. An ARRAY looks like this:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">ARRAY <span style=\"color: #66cc66;\">=<\/span> lbrack <span style=\"color: #66cc66;\">*<\/span> V<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;VAL_LIST&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">^-<\/span><span style=\"color: #cc66cc;\">1<\/span> <span style=\"color: #66cc66;\">*<\/span> rbrack<span style=\"color: #66cc66;\">,<\/span>\nVAL_LIST <span style=\"color: #66cc66;\">=<\/span> V<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;VAL&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span> <span style=\"color: #66cc66;\">&#40;<\/span>comma <span style=\"color: #66cc66;\">*<\/span> V<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;VAL&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">^<\/span><span style=\"color: #cc66cc;\">0<\/span><\/pre><\/div><\/div><\/div>\n\n<p>(<code>lbrack<\/code>, <code>rbrack<\/code>, and <code>comma<\/code> are simple patterns matching one punctuation character followed by <code>spc<\/code>, just like <code>lparen<\/code> and <code>rparen<\/code> were).<\/p>\n<p>We&#8217;re adding a new nonterminal VAL that represents a value. These can be either EXPRs or an ARRAY:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">VAL <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> V<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;ARRAY&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span><\/pre><\/div><\/div><\/div>\n\n<p>And where we had EXPR as the right-hand side of an assignment statement, now it should be VAL:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">STMT <span style=\"color: #66cc66;\">=<\/span>\n    name <span style=\"color: #66cc66;\">*<\/span> <span style=\"color: #ff6666;\">&quot;=&quot;<\/span> <span style=\"color: #66cc66;\">*<\/span> spc <span style=\"color: #66cc66;\">*<\/span> V<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;VAL&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">\/<\/span> assign <span style=\"color: #66cc66;\">+<\/span>\n    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><\/pre><\/div><\/div><\/div>\n\n<p>So, now we can parse things like &#8220;a=[1, 2, 3]&#8221;. We&#8217;ll need to actually capture things though. LPeg has a function, <code>Ct<\/code>, that packs all the captures of a pattern into a table, and treats it as one capture. We can use that on the VAL_LIST instead of bothering to write a function to capture ARRAYs:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">ARRAY <span style=\"color: #66cc66;\">=<\/span> lbrack <span style=\"color: #66cc66;\">*<\/span> Ct<span style=\"color: #66cc66;\">&#40;<\/span> V<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;VAL_LIST&quot;<\/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> rbrack<\/pre><\/div><\/div><\/div>\n\n<p>Now when we parse an assignment to an array, it will actually assign something, and we can test that:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">stmt<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;a = [4, 5, 6]&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">;<\/span>\n<span style=\"color: #0000aa;\">assert<\/span><span style=\"color: #66cc66;\">&#40;<\/span>VARS<span style=\"color: #66cc66;\">.<\/span>a<span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #cc66cc;\">1<\/span><span style=\"color: #66cc66;\">&#93;<\/span> <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #cc66cc;\">4<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n<span style=\"color: #0000aa;\">assert<\/span><span style=\"color: #66cc66;\">&#40;<\/span>VARS<span style=\"color: #66cc66;\">.<\/span>a<span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #cc66cc;\">2<\/span><span style=\"color: #66cc66;\">&#93;<\/span> <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #cc66cc;\">5<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n<span style=\"color: #0000aa;\">assert<\/span><span style=\"color: #66cc66;\">&#40;<\/span>VARS<span style=\"color: #66cc66;\">.<\/span>a<span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #cc66cc;\">3<\/span><span style=\"color: #66cc66;\">&#93;<\/span> <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #cc66cc;\">6<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\nVARS<span style=\"color: #66cc66;\">.<\/span>a<span style=\"color: #66cc66;\">=<\/span><span style=\"color: #aa9900;\">nil<\/span>\nstmt<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;b = []&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">;<\/span>\n<span style=\"color: #0000aa;\">assert<\/span><span style=\"color: #66cc66;\">&#40;<\/span>VARS<span style=\"color: #66cc66;\">.<\/span>b<span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #cc66cc;\">1<\/span><span style=\"color: #66cc66;\">&#93;<\/span> <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #aa9900;\">nil<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\nVARS<span style=\"color: #66cc66;\">.<\/span>b<span style=\"color: #66cc66;\">=<\/span><span style=\"color: #aa9900;\">nil<\/span><\/pre><\/div><\/div><\/div>\n\n<p>As well as, of course, nesting arrays:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">stmt<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;c = [[1,2], [3,4]]&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n<span style=\"color: #0000aa;\">assert<\/span><span style=\"color: #66cc66;\">&#40;<\/span>VARS<span style=\"color: #66cc66;\">.<\/span>c<span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #cc66cc;\">1<\/span><span style=\"color: #66cc66;\">&#93;<\/span><span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #cc66cc;\">1<\/span><span style=\"color: #66cc66;\">&#93;<\/span> <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #cc66cc;\">1<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n<span style=\"color: #0000aa;\">assert<\/span><span style=\"color: #66cc66;\">&#40;<\/span>VARS<span style=\"color: #66cc66;\">.<\/span>c<span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #cc66cc;\">1<\/span><span style=\"color: #66cc66;\">&#93;<\/span><span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #cc66cc;\">2<\/span><span style=\"color: #66cc66;\">&#93;<\/span> <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #cc66cc;\">2<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n<span style=\"color: #0000aa;\">assert<\/span><span style=\"color: #66cc66;\">&#40;<\/span>VARS<span style=\"color: #66cc66;\">.<\/span>c<span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #cc66cc;\">2<\/span><span style=\"color: #66cc66;\">&#93;<\/span><span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #cc66cc;\">1<\/span><span style=\"color: #66cc66;\">&#93;<\/span> <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #cc66cc;\">3<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n<span style=\"color: #0000aa;\">assert<\/span><span style=\"color: #66cc66;\">&#40;<\/span>VARS<span style=\"color: #66cc66;\">.<\/span>c<span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #cc66cc;\">2<\/span><span style=\"color: #66cc66;\">&#93;<\/span><span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #cc66cc;\">2<\/span><span style=\"color: #66cc66;\">&#93;<\/span> <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #cc66cc;\">4<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\nVARS<span style=\"color: #66cc66;\">.<\/span>c<span style=\"color: #66cc66;\">=<\/span><span style=\"color: #aa9900;\">nil<\/span><\/pre><\/div><\/div><\/div>\n\n<h2>Array subscripting<\/h2>\n<p>Now to work on how to get values out of arrays. Taking a value out of an array is a lot like reading the value of a variable in general. Let&#8217;s make a new nonterminal, &#8220;REF,&#8221; that will hold a <em>reference<\/em> that we can read or write to. A REF will be a variable name followed by a series of subscripts in brackets. FACT will match a REF, and read its value:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">REF <span style=\"color: #66cc66;\">=<\/span> name <span style=\"color: #66cc66;\">*<\/span> <span style=\"color: #66cc66;\">&#40;<\/span>lbrack <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> rbrack<span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">^<\/span><span style=\"color: #cc66cc;\">0<\/span> <span style=\"color: #66cc66;\">\/<\/span> makeref<span style=\"color: #66cc66;\">,<\/span>\nFACT <span style=\"color: #66cc66;\">=<\/span>\n    number <span style=\"color: #66cc66;\">\/<\/span> eval <span style=\"color: #66cc66;\">+<\/span>\n    lparen <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> rparen <span style=\"color: #66cc66;\">\/<\/span> eval <span style=\"color: #66cc66;\">+<\/span>\n    V<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;REF&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">\/<\/span> lookup<span style=\"color: #66cc66;\">,<\/span><\/pre><\/div><\/div><\/div>\n\n<p>The functions to make a REF and read its value look like this:<\/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> makeref<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #66cc66;\">...<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">local<\/span> indices <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #66cc66;\">&#123;<\/span><span style=\"color: #66cc66;\">...<\/span><span style=\"color: #66cc66;\">&#125;<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">local<\/span> tbl <span style=\"color: #66cc66;\">=<\/span> VARS\n&nbsp;\n    <span style=\"color: #aa9900; font-weight: bold;\">for<\/span> i <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #cc66cc;\">1<\/span><span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #66cc66;\">#<\/span>indices<span style=\"color: #66cc66;\">-<\/span><span style=\"color: #cc66cc;\">1<\/span> <span style=\"color: #aa9900; font-weight: bold;\">do<\/span>\n        tbl <span style=\"color: #66cc66;\">=<\/span> tbl<span style=\"color: #66cc66;\">&#91;<\/span>indices<span style=\"color: #66cc66;\">&#91;<\/span>i<span style=\"color: #66cc66;\">&#93;<\/span><span style=\"color: #66cc66;\">&#93;<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">end<\/span>\n&nbsp;\n    <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> <span style=\"color: #66cc66;\">&#123;<\/span>scope<span style=\"color: #66cc66;\">=<\/span>tbl<span style=\"color: #66cc66;\">,<\/span> index<span style=\"color: #66cc66;\">=<\/span>indices<span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #66cc66;\">#<\/span>indices<span style=\"color: #66cc66;\">&#93;<\/span><span style=\"color: #66cc66;\">&#125;<\/span>\n<span style=\"color: #aa9900; font-weight: bold;\">end<\/span>\n&nbsp;\n<span style=\"color: #aa9900; font-weight: bold;\">function<\/span> lookup<span style=\"color: #66cc66;\">&#40;<\/span>ref<span style=\"color: #66cc66;\">&#41;<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> ref<span style=\"color: #66cc66;\">.<\/span>scope<span style=\"color: #66cc66;\">&#91;<\/span>ref<span style=\"color: #66cc66;\">.<\/span>index<span style=\"color: #66cc66;\">&#93;<\/span>\n<span style=\"color: #aa9900; font-weight: bold;\">end<\/span><\/pre><\/div><\/div><\/div>\n\n<p>A REF consists of a table with <code>scope<\/code> and <code>index<\/code> keys. The <em>scope<\/em> is the table in which the variable resides (all variables that aren&#8217;t array elements reside in <code>VARS<\/code>, so it&#8217;s simple enough to start there) and the index is the place in that table where you can find it. When we parse a REF we call <code>makeref<\/code> to create this object, and when we parse a FACT that <em>is<\/em> a REF we call <code>lookup<\/code> to read its current value.<\/p>\n<p>This is the first thing our parser has generated that evaluates to an intermediate object, instead of a number. EXPRs, TERMs, and FACTs all get turned into the numbers they evaluate to when we parse them; a REF has no meaning until it&#8217;s evaluated by <code>lookup<\/code>. We&#8217;re going to expand on this general idea of an intermediate representation a lot in the next post.<\/p>\n<p>Anyway, for now, it&#8217;s easy to write a test that shows that we can look up array elements:<\/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: #0000aa;\">assert<\/span><span style=\"color: #66cc66;\">&#40;<\/span>stmt<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;c[4\/2][1]&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #cc66cc;\">3<\/span><span style=\"color: #66cc66;\">&#41;<\/span><\/pre><\/div><\/div><\/div>\n\n<h2>Assigning to arrays<\/h2>\n<p>You may be wondering, why not combine <code>makeref<\/code> and <code>lookup<\/code>? Why not have <code>makeref<\/code> go one step further down the chain of indices and return the final value?<\/p>\n<p>It&#8217;s because we also want to support assignments; REFs as <em>lvalues<\/em>. Lua doesn&#8217;t let us take a reference to a number, numbers are always passed by value, so we have to store the table and the index to write to instead. By making one function to create that, we can use it in both FACT (with <code>lookup<\/code>) and in assignments, with what we&#8217;re about to write.<\/p>\n<p>Let&#8217;s change the grammar for STMTs:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">STMT <span style=\"color: #66cc66;\">=<\/span>\n    V<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;REF&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> V<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;VAL&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">\/<\/span> assign <span style=\"color: #66cc66;\">+<\/span>\n    V<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;EXPR&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span><\/pre><\/div><\/div><\/div>\n\n<p>Now, change the <code>assign<\/code> function to expect its first parameter to be a REF instead of a name:<\/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> assign<span style=\"color: #66cc66;\">&#40;<\/span>ref<span style=\"color: #66cc66;\">,<\/span> value<span style=\"color: #66cc66;\">&#41;<\/span>\n    ref<span style=\"color: #66cc66;\">.<\/span>scope<span style=\"color: #66cc66;\">&#91;<\/span>ref<span style=\"color: #66cc66;\">.<\/span>index<span style=\"color: #66cc66;\">&#93;<\/span> <span style=\"color: #66cc66;\">=<\/span> value\n    <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> value\n<span style=\"color: #aa9900; font-weight: bold;\">end<\/span><\/pre><\/div><\/div><\/div>\n\n<p>With this one change, now we can assign to elements of arrays:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">stmt<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;c[3] = 5&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n<span style=\"color: #0000aa;\">assert<\/span><span style=\"color: #66cc66;\">&#40;<\/span>VARS<span style=\"color: #66cc66;\">.<\/span>c<span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #cc66cc;\">3<\/span><span style=\"color: #66cc66;\">&#93;<\/span> <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #cc66cc;\">5<\/span><span style=\"color: #66cc66;\">&#41;<\/span><\/pre><\/div><\/div><\/div>\n\n<h2>Next steps<\/h2>\n<p>Our little calculator from part 1 now understands variables, arrays, and even nested arrays. It&#8217;s starting to become a more complete language. However, we&#8217;re still missing a lot of concepts: there are no conditional statements or loops, both of which are needed to make variables and arrays useful (what good is a variable if it can&#8217;t affect program flow; what good is an array if you can&#8217;t loop over it?). We are also reaching (and edging past) the limits of the evaluate-as-you-parse model. We&#8217;ve already seen how it doesn&#8217;t work for assignments to arrays.<\/p>\n<p>So, next week, we&#8217;re going to do a major overhaul of how this language gets run, and then use that new design to implement some features that would be impossible with this one: conditionals and looping.<\/p>\n<p>The complete code to this post is available <a onclick=\"javascript:pageTracker._trackPageview('\/outgoing\/gist.github.com\/randrews\/5eab368f35ab8e774433');\"  href=\"https:\/\/gist.github.com\/randrews\/5eab368f35ab8e774433\">here<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is part two of my series on writing a toy programming language using LPeg. You should first read part one here. Last time, we made an interpreter for a simple calculator: it would read in mathematical expressions and evaluate them, printing the result. This time, we&#8217;re going to add two new features: variables 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\/68"}],"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=68"}],"version-history":[{"count":0,"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=\/wp\/v2\/posts\/68\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=68"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=68"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=68"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}