Add traverser inline annotations

This commit is contained in:
James Kyle 2016-03-31 01:11:16 -07:00
parent d3a5ab209a
commit 7fa8ab691f

View File

@ -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: '(' }, ...] * (add 2 (subtract 4 2)) => [{ type: 'paren', value: '(' }, ...]
*/ */
@ -621,14 +623,6 @@ function parser(tokens) {
return ast; 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 <code>traverser</code> function which accepts an AST and a
// visitor. Inside we're going to define two functions...
function traverser(ast, visitor) { 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) { function traverseArray(array, parent) {
array.forEach(function(child) { array.forEach(function(child) {
traverseNode(child, parent); 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) { 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]; var method = visitor[node.type];
// If it exists we'll call it with the `node` and its `parent`.
if (method) { if (method) {
method(node, parent); method(node, parent);
} }
// Next we are going to split things up by the current node type.
switch (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': case 'Program':
traverseArray(node.body, node); traverseArray(node.body, node);
break; break;
// Next we do the same will `CallExpressions` and traverse their `params`.
case 'CallExpression': case 'CallExpression':
traverseArray(node.params, node); traverseArray(node.params, node);
break; break;
// In the case of `NumberLiterals` we don't have any child nodes to visit,
// so we'll just break.
case 'NumberLiteral': case 'NumberLiteral':
break; break;
// And again, if we haven't recognized the node type then we'll throw an
// error.
default: default:
throw new TypeError(node.type); 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); 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
* ----------------------------------------------------------------------------
*/
/** /**
* ============================================================================ * ============================================================================
* (˃̵͈̑˂̵͈̑) * (˃̵͈̑˂̵͈̑)