Online Book Reader

Home Category

Beautiful Code [143]

By Root 5145 0

advance( );

scope.reserve(n);

return n.std( );

}

v = expression(0);

if (!v.assignment && v.id !== "(") {

v.error("Bad expression statement.");

}

advance(";");

return v;

};

The statements function parses statements until it sees (end) or } signaling the end of a block. It returns a statement, an array of statements, or (if there were no statements present) simply null:

var statements = function ( ) {

var a = [], s;

while (true) {

if (token.id === "}" || token.id === "(end)") {

break;

}

s = statement( );

if (s) {

a.push(s);

}

}

return a.length === 0 ? null : a.length === 1 ? a[0] : a;

};

The stmt function is used to add statements to the symbol table. It takes a statement id and an std function:

var stmt = function (s, f) {

var x = symbol(s);

x.std = f;

return x;

};

The block statement wraps a pair of curly braces around a list of statements, giving them a new scope:

stmt("{", function ( ) {

new_scope( );

var a = statements( );

advance("}");

scope.pop( );

return a;

});

The block function parses a block:

var block = function ( ) {

var t = token;

advance("{");

return t.std( );

};

The var statement defines one or more variables in the current block. Each name can optionally be followed by = and an expression:

Code View: Scroll / Show All

stmt("var", function ( ) {

var a = [], n, t;

while (true) {

n = token;

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

n.error("Expected a new variable name.");

}

scope.define(n);

advance( );

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

t = token;

advance("=");

t.first = n;

t.second = expression(0);

t.arity = "binary";

a.push(t);

}

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

break;

}

advance(",");

}

advance(";");

return a.length === 0 ? null : a.length === 1 ? a[0] : a;

});

The while statement defines a loop. It contains an expression in parentheses and a block:

stmt("while", function ( ) {

advance("(");

this.first = expression(0);

advance(")");

this.second = block( );

this.arity = "statement";

return this;

});

The if statement allows for conditional execution. If we see the else symbol after the block, we parse the next block or if statement:

stmt("if", function ( ) {

advance("(");

this.first = expression(0);

advance(")");

this.second = block( );

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

scope.reserve(token);

advance("else");

this.third = token.id === "if" ? statement() : block( );

}

this.arity = "statement";

return this;

});

The break statement is used to break out of loops. We make sure that the next symbol is }:

stmt("break", function ( ) {

advance(";");

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

token.error("Unreachable statement.");

}

this.arity = "statement";

return this;

});

The return statement is used to return from functions. It can return an optional expression:

stmt("return", function ( ) {

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

this.first = expression(0);

}

advance(";");

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

token.error("Unreachable statement.");

}

this.arity = "statement";

return this;

});

Top Down Operator Precedence > Functions

9.12. Functions

Functions are executable object values. A function has an optional name (so that it can call itself recursively), a list of parameter names wrapped in parentheses, and a body that is a list of statements wrapped in curly braces. A function has its own scope:

Code View: Scroll / Show All

prefix("function", function ( ) {

var a = [];

scope = new_scope( );

if (token.arity === "name") {

scope.define(token);

this.name = token.value;

advance( );

}

advance("(");

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

while (true) {

if (token.arity !== "name") {

token.error("Expected a parameter name.");

}

scope.define(token);

a.push(token);

advance( );

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

break;

}

advance(",");

}

}

this.first = a;

advance(")");

advance("{");

this.second = statements( );

Return Main Page Previous Page Next Page

®Online Book Reader