From 7fa8ab691fa5433272867c12cf0287bab20e1b5f Mon Sep 17 00:00:00 2001 From: James Kyle Date: Thu, 31 Mar 2016 01:11:16 -0700 Subject: [PATCH] Add traverser inline annotations --- super-tiny-compiler.js | 70 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 60 insertions(+), 10 deletions(-) diff --git a/super-tiny-compiler.js b/super-tiny-compiler.js index 1b8f81e..c414c2c 100644 --- a/super-tiny-compiler.js +++ b/super-tiny-compiler.js @@ -329,9 +329,11 @@ */ /** - * We're gonna start off with our first phase of parsing--lexical analysis--with the tokenizer. + * We're gonna start off with our first phase of parsing, lexical analysis, with + * the tokenizer. * - * We're just going to take our string of code and break it down into an array of tokens. + * We're just going to take our string of code and break it down into an array + * of tokens. * * (add 2 (subtract 4 2)) => [{ type: 'paren', value: '(' }, ...] */ @@ -621,14 +623,6 @@ function parser(tokens) { return ast; } -/** - * ---------------------------------------------------------------------------- - * *Note:* This is all I've written so far, so the code below isn't annnotated - * yet. You can still read it all and it totally works, but I plan on improving - * this in the near future - * ---------------------------------------------------------------------------- - */ - /** * ============================================================================ * ⌒(❀>◞౪◟<❀)⌒ @@ -636,38 +630,94 @@ function parser(tokens) { * ============================================================================ */ +/** + * So now we have our AST, and we want to be able to visit different nodes with + * a visitor. We need to be able to call the methods on the visitor whenever we + * encounter a node with a matching type. + * + * traverse(ast, { + * Program(node, parent) { + * // ... + * }, + * + * CallExpression(node, parent) { + * // ... + * }, + * + * NumberLiteral(node, parent) { + * // ... + * } + * }); + */ + +// So we define a traverser function which accepts an AST and a +// visitor. Inside we're going to define two functions... function traverser(ast, visitor) { + // A `traverseArray` function that will allow us to iterate over an array and + // call the next function that we will define: `traverseNode`. function traverseArray(array, parent) { array.forEach(function(child) { traverseNode(child, parent); }); } + // `traverseNode` will accept a `node` and its `parent` node. So that it can + // pass both to our visitor methods. function traverseNode(node, parent) { + + // We start by testing for the existance of a method on the visitor with a + // matching `type`. var method = visitor[node.type]; + // If it exists we'll call it with the `node` and its `parent`. if (method) { method(node, parent); } + // Next we are going to split things up by the current node type. switch (node.type) { + + // We'll start with our top level `Program`. Since Program nodes have a + // property named body that has an array of nodes, we will call + // `traverseArray` to traverse down into them. + // + // (Remember that `traverseArray` will in turn call `traverseNode` so we + // are causing the tree to be traversed recursively) case 'Program': traverseArray(node.body, node); break; + + // Next we do the same will `CallExpressions` and traverse their `params`. case 'CallExpression': traverseArray(node.params, node); break; + + // In the case of `NumberLiterals` we don't have any child nodes to visit, + // so we'll just break. case 'NumberLiteral': break; + + // And again, if we haven't recognized the node type then we'll throw an + // error. default: throw new TypeError(node.type); } } + // Finally we kickstart the traverser by calling `traverseNode` with our ast + // with no `parent` because the top level of the AST doesn't have a parent. traverseNode(ast, null); } +/** + * ---------------------------------------------------------------------------- + * *Note:* This is all I've written so far, so the code below isn't annnotated + * yet. You can still read it all and it totally works, but I plan on improving + * this in the near future + * ---------------------------------------------------------------------------- + */ + /** * ============================================================================ * ⁽(◍˃̵͈̑ᴗ˂̵͈̑)⁽