Note that there are some explanatory texts on larger screens.

plurals
  1. POCrockfords Top Down Operator Precedence
    text
    copied!<p>Out of interest, i want to learn how to write a parser for a simple language, to ultimately write an interpreter for my own little code-golfing language, as soon as i understood how such things work in general.</p> <p>So I started reading Douglas Crockfords article <a href="http://javascript.crockford.com/tdop/tdop.html">Top Down Operator Precedence</a>.</p> <p><em>Note: You should probably read the article if you want a deeper understanding of the context of the code snippets below</em></p> <p>I have trouble understanding how the <code>var</code> statement and the assignment operator <code>=</code> should work together.</p> <p>D.C. defines an assignment operator like</p> <pre><code>var assignment = function (id) { return infixr(id, 10, function (left) { if (left.id !== "." &amp;&amp; left.id !== "[" &amp;&amp; left.arity !== "name") { left.error("Bad lvalue."); } this.first = left; this.second = expression(9); this.assignment = true; this.arity = "binary"; return this; }); }; assignment("="); </code></pre> <p><em>Note: [[value]] refers to a token, simplified to its value</em> </p> <p>Now if the expression function reaches e.g. <code>[[t]],[[=]],[[2]]</code>,the result of <code>[[=]].led</code> is something like this. </p> <pre><code>{ "arity": "binary", "value": "=", "assignment": true, //&lt;- "first": { "arity": "name", "value": "t" }, "second": { "arity": "literal", "value": "2" } } </code></pre> <p>D.C. makes the <code>assignment</code> function because </p> <blockquote> <p>we want it to do two extra bits of business: examine the left operand to make sure that it is a proper lvalue, and <strong>set an assignment member</strong> so that we can <strong>later quickly identify</strong> assignment statements.</p> </blockquote> <p>Which makes sense to me up to the point where he introduces the <code>var</code> statement, which is defined as follows.</p> <blockquote> <p>The var statement defines one or more variables in the current block. Each name can optionally be followed by = and an initializing expression. </p> </blockquote> <pre><code>stmt("var", function () { var a = [], n, t; while (true) { n = token; if (n.arity !== "name") { n.error("Expected a new variable name."); } scope.define(n); advance(); if (token.id === "=") { t = token; advance("="); t.first = n; t.second = expression(0); t.arity = "binary"; a.push(t); } if (token.id !== ",") { break; } advance(","); } advance(";"); return a.length === 0 ? null : a.length === 1 ? a[0] : a; }); </code></pre> <p>Now if the parser reaches a set of tokens like <code>[[var]],[[t]],[[=]],[[1]]</code> the generated tree would look something like.</p> <pre><code>{ "arity": "binary", "value": "=", "first": { "arity": "name", "value": "t" }, "second": { "arity": "literal", "value": "1" } } </code></pre> <p><strong>The keypart of my question is the <code>if (token.id === "=") {...}</code> part.</strong></p> <p>I don't understand why we call </p> <pre><code> t = token; advance("="); t.first = n; t.second = expression(0); t.arity = "binary"; a.push(t); </code></pre> <p>rather than </p> <pre><code> t = token; advance("="); t.led (n); a.push(t); </code></pre> <p>in the <code>...</code> part.</p> <p>which would call our <code>[[=]]</code> operators <code>led</code> function <em>(the assignment function)</em>, which does</p> <blockquote> <p>make sure that it is a proper lvalue, and <strong>set an assignment member</strong> so that we can <strong>later quickly identify</strong> assignment statements. <em>e.g</em> </p> </blockquote> <pre><code>{ "arity": "binary", "value": "=", "assignment": true, "first": { "arity": "name", "value": "t" }, "second": { "arity": "literal", "value": "1" } } </code></pre> <p><em>since there is no operator with a <code>lbp</code> between 0 and 10, calling <code>expression(0) vs. expression (9)</code> makes no difference. (<code>!(0&lt;0) &amp;&amp; !(9&lt;0) &amp;&amp; 0&lt;10 &amp;&amp; 9&lt;10)</code>)</em> </p> <p><em>And the <code>token.id === "="</code> condition prevents assignments to an object member as <code>token.id</code> would either be <code>'['</code> or <code>'.'</code> and <code>t.led</code> wouldn't be called.</em> </p> <p>My question in short is: </p> <p><strong>Why do we not call the, optionally after a variable declaration followable, assignment operators' available <code>led</code> function. But instead manually set the <code>first</code> and <code>second</code> members of the statement but not the <code>assignment</code> member ?</strong></p> <p>Here are two fiddles parsing a simple string. Using the <a href="http://jsfiddle.net/jYLYr/">original</a> code and one using the <a href="http://jsfiddle.net/hQXFT/">assignment</a> operators <code>led</code>.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload