diff options
author | kpdecker <kpdecker@gmail.com> | 2014-08-23 16:29:22 -0500 |
---|---|---|
committer | kpdecker <kpdecker@gmail.com> | 2014-08-23 16:29:22 -0500 |
commit | 529e2b67960dba2e41122fc4d56b5c2af5ada9a5 (patch) | |
tree | 9b4af5981298bccc8e90d57b66773da7b7a1543f /lib/handlebars/compiler/ast.js | |
parent | 3531e041174509c6c3c69417b1714dcda6bccb3e (diff) | |
parent | eee2c4d4f29e233280907bc89a32556de66fe783 (diff) | |
download | handlebars.js-529e2b67960dba2e41122fc4d56b5c2af5ada9a5.zip handlebars.js-529e2b67960dba2e41122fc4d56b5c2af5ada9a5.tar.gz handlebars.js-529e2b67960dba2e41122fc4d56b5c2af5ada9a5.tar.bz2 |
Merge branch 'refactor-parser' of github.com:mmun/handlebars.js into mmun-refactor-parser
Conflicts:
lib/handlebars/compiler/ast.js
spec/ast.js
src/handlebars.yy
Diffstat (limited to 'lib/handlebars/compiler/ast.js')
-rw-r--r-- | lib/handlebars/compiler/ast.js | 178 |
1 files changed, 6 insertions, 172 deletions
diff --git a/lib/handlebars/compiler/ast.js b/lib/handlebars/compiler/ast.js index ae5ea63..5a47e2b 100644 --- a/lib/handlebars/compiler/ast.js +++ b/lib/handlebars/compiler/ast.js @@ -1,6 +1,6 @@ import Exception from "../exception"; -function LocationInfo(locInfo){ +function LocationInfo(locInfo) { locInfo = locInfo || {}; this.firstLine = locInfo.first_line; this.firstColumn = locInfo.first_column; @@ -9,41 +9,11 @@ function LocationInfo(locInfo){ } var AST = { - ProgramNode: function(isRoot, statements, inverseStrip, inverse, locInfo) { - var inverseLocationInfo, firstInverseNode; - if (arguments.length === 4) { - locInfo = inverse; - inverse = null; - } else if (arguments.length === 3) { - locInfo = inverseStrip; - inverseStrip = null; - } - + ProgramNode: function(statements, strip, locInfo) { LocationInfo.call(this, locInfo); this.type = "program"; this.statements = statements; - this.strip = {}; - - if(inverse) { - firstInverseNode = inverse[0]; - if (firstInverseNode) { - inverseLocationInfo = { - first_line: firstInverseNode.firstLine, - last_line: firstInverseNode.lastLine, - last_column: firstInverseNode.lastColumn, - first_column: firstInverseNode.firstColumn - }; - this.inverse = new AST.ProgramNode(isRoot, inverse, inverseStrip, inverseLocationInfo); - } else { - this.inverse = new AST.ProgramNode(isRoot, inverse, inverseStrip); - } - this.strip.right = inverseStrip.left; - } else if (inverseStrip) { - this.strip.left = inverseStrip.right; - } - - // Scan all children to complete the standalone analysis - checkStandalone(this, isRoot, statements); + this.strip = strip; }, MustacheNode: function(rawParams, hash, open, strip, locInfo) { @@ -111,43 +81,14 @@ var AST = { this.strip.inlineStandalone = true; }, - BlockNode: function(mustache, program, inverse, close, locInfo) { + BlockNode: function(mustache, program, inverse, strip, locInfo) { LocationInfo.call(this, locInfo); - if(mustache.sexpr.id.original !== close.path.original) { - throw new Exception(mustache.sexpr.id.original + " doesn't match " + close.path.original, this); - } - this.type = 'block'; this.mustache = mustache; this.program = program; this.inverse = inverse; - - var firstChild = program || inverse, - lastChild = inverse || program; - - this.strip = { - left: mustache.strip.left, - right: close.strip.right, - - // Determine the standalone candiacy. Basically flag our content as being possibly standalone - // so our parent can determine if we actually are standalone - openStandalone: isNextWhitespace(firstChild), - closeStandalone: isPrevWhitespace(lastChild) - }; - - // Calculate stripping for any else statements - firstChild.strip.left = mustache.strip.right; - lastChild.strip.right = close.strip.left; - - // Find standalone else statments - if (program && inverse - && isPrevWhitespace(program) - && isNextWhitespace(inverse)) { - - omitLeft(program); - omitRight(inverse); - } + this.strip = strip; if (inverse && !program) { this.isInverse = true; @@ -165,7 +106,7 @@ var AST = { this.type = 'block'; this.mustache = mustache; - this.program = new AST.ProgramNode(false, [content], locInfo); + this.program = new AST.ProgramNode([content], {}, locInfo); }, ContentNode: function(string, locInfo) { @@ -269,113 +210,6 @@ var AST = { }; -function checkStandalone(program, isRoot, statements) { - for (var i = 0, l = statements.length; i < l; i++) { - var current = statements[i], - strip = current.strip; - - if (!strip) { - continue; - } - - var _isPrevWhitespace = isPrevWhitespace(program, i, isRoot, current.type === 'partial'), - _isNextWhitespace = isNextWhitespace(program, i, isRoot); - strip.openStandalone = strip.openStandalone && _isPrevWhitespace; - strip.closeStandalone = strip.closeStandalone && _isNextWhitespace; - strip.inlineStandalone = strip.inlineStandalone && _isPrevWhitespace && _isNextWhitespace; - - if (strip.inlineStandalone) { - omitRight(program, i); - - if (omitLeft(program, i)) { - // If we are on a standalone node, save the indent info for partials - if (current.type === 'partial') { - current.indent = statements[i-1].string; - } - } - } - if (strip.openStandalone) { - omitRight(current.program || current.inverse); - - // Strip out the previous content node if it's whitespace only - omitLeft(program, i); - } - if (strip.closeStandalone) { - // Always strip the next node - omitRight(program, i); - - omitLeft(current.inverse || current.program); - } - } -} -function isPrevWhitespace(parent, i, isRoot, disallowIndent) { - var statements = parent.statements; - if (i === undefined) { - i = statements.length; - } - - // Nodes that end with newlines are considered whitespace (but are special - // cased for strip operations) - var prev = statements[i-1]; - if (prev && /\n$/.test(prev.string)) { - return true; - } - - return checkWhitespace(isRoot, prev, statements[i-2]); -} -function isNextWhitespace(parent, i, isRoot) { - var statements = parent.statements; - if (i === undefined) { - i = -1; - } - - return checkWhitespace(isRoot, statements[i+1], statements[i+2]); -} -function checkWhitespace(isRoot, next1, next2, disallowIndent) { - if (!next1) { - return isRoot; - } else if (next1.type === 'content') { - // Check if the previous node is empty or whitespace only - if (disallowIndent ? !next1.string : /^[\s]*$/.test(next1.string)) { - if (next2) { - return next2.type === 'content' || /\n$/.test(next1.string); - } else { - return isRoot || (next1.string.indexOf('\n') >= 0); - } - } - } -} - -// Marks the node to the right of the position as omitted. -// I.e. " "{{foo}} will mark the " " node as omitted. -// -// If i is undefined, then the first child will be marked as such. -function omitRight(program, i) { - var first = program.statements[i == null ? 0 : i + 1]; - if (first) { - first.omit = true; - } -} - -// Marks the node to the left of the position as omitted. -// I.e. " "{{foo}} will mark the " " node as omitted. -// -// If i is undefined then the last child will be marked as such. -function omitLeft(program, i) { - var statements = program.statements; - if (i === undefined) { - i = statements.length; - } - - var last = statements[i-1], - prev = statements[i-2]; - - // We omit the last node if it's whitespace only and not preceeded by a non-content node. - if (last && /^[\s]*$/.test(last.string) && (!prev || prev.type === 'content')) { - return last.omit = true; - } -} - // Must be exported as an object rather than the root of the module as the jison lexer // most modify the object to operate properly. export default AST; |