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: '(' }, ...]
|
* (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
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ============================================================================
|
* ============================================================================
|
||||||
* ⁽(◍˃̵͈̑ᴗ˂̵͈̑)⁽
|
* ⁽(◍˃̵͈̑ᴗ˂̵͈̑)⁽
|
||||||
|
Loading…
Reference in New Issue
Block a user