{"id":70,"date":"2015-06-12T23:41:45","date_gmt":"2015-06-13T04:41:45","guid":{"rendered":"http:\/\/www.playwithlua.com\/?p=70"},"modified":"2015-06-12T23:41:45","modified_gmt":"2015-06-13T04:41:45","slug":"making-a-toy-programming-language-in-lua-part-3","status":"publish","type":"post","link":"http:\/\/www.playwithlua.com\/?p=70","title":{"rendered":"Making a toy programming language in Lua, part 3"},"content":{"rendered":"<p>This is part three 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 start with part one <a href=\"http:\/\/www.playwithlua.com\/?p=66\">here<\/a>.<\/p>\n<p>Last time, we added variables and arrays to the language. Assigning to arrays was starting to strain our design some, so this time we&#8217;ll refactor it a lot, and add two features that would be impossible without that refactoring: conditional statements and loops.<\/p>\n<p><!--more--><\/p>\n<h2>Abstract syntax trees<\/h2>\n<p>Right now, our parser evaluates expressions as soon as it can, while it&#8217;s still in the process of parsing them. This was fine while we were just parsing mathematical expressions, and it&#8217;s even fine when we start to include variables (as long as assignment statements can&#8217;t appear inside expressions), but conditionals and loops break that: we need to <em>parse<\/em> the entire &#8220;if&#8221; statement, but we only want the body to <em>happen<\/em> after we evaluate the condition. With our current parser, we would evaluate the body (and cause the side-effects of any assignment statements it contains) as soon as we parse it, so those statements would run whether the condition was true or false.<\/p>\n<p>In order to fix this, we first need to do a major overhaul of our language. I&#8217;m going to part with <em>The Unix Programming Environment<\/em> a little here: they jumped right to compilation and code generation, whereas I&#8217;m going to do that, but not immediately: it&#8217;s more common to do what I&#8217;m going to do, and build an <em>abstract syntax tree<\/em> first.<\/p>\n<p>So, the first thing we need to do is decide how to represent an AST. Let&#8217;s have each node be a table with index 1 being the type of node, and the rest being the captures. So, the AST for &#8220;2+3&#8221; would be:<\/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: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;expr&quot;<\/span><span style=\"color: #66cc66;\">,<\/span>\n  <span style=\"color: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;term&quot;<\/span><span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #cc66cc;\">2<\/span> <span style=\"color: #66cc66;\">&#125;<\/span><span style=\"color: #66cc66;\">,<\/span>\n  <span style=\"color: #ff6666;\">&quot;+&quot;<\/span><span style=\"color: #66cc66;\">,<\/span>\n  <span style=\"color: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;term&quot;<\/span><span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #cc66cc;\">3<\/span> <span style=\"color: #66cc66;\">&#125;<\/span>\n<span style=\"color: #66cc66;\">&#125;<\/span><\/pre><\/div><\/div><\/div>\n\n<p>We can construct this easily enough. Actually much more easily than if we were using Yacc. We&#8217;ll use two more LPeg functions, <code>Cc<\/code> and <code>Ct<\/code>. <code>Ct<\/code> is a <em>table capture,<\/em> which wraps up all the captures for a pattern into a table, and <code>Cc<\/code> is a <em>constant capture,<\/em> which consumes none of the input but captures its argument. By taking a nonterminal like EXPR, which 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;\">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><\/pre><\/div><\/div><\/div>\n\n<p>&#8230;Removing the function captures (because we don&#8217;t want to evaluate it yet), wrapping it up in <code>Ct<\/code>, and prefacing it with <code>Cc<\/code> to tag it:<\/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> Ct<span style=\"color: #66cc66;\">&#40;<\/span> Cc<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;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;\">&#41;<\/span><span style=\"color: #66cc66;\">,<\/span><\/pre><\/div><\/div><\/div>\n\n<p>&#8230;we can make our parser generate an AST. The way LPeg can build this directly into the grammar is really quite neat, I think.<\/p>\n<p>When we do this to the entire grammar, here&#8217;s what we&#8217;re left with:<\/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        Ct<span style=\"color: #66cc66;\">&#40;<\/span> Cc<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;assign&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;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;\">&#41;<\/span> <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> Ct<span style=\"color: #66cc66;\">&#40;<\/span> Cc<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;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;\">&#41;<\/span><span style=\"color: #66cc66;\">,<\/span>\n    TERM <span style=\"color: #66cc66;\">=<\/span> Ct<span style=\"color: #66cc66;\">&#40;<\/span> Cc<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> 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;\">&#41;<\/span><span style=\"color: #66cc66;\">,<\/span>\n    REF <span style=\"color: #66cc66;\">=<\/span> Ct<span style=\"color: #66cc66;\">&#40;<\/span> Cc<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> 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;\">&#41;<\/span><span style=\"color: #66cc66;\">,<\/span>\n    FACT <span style=\"color: #66cc66;\">=<\/span>\n        number <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>\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>\n    ARRAY <span style=\"color: #66cc66;\">=<\/span> Ct<span style=\"color: #66cc66;\">&#40;<\/span> Cc<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;array&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <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 <span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">,<\/span>\n    VAL_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><span style=\"color: #66cc66;\">,<\/span>\n    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>\n<span style=\"color: #66cc66;\">&#125;<\/span><\/pre><\/div><\/div><\/div>\n\n<p>As you can see, we&#8217;ve only changed a few of them, because some things are simple enough not to need their own nodes: numbers and REFs don&#8217;t really need to be wrapped in FACT nodes, because a FACT will always just evaluate to its only child, for example. Same with STMT, we only really care if it&#8217;s an assignment or an EXPR, because a STMT that contains an EXPR just evaluates that EXPR.<\/p>\n<p>So, now, trying to match &#8220;2+3&#8221; yields the exact tree that we&#8217;d expect:<\/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;\">-- stmt:match(&quot;2+3&quot;) gives:<\/span>\n&nbsp;\n<span style=\"color: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;expr&quot;<\/span><span style=\"color: #66cc66;\">,<\/span>\n  <span style=\"color: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;term&quot;<\/span><span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #cc66cc;\">2<\/span> <span style=\"color: #66cc66;\">&#125;<\/span><span style=\"color: #66cc66;\">,<\/span>\n  <span style=\"color: #ff6666;\">&quot;+&quot;<\/span><span style=\"color: #66cc66;\">,<\/span>\n  <span style=\"color: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;term&quot;<\/span><span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #cc66cc;\">3<\/span> <span style=\"color: #66cc66;\">&#125;<\/span>\n<span style=\"color: #66cc66;\">&#125;<\/span><\/pre><\/div><\/div><\/div>\n\n<h2>Evaluating an AST<\/h2>\n<p>Obviously we&#8217;ll need to change the <code>eval<\/code> function to handle these. In fact, let&#8217;s split it up into several functions. TERMs and EXPRs can share a function that&#8217;s a lot like the current <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_expr<span style=\"color: #66cc66;\">&#40;<\/span>expr<span style=\"color: #66cc66;\">&#41;<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">local<\/span> accum <span style=\"color: #66cc66;\">=<\/span> eval<span style=\"color: #66cc66;\">&#40;<\/span>expr<span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #cc66cc;\">2<\/span><span style=\"color: #66cc66;\">&#93;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #808080; font-style: italic;\">-- because 1 is &quot;expr&quot;<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">for<\/span> i <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #cc66cc;\">3<\/span><span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #66cc66;\">#<\/span>expr<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> expr<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> eval<span style=\"color: #66cc66;\">&#40;<\/span>expr<span style=\"color: #66cc66;\">&#91;<\/span>i<span style=\"color: #66cc66;\">+<\/span><span style=\"color: #cc66cc;\">1<\/span><span style=\"color: #66cc66;\">&#93;<\/span><span style=\"color: #66cc66;\">&#41;<\/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>We&#8217;re still doing the same basic thing, with the loop and accumulator. The main differences are that we start at index 2 (because index 1 is the name of the node, either &#8220;expr&#8221; or &#8220;term&#8221;), and that all the subvalues, <code>num1<\/code> and <code>num2<\/code>, get sent to <code>eval<\/code> before being used. This recursion lets us handle EXPRs that have nested EXPRs or TERMs in them.<\/p>\n<p>The <code>eval<\/code> function itself becomes fairly simple as well. There aren&#8217;t many things we can possibly send it:<\/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>ast<span style=\"color: #66cc66;\">&#41;<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">if<\/span> <span style=\"color: #0000aa;\">type<\/span><span style=\"color: #66cc66;\">&#40;<\/span>ast<span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #ff6666;\">'number'<\/span> <span style=\"color: #aa9900; font-weight: bold;\">then<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> ast\n    <span style=\"color: #aa9900; font-weight: bold;\">elseif<\/span> ast<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: #ff6666;\">'expr'<\/span> <span style=\"color: #aa9900; font-weight: bold;\">or<\/span> ast<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: #ff6666;\">'term'<\/span> <span style=\"color: #aa9900; font-weight: bold;\">then<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> eval_expr<span style=\"color: #66cc66;\">&#40;<\/span>ast<span style=\"color: #66cc66;\">&#41;<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">elseif<\/span> ast<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: #ff6666;\">'array'<\/span> <span style=\"color: #aa9900; font-weight: bold;\">then<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">local<\/span> new <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;\">for<\/span> _<span style=\"color: #66cc66;\">,<\/span> el <span style=\"color: #aa9900; font-weight: bold;\">in<\/span> <span style=\"color: #0000aa;\">ipairs<\/span><span style=\"color: #66cc66;\">&#40;<\/span>ast<span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #cc66cc;\">2<\/span><span style=\"color: #66cc66;\">&#93;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #aa9900; font-weight: bold;\">do<\/span>\n            <span style=\"color: #0000aa;\">table.insert<\/span><span style=\"color: #66cc66;\">&#40;<\/span>new<span style=\"color: #66cc66;\">,<\/span> eval<span style=\"color: #66cc66;\">&#40;<\/span>el<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;\">return<\/span> new\n    <span style=\"color: #aa9900; font-weight: bold;\">elseif<\/span> ast<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: #ff6666;\">'ref'<\/span> <span style=\"color: #aa9900; font-weight: bold;\">then<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> lookup<span style=\"color: #66cc66;\">&#40;<\/span>ast<span style=\"color: #66cc66;\">&#41;<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">elseif<\/span> ast<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: #ff6666;\">'assign'<\/span> <span style=\"color: #aa9900; font-weight: bold;\">then<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> assign<span style=\"color: #66cc66;\">&#40;<\/span>ast<span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #cc66cc;\">2<\/span><span style=\"color: #66cc66;\">&#93;<\/span><span style=\"color: #66cc66;\">,<\/span> eval<span style=\"color: #66cc66;\">&#40;<\/span>ast<span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #cc66cc;\">3<\/span><span style=\"color: #66cc66;\">&#93;<\/span><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>Numbers are returned untouched, expressions and terms get sent to <code>eval_expr<\/code>, and arrays are recursively evaluated and returned in a table. References and assignments are a little more complicated.<\/p>\n<h2>Variables in an AST<\/h2>\n<p>To evaluate a REF, we need to follow a chain of indices: the first element in the chain is a variable name, but the variable could be an array, in which case there will be more elements, until finally you reach a number. So, the <code>lookup<\/code> function to do this, which has a lot in common with <code>makeref<\/code> from last time:<\/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> lookup<span style=\"color: #66cc66;\">&#40;<\/span>ref<span style=\"color: #66cc66;\">&#41;<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">local<\/span> current <span style=\"color: #66cc66;\">=<\/span> VARS\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>ref <span style=\"color: #aa9900; font-weight: bold;\">do<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">local<\/span> next_index <span style=\"color: #66cc66;\">=<\/span> ref<span style=\"color: #66cc66;\">&#91;<\/span>i<span style=\"color: #66cc66;\">&#93;<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">if<\/span> <span style=\"color: #0000aa;\">type<\/span><span style=\"color: #66cc66;\">&#40;<\/span>next_index<span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #ff6666;\">'table'<\/span> <span style=\"color: #aa9900; font-weight: bold;\">then<\/span>\n            next_index <span style=\"color: #66cc66;\">=<\/span> eval<span style=\"color: #66cc66;\">&#40;<\/span>next_index<span style=\"color: #66cc66;\">&#41;<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">end<\/span>\n&nbsp;\n        current <span style=\"color: #66cc66;\">=<\/span> current<span style=\"color: #66cc66;\">&#91;<\/span>next_index<span style=\"color: #66cc66;\">&#93;<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">end<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> current\n<span style=\"color: #aa9900; font-weight: bold;\">end<\/span><\/pre><\/div><\/div><\/div>\n\n<p>At each step, the next index can be a variable name, a number, or an expression that evaluates to a number. So, if it&#8217;s a table, it must be an expression, and we <code>eval<\/code> it.<\/p>\n<p>An assignment is pretty much the same: we take a ref and a value, follow down to one before the end of the chain of indices, and then set the value:<\/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    <span style=\"color: #aa9900; font-weight: bold;\">local<\/span> current <span style=\"color: #66cc66;\">=<\/span> VARS\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>ref <span style=\"color: #aa9900; font-weight: bold;\">do<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">local<\/span> next_index <span style=\"color: #66cc66;\">=<\/span> ref<span style=\"color: #66cc66;\">&#91;<\/span>i<span style=\"color: #66cc66;\">&#93;<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">if<\/span> <span style=\"color: #0000aa;\">type<\/span><span style=\"color: #66cc66;\">&#40;<\/span>next_index<span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #ff6666;\">'table'<\/span> <span style=\"color: #aa9900; font-weight: bold;\">then<\/span>\n            next_index <span style=\"color: #66cc66;\">=<\/span> eval<span style=\"color: #66cc66;\">&#40;<\/span>next_index<span style=\"color: #66cc66;\">&#41;<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">end<\/span>\n&nbsp;\n        <span style=\"color: #aa9900; font-weight: bold;\">if<\/span> i <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #66cc66;\">#<\/span>ref <span style=\"color: #aa9900; font-weight: bold;\">then<\/span> <span style=\"color: #808080; font-style: italic;\">-- last one, set the value<\/span>\n            current<span style=\"color: #66cc66;\">&#91;<\/span>next_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;\">else<\/span> <span style=\"color: #808080; font-style: italic;\">-- not the last, keep following the chain<\/span>\n            current <span style=\"color: #66cc66;\">=<\/span> current<span style=\"color: #66cc66;\">&#91;<\/span>next_index<span style=\"color: #66cc66;\">&#93;<\/span>\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;\">end<\/span><\/pre><\/div><\/div><\/div>\n\n<p>So, with these changes, and one minor tweak in our <code>test<\/code> function (add <code>stmt = stmt \/ eval<\/code> to the top of it), all our tests will pass again. Now we&#8217;re ready to start adding functionality to use the AST.<\/p>\n<h2>Conditionals<\/h2>\n<p>First, let&#8217;s modify the parser to handle conditionals. We&#8217;ll need to add three new concepts: a statement list (that will go inside the conditional), a boolean expression (that will be the predicate of the conditional), and the conditional itself. Booleans seem easy enough to start with. Match the possible operators:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">boolean <span style=\"color: #66cc66;\">=<\/span> C<span style=\"color: #66cc66;\">&#40;<\/span> S<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;&lt;&gt;&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">+<\/span> <span style=\"color: #ff6666;\">&quot;&lt;=&quot;<\/span> <span style=\"color: #66cc66;\">+<\/span> <span style=\"color: #ff6666;\">&quot;&gt;=&quot;<\/span> <span style=\"color: #66cc66;\">+<\/span> <span style=\"color: #ff6666;\">&quot;!=&quot;<\/span> <span style=\"color: #66cc66;\">+<\/span> <span style=\"color: #ff6666;\">&quot;==&quot;<\/span> <span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span> spc<\/pre><\/div><\/div><\/div>\n\n<p>Then add another nonterminal to the parser:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">BOOL <span style=\"color: #66cc66;\">=<\/span> Ct<span style=\"color: #66cc66;\">&#40;<\/span> Cc<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;bool&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;EXPR&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span> boolean <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;\">&#41;<\/span><\/pre><\/div><\/div><\/div>\n\n<p>Statement lists are easy enough, and they&#8217;ll become our new starting nonterminal, replacing STMT:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">LIST <span style=\"color: #66cc66;\">=<\/span>\n    V<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;STMT&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">+<\/span>\n    Ct<span style=\"color: #66cc66;\">&#40;<\/span> Cc<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;list&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span>\n            lcurly <span style=\"color: #66cc66;\">*<\/span>\n            V<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;STMT&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span> <span style=\"color: #66cc66;\">&#40;<\/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;STMT&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>\n            rcurly <span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">,<\/span><\/pre><\/div><\/div><\/div>\n\n<p>So a LIST is either a single STMT, or a series of them inside braces and separated by semicolons (<code>lcurly<\/code> and <code>rcurly<\/code> match left and right curly braces). Finally, here&#8217;s how we&#8217;ll define a conditional:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">IF <span style=\"color: #66cc66;\">=<\/span> Ct<span style=\"color: #66cc66;\">&#40;<\/span> C<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;if&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span> spc <span style=\"color: #66cc66;\">*<\/span> lparen <span style=\"color: #66cc66;\">*<\/span> V<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;BOOL&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span> rparen <span style=\"color: #66cc66;\">*<\/span> V<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;LIST&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">&#41;<\/span><\/pre><\/div><\/div><\/div>\n\n<p>All together, here&#8217;s our parser now:<\/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;LIST&quot;<\/span><span style=\"color: #66cc66;\">;<\/span>\n    LIST <span style=\"color: #66cc66;\">=<\/span>\n        V<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;STMT&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">+<\/span>\n        Ct<span style=\"color: #66cc66;\">&#40;<\/span> Cc<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;list&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span>\n                lcurly <span style=\"color: #66cc66;\">*<\/span>\n                V<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;STMT&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span> <span style=\"color: #66cc66;\">&#40;<\/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;STMT&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>\n                rcurly <span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">,<\/span>\n    STMT <span style=\"color: #66cc66;\">=<\/span> \n        Ct<span style=\"color: #66cc66;\">&#40;<\/span> Cc<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;assign&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;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;\">&#41;<\/span> <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        V<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;IF&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">,<\/span>\n    EXPR <span style=\"color: #66cc66;\">=<\/span> Ct<span style=\"color: #66cc66;\">&#40;<\/span> Cc<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;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;\">&#41;<\/span><span style=\"color: #66cc66;\">,<\/span>\n    TERM <span style=\"color: #66cc66;\">=<\/span> Ct<span style=\"color: #66cc66;\">&#40;<\/span> Cc<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> 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;\">&#41;<\/span><span style=\"color: #66cc66;\">,<\/span>\n    REF <span style=\"color: #66cc66;\">=<\/span> Ct<span style=\"color: #66cc66;\">&#40;<\/span> Cc<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> 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;\">&#41;<\/span><span style=\"color: #66cc66;\">,<\/span>\n    FACT <span style=\"color: #66cc66;\">=<\/span>\n        number <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>\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>\n    ARRAY <span style=\"color: #66cc66;\">=<\/span> Ct<span style=\"color: #66cc66;\">&#40;<\/span> Cc<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;array&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <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 <span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">,<\/span>\n    VAL_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><span style=\"color: #66cc66;\">,<\/span>\n    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><span style=\"color: #66cc66;\">,<\/span>\n    BOOL <span style=\"color: #66cc66;\">=<\/span> Ct<span style=\"color: #66cc66;\">&#40;<\/span> Cc<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;bool&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;EXPR&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span> boolean <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;\">&#41;<\/span><span style=\"color: #66cc66;\">,<\/span>\n    IF <span style=\"color: #66cc66;\">=<\/span> Ct<span style=\"color: #66cc66;\">&#40;<\/span> C<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;if&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span> spc <span style=\"color: #66cc66;\">*<\/span> lparen <span style=\"color: #66cc66;\">*<\/span> V<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;BOOL&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span> rparen <span style=\"color: #66cc66;\">*<\/span> V<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;LIST&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">&#41;<\/span>\n<span style=\"color: #66cc66;\">&#125;<\/span><\/pre><\/div><\/div><\/div>\n\n<p>There&#8217;s one final tweak to make. An &#8220;if&#8221; statement will actually be parsed as a name, and <code>eval<\/code> will try to look up the variable called &#8220;if.&#8221; We need to tell the <code>name<\/code> pattern to not recognize &#8220;if&#8221; as a name; this is the first <em>keyword<\/em> in our language (there will be more):<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">name <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\nkeywords <span style=\"color: #66cc66;\">=<\/span> P<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;if&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span> spc\nname <span style=\"color: #66cc66;\">=<\/span> name <span style=\"color: #66cc66;\">-<\/span> keywords<\/pre><\/div><\/div><\/div>\n\n<p>Parsing an example &#8220;if&#8221; statement like &#8220;if(a > 0) { 2+3; a=4*5 }&#8221; now gives this parse tree:<\/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: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;if&quot;<\/span><span style=\"color: #66cc66;\">,<\/span>\n  <span style=\"color: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;bool&quot;<\/span><span style=\"color: #66cc66;\">,<\/span>\n    <span style=\"color: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;expr&quot;<\/span><span style=\"color: #66cc66;\">,<\/span>\n      <span style=\"color: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;term&quot;<\/span><span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;ref&quot;<\/span><span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #ff6666;\">&quot;a&quot;<\/span> <span style=\"color: #66cc66;\">&#125;<\/span> <span style=\"color: #66cc66;\">&#125;<\/span> <span style=\"color: #66cc66;\">&#125;<\/span><span style=\"color: #66cc66;\">,<\/span>\n      <span style=\"color: #ff6666;\">&quot;&gt;&quot;<\/span><span style=\"color: #66cc66;\">,<\/span>\n      <span style=\"color: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;expr&quot;<\/span><span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;term&quot;<\/span><span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #cc66cc;\">0<\/span> <span style=\"color: #66cc66;\">&#125;<\/span> <span style=\"color: #66cc66;\">&#125;<\/span>\n    <span style=\"color: #66cc66;\">&#125;<\/span><span style=\"color: #66cc66;\">,<\/span>\n  <span style=\"color: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;list&quot;<\/span><span style=\"color: #66cc66;\">,<\/span>\n    <span style=\"color: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;expr&quot;<\/span><span style=\"color: #66cc66;\">,<\/span>\n      <span style=\"color: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;term&quot;<\/span><span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #cc66cc;\">2<\/span> <span style=\"color: #66cc66;\">&#125;<\/span><span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #ff6666;\">&quot;+&quot;<\/span><span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;term&quot;<\/span><span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #cc66cc;\">3<\/span> <span style=\"color: #66cc66;\">&#125;<\/span>\n    <span style=\"color: #66cc66;\">&#125;<\/span><span style=\"color: #66cc66;\">,<\/span>\n    <span style=\"color: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;assign&quot;<\/span><span style=\"color: #66cc66;\">,<\/span>\n      <span style=\"color: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;ref&quot;<\/span><span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #ff6666;\">&quot;a&quot;<\/span> <span style=\"color: #66cc66;\">&#125;<\/span><span style=\"color: #66cc66;\">,<\/span>\n      <span style=\"color: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;expr&quot;<\/span><span style=\"color: #66cc66;\">,<\/span>\n        <span style=\"color: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;term&quot;<\/span><span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #cc66cc;\">4<\/span><span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #ff6666;\">&quot;*&quot;<\/span><span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #cc66cc;\">5<\/span> <span style=\"color: #66cc66;\">&#125;<\/span>\n      <span style=\"color: #66cc66;\">&#125;<\/span>\n    <span style=\"color: #66cc66;\">&#125;<\/span>\n  <span style=\"color: #66cc66;\">&#125;<\/span>\n<span style=\"color: #66cc66;\">&#125;<\/span><\/pre><\/div><\/div><\/div>\n\n<h2>Evaluating conditionals<\/h2>\n<p>This is all obviously going to mean some changes to the <code>eval<\/code> function. We&#8217;ll have to add a function like <code>eval_expr<\/code> to handle boolean expressions, and two new options in <code>eval<\/code> to handle statement lists and &#8220;if&#8221; statements. Here&#8217;s how we do booleans:<\/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_bool<span style=\"color: #66cc66;\">&#40;<\/span>expr<span style=\"color: #66cc66;\">&#41;<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">local<\/span> num1 <span style=\"color: #66cc66;\">=<\/span> eval<span style=\"color: #66cc66;\">&#40;<\/span>expr<span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #cc66cc;\">2<\/span><span style=\"color: #66cc66;\">&#93;<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">local<\/span> operator <span style=\"color: #66cc66;\">=<\/span> expr<span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #cc66cc;\">3<\/span><span style=\"color: #66cc66;\">&#93;<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">local<\/span> num2 <span style=\"color: #66cc66;\">=<\/span> eval<span style=\"color: #66cc66;\">&#40;<\/span>expr<span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #cc66cc;\">4<\/span><span style=\"color: #66cc66;\">&#93;<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n&nbsp;\n    <span style=\"color: #aa9900; font-weight: bold;\">if<\/span> operator <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #ff6666;\">'&lt;'<\/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;\">&lt;<\/span> num2\n    <span style=\"color: #aa9900; font-weight: bold;\">elseif<\/span> operator <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #ff6666;\">'&lt;='<\/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;\">&lt;=<\/span> num2\n    <span style=\"color: #aa9900; font-weight: bold;\">elseif<\/span> operator <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #ff6666;\">'&gt;'<\/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;\">&gt;<\/span> num2\n    <span style=\"color: #aa9900; font-weight: bold;\">elseif<\/span> operator <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #ff6666;\">'&gt;='<\/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;\">&gt;=<\/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;\">end<\/span>\n<span style=\"color: #aa9900; font-weight: bold;\">end<\/span><\/pre><\/div><\/div><\/div>\n\n<p>This is a lot simpler than <code>eval_expr<\/code> because we know exactly how many arguments there will be: we can&#8217;t chain together booleans like we can EXPRs and TERMs.<\/p>\n<p>The two new paths through <code>eval<\/code> differ from the rest in one way: they&#8217;re not guaranteed to return anything. Statement lists and conditionals can&#8217;t be nested inside of other value-returning constructs (like EXPRs) so we won&#8217;t ever have to return a value from those to <code>eval<\/code> itself. 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>ast<span style=\"color: #66cc66;\">&#41;<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">if<\/span> <span style=\"color: #0000aa;\">type<\/span><span style=\"color: #66cc66;\">&#40;<\/span>ast<span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #ff6666;\">'number'<\/span> <span style=\"color: #aa9900; font-weight: bold;\">then<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> ast\n    <span style=\"color: #aa9900; font-weight: bold;\">elseif<\/span> ast<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: #ff6666;\">'expr'<\/span> <span style=\"color: #aa9900; font-weight: bold;\">or<\/span> ast<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: #ff6666;\">'term'<\/span> <span style=\"color: #aa9900; font-weight: bold;\">then<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> eval_expr<span style=\"color: #66cc66;\">&#40;<\/span>ast<span style=\"color: #66cc66;\">&#41;<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">elseif<\/span> ast<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: #ff6666;\">'array'<\/span> <span style=\"color: #aa9900; font-weight: bold;\">then<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">local<\/span> new <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;\">for<\/span> _<span style=\"color: #66cc66;\">,<\/span> el <span style=\"color: #aa9900; font-weight: bold;\">in<\/span> <span style=\"color: #0000aa;\">ipairs<\/span><span style=\"color: #66cc66;\">&#40;<\/span>ast<span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #cc66cc;\">2<\/span><span style=\"color: #66cc66;\">&#93;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #aa9900; font-weight: bold;\">do<\/span>\n            <span style=\"color: #0000aa;\">table.insert<\/span><span style=\"color: #66cc66;\">&#40;<\/span>new<span style=\"color: #66cc66;\">,<\/span> eval<span style=\"color: #66cc66;\">&#40;<\/span>el<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;\">return<\/span> new\n    <span style=\"color: #aa9900; font-weight: bold;\">elseif<\/span> ast<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: #ff6666;\">'ref'<\/span> <span style=\"color: #aa9900; font-weight: bold;\">then<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> lookup<span style=\"color: #66cc66;\">&#40;<\/span>ast<span style=\"color: #66cc66;\">&#41;<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">elseif<\/span> ast<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: #ff6666;\">'assign'<\/span> <span style=\"color: #aa9900; font-weight: bold;\">then<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> assign<span style=\"color: #66cc66;\">&#40;<\/span>ast<span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #cc66cc;\">2<\/span><span style=\"color: #66cc66;\">&#93;<\/span><span style=\"color: #66cc66;\">,<\/span> eval<span style=\"color: #66cc66;\">&#40;<\/span>ast<span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #cc66cc;\">3<\/span><span style=\"color: #66cc66;\">&#93;<\/span><span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">&#41;<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">elseif<\/span> ast<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: #ff6666;\">'list'<\/span> <span style=\"color: #aa9900; font-weight: bold;\">then<\/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>ast <span style=\"color: #aa9900; font-weight: bold;\">do<\/span>\n            eval<span style=\"color: #66cc66;\">&#40;<\/span>ast<span style=\"color: #66cc66;\">&#91;<\/span>i<span style=\"color: #66cc66;\">&#93;<\/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;\">elseif<\/span> ast<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: #ff6666;\">'if'<\/span> <span style=\"color: #aa9900; font-weight: bold;\">then<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">if<\/span> eval_bool<span style=\"color: #66cc66;\">&#40;<\/span>ast<span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #cc66cc;\">2<\/span><span style=\"color: #66cc66;\">&#93;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #aa9900; font-weight: bold;\">then<\/span>\n            <span style=\"color: #aa9900; font-weight: bold;\">return<\/span> eval<span style=\"color: #66cc66;\">&#40;<\/span>ast<span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #cc66cc;\">3<\/span><span style=\"color: #66cc66;\">&#93;<\/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>\n<span style=\"color: #aa9900; font-weight: bold;\">end<\/span><\/pre><\/div><\/div><\/div>\n\n<p>Evaluating a list just means evaluating everything in it, and evaluating an &#8220;if&#8221; means <code>eval_bool<\/code>-ing the condition, then evaluating the body <em>only if it&#8217;s true<\/em>. This means we can now stick this in the bottom of <code>test<\/code> and it will pass:<\/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;if(1 &lt; 0) b = 5&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>b <span style=\"color: #66cc66;\">~=<\/span> <span style=\"color: #cc66cc;\">5<\/span><span style=\"color: #66cc66;\">&#41;<\/span><\/pre><\/div><\/div><\/div>\n\n<p>Because 1 is not less than 0, the part of the AST that does the assignment is never run, and nothing gets assigned to &#8220;b&#8221;.<\/p>\n<h2>Loops<\/h2>\n<p>We can implement loops almost the same way. First we modify the parser to parse loops, which is already mostly done, since it&#8217;s the same general thing as conditionals:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">WHILE <span style=\"color: #66cc66;\">=<\/span> Ct<span style=\"color: #66cc66;\">&#40;<\/span> C<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;while&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span> spc <span style=\"color: #66cc66;\">*<\/span> lparen <span style=\"color: #66cc66;\">*<\/span> V<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;BOOL&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span> rparen <span style=\"color: #66cc66;\">*<\/span> V<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;LIST&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">&#41;<\/span><\/pre><\/div><\/div><\/div>\n\n<p>Add &#8220;while&#8221; to the list of keywords:<\/p>\n\n<div class=\"my_syntax_box\"><div class=\"my_syntax\"><div class=\"code\"><pre class=\"lua\" style=\"font-family:monospace;\">keywords <span style=\"color: #66cc66;\">=<\/span> <span style=\"color: #66cc66;\">&#40;<\/span>P<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;if&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">+<\/span>P<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;while&quot;<\/span><span style=\"color: #66cc66;\">&#41;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #66cc66;\">*<\/span> spc<\/pre><\/div><\/div><\/div>\n\n<p>And we should be able to parse loops:<\/p>\n<pre>\r\nwhile(n<10) {\r\n  n = n+1\r\n}\r\n<\/pre>\n<p>turns into<\/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: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;while&quot;<\/span><span style=\"color: #66cc66;\">,<\/span>\n  <span style=\"color: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;bool&quot;<\/span><span style=\"color: #66cc66;\">,<\/span>\n    <span style=\"color: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;expr&quot;<\/span><span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;term&quot;<\/span><span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;ref&quot;<\/span><span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #ff6666;\">&quot;n&quot;<\/span> <span style=\"color: #66cc66;\">&#125;<\/span> <span style=\"color: #66cc66;\">&#125;<\/span> <span style=\"color: #66cc66;\">&#125;<\/span><span style=\"color: #66cc66;\">,<\/span>\n    <span style=\"color: #ff6666;\">&quot;&lt;&quot;<\/span><span style=\"color: #66cc66;\">,<\/span>\n    <span style=\"color: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;expr&quot;<\/span><span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;term&quot;<\/span><span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #cc66cc;\">10<\/span> <span style=\"color: #66cc66;\">&#125;<\/span> <span style=\"color: #66cc66;\">&#125;<\/span>\n  <span style=\"color: #66cc66;\">&#125;<\/span><span style=\"color: #66cc66;\">,<\/span>\n  <span style=\"color: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;list&quot;<\/span><span style=\"color: #66cc66;\">,<\/span>\n    <span style=\"color: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;assign&quot;<\/span><span style=\"color: #66cc66;\">,<\/span>\n      <span style=\"color: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;ref&quot;<\/span><span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #ff6666;\">&quot;n&quot;<\/span> <span style=\"color: #66cc66;\">&#125;<\/span><span style=\"color: #66cc66;\">,<\/span>\n      <span style=\"color: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;expr&quot;<\/span><span style=\"color: #66cc66;\">,<\/span>\n        <span style=\"color: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;term&quot;<\/span><span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;ref&quot;<\/span><span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #ff6666;\">&quot;n&quot;<\/span> <span style=\"color: #66cc66;\">&#125;<\/span> <span style=\"color: #66cc66;\">&#125;<\/span><span style=\"color: #66cc66;\">,<\/span>\n        <span style=\"color: #ff6666;\">&quot;+&quot;<\/span><span style=\"color: #66cc66;\">,<\/span>\n        <span style=\"color: #66cc66;\">&#123;<\/span> <span style=\"color: #ff6666;\">&quot;term&quot;<\/span><span style=\"color: #66cc66;\">,<\/span> <span style=\"color: #cc66cc;\">1<\/span> <span style=\"color: #66cc66;\">&#125;<\/span>\n      <span style=\"color: #66cc66;\">&#125;<\/span>\n    <span style=\"color: #66cc66;\">&#125;<\/span>\n  <span style=\"color: #66cc66;\">&#125;<\/span>\n<span style=\"color: #66cc66;\">&#125;<\/span><\/pre><\/div><\/div><\/div>\n\n<p>Now we just need the <code>eval<\/code> function to actually run the loops. We'll do this in much the same way as the conditionals. Add a case to <code>eval<\/code> to handle \"while\" nodes:<\/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>ast<span style=\"color: #66cc66;\">&#41;<\/span>\n    <span style=\"color: #808080; font-style: italic;\">-- stuff elided --<\/span>\n    <span style=\"color: #aa9900; font-weight: bold;\">elseif<\/span> ast<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: #ff6666;\">'while'<\/span> <span style=\"color: #aa9900; font-weight: bold;\">then<\/span>\n        <span style=\"color: #aa9900; font-weight: bold;\">while<\/span> eval_bool<span style=\"color: #66cc66;\">&#40;<\/span>ast<span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #cc66cc;\">2<\/span><span style=\"color: #66cc66;\">&#93;<\/span><span style=\"color: #66cc66;\">&#41;<\/span> <span style=\"color: #aa9900; font-weight: bold;\">do<\/span>\n            eval<span style=\"color: #66cc66;\">&#40;<\/span>ast<span style=\"color: #66cc66;\">&#91;<\/span><span style=\"color: #cc66cc;\">3<\/span><span style=\"color: #66cc66;\">&#93;<\/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>\n<span style=\"color: #aa9900; font-weight: bold;\">end<\/span><\/pre><\/div><\/div><\/div>\n\n<p>And now we can write a unit test for this:<\/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>n<span style=\"color: #66cc66;\">=<\/span><span style=\"color: #cc66cc;\">0<\/span><span style=\"color: #66cc66;\">;<\/span> VARS<span style=\"color: #66cc66;\">.<\/span>x<span style=\"color: #66cc66;\">=<\/span><span style=\"color: #cc66cc;\">1<\/span>\nstmt<span style=\"color: #66cc66;\">:<\/span>match<span style=\"color: #66cc66;\">&#40;<\/span><span style=\"color: #ff6666;\">&quot;while(n &lt; 8) { x = x * 2; n = n + 1 }&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>x <span style=\"color: #66cc66;\">==<\/span> <span style=\"color: #cc66cc;\">256<\/span><span style=\"color: #66cc66;\">&#41;<\/span><\/pre><\/div><\/div><\/div>\n\n<h2>Next steps<\/h2>\n<p>So, now that we've separated parsing our language from running programs we've parsed, we can easily add new features like control structures. Most new features you might want to add follow this basic pattern: modify the parser to recognize it, then modify the evaluator to run the parse tree. And that's mostly what we're going to do next time too: we'll modify the parser to recognize function definitions, and we'll modify the evaluator to store and call them.<\/p>\n<p>As always, the completed code for this chapter is available <a onclick=\"javascript:pageTracker._trackPageview('\/outgoing\/gist.github.com\/randrews\/c0e712b48bde007dd21e');\"  href=\"https:\/\/gist.github.com\/randrews\/c0e712b48bde007dd21e\">here<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is part three of my series on writing a toy programming language using LPeg. You should start with part one here. Last time, we added variables and arrays to the language. Assigning to arrays was starting to strain our design some, so this time we&#8217;ll refactor it a lot, and add two features that [&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\/70"}],"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=70"}],"version-history":[{"count":0,"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=\/wp\/v2\/posts\/70\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=70"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=70"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.playwithlua.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=70"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}