Online Book Reader

Home Category

Beautiful Code [144]

By Root 5200 0

advance("}");

this.arity = "function";

scope.pop( );

return this;

});

Functions are invoked with the ( operator. It can take zero or more comma-separated arguments. We look at the left operand to detect expressions that cannot possibly be function values:

Code View: Scroll / Show All

infix("(", 90, function (left) {

var a = [];

this.first = left;

this.second = a;

this.arity = "binary";

if ((left.arity !== "unary" ||

left.id !== "function") &&

left.arity !== "name" &&

(left.arity !== "binary" ||

(left.id !== "." &&

left.id !== "(" &&

left.id !== "["))) {

left.error("Expected a variable name.");

}

if (token.id !== ")") {

while (true) {

a.push(expression(0));

if (token.id !== ",") {

break;

}

advance(",");

}

}

advance(")");

return this;

});

Top Down Operator Precedence > Array and Object Literals

9.13. Array and Object Literals

An array literal is a set of square brackets around zero or more comma-separated expressions. Each of the expressions is evaluated, and the results are collected into a new array:

prefix("[", function ( ) {

var a = [];

if (token.id !== "]") {

while (true) {

a.push(expression(0));

if (token.id !== ",") {

break;

}

advance(",");

}

}

advance("]");

this.first = a;

this.arity = "unary";

return this;

});

An object literal is a set of curly braces around zero or more comma-separated pairs. A pair is a key/expression pair separated by a :. The key is a literal or a name treated as a literal:

Code View: Scroll / Show All

prefix("{", function ( ) {

var a = [];

if (token.id !== "}") {

while (true) {

var n = token;

if (n.arity !== "name" && n.arity !== "literal") {

token.error("Bad key.");

}

advance( );

advance(":");

var v = expression(0);

v.key = n.value;

a.push(v);

if (token.id !== ",") {

break;

}

advance(",");

}

}

advance("}");

this.first = a;

this.arity = "unary";

return this;

});

Top Down Operator Precedence > Things to Do and Think About

9.14. Things to Do and Think About

The simple parser shown in this chapter is easily extensible. The tree could be passed to a code generator, or it could be passed to an interpreter. Very little computation is required to produce the tree. And as we saw, very little effort was required to write the programming that built the tree.

We could make the infix function take an opcode that would aid in code generation. We could also have it take additional methods that would be used to do constant folding and code generation.

We could add additional statements, such as for, switch, and try. We could add statement labels. We could add more error checking and error recovery. We could add lots more operators. We could add type specification and inference.

We could make our language extensible. With the same ease that we can define new variables, we can let the programmer add new operators and new statements.

You can try the demonstration of the parser that was described in this chapter at http://javascript.crockford.com/tdop/index.html.

Another example of this parsing technique can be found in JSLint at http://JSLint.com.

The Quest for an Accelerated Population Count > Basic Methods

10. The Quest for an Accelerated Population Count

Henry S. Warren, Jr.

A fundamental computer algorithm, and a deceptively simple one, is the population count or sideways sum, which calculates the number of bits in a computer word that are 1. The population count function has applications that range from the very simple to the quite sublime. For example, if sets are represented by bit strings, population count gives the size of the set. It can also be used to generate binomially distributed random integers. These and other applications are discussed at the end of this chapter.

Although uses of this operation are not terribly common, many computers—often the supercomputers of their day—had an instruction for it. These included the Ferranti Mark I (1951), the IBM

Return Main Page Previous Page Next Page

®Online Book Reader