mirror of
https://github.com/jamiebuilds/the-super-tiny-compiler.git
synced 2024-10-27 20:34:08 +00:00
Add traverser inline annotations
This commit is contained in:
parent
d3a5ab209a
commit
7fa8ab691f
@ -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 <code>traverser</code> 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
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* ============================================================================
|
||||
* ⁽(◍˃̵͈̑ᴗ˂̵͈̑)⁽
|
||||
|
Loading…
Reference in New Issue
Block a user