diff options
author | kpdecker <kpdecker@gmail.com> | 2014-11-26 12:46:38 -0600 |
---|---|---|
committer | kpdecker <kpdecker@gmail.com> | 2014-11-26 19:04:18 -0600 |
commit | 2a4819d75cba7513946af5cf28ee22881561814f (patch) | |
tree | 6f88ee441e493e1d1f928598112a158400d500c8 | |
parent | 5cfe6a0be16a912a5f00af251753a3d5746a6577 (diff) | |
download | handlebars.js-2a4819d75cba7513946af5cf28ee22881561814f.zip handlebars.js-2a4819d75cba7513946af5cf28ee22881561814f.tar.gz handlebars.js-2a4819d75cba7513946af5cf28ee22881561814f.tar.bz2 |
Update statement node ASTs
-rw-r--r-- | lib/handlebars/compiler/ast.js | 81 | ||||
-rw-r--r-- | lib/handlebars/compiler/compiler.js | 99 | ||||
-rw-r--r-- | lib/handlebars/compiler/helpers.js | 22 | ||||
-rw-r--r-- | lib/handlebars/compiler/printer.js | 51 | ||||
-rw-r--r-- | lib/handlebars/compiler/visitor.js | 27 | ||||
-rw-r--r-- | spec/ast.js | 63 | ||||
-rw-r--r-- | spec/parser.js | 2 | ||||
-rw-r--r-- | spec/partials.js | 6 | ||||
-rw-r--r-- | spec/visitor.js | 14 | ||||
-rw-r--r-- | src/handlebars.yy | 13 |
10 files changed, 179 insertions, 199 deletions
diff --git a/lib/handlebars/compiler/ast.js b/lib/handlebars/compiler/ast.js index 2f95cfb..26ea4ab 100644 --- a/lib/handlebars/compiler/ast.js +++ b/lib/handlebars/compiler/ast.js @@ -28,6 +28,41 @@ var AST = { this.strip = strip; }, + BlockNode: function(sexpr, program, inverse, strip, locInfo) { + this.loc = locInfo; + + this.type = 'BlockStatement'; + this.sexpr = sexpr; + this.program = program; + this.inverse = inverse; + this.strip = strip; + }, + + PartialNode: function(sexpr, strip, locInfo) { + this.loc = locInfo; + this.type = 'PartialStatement'; + this.sexpr = sexpr; + this.indent = ''; + + this.strip = strip; + this.strip.inlineStandalone = true; + }, + + ContentNode: function(string, locInfo) { + this.loc = locInfo; + this.type = 'ContentStatement'; + this.original = this.value = string; + }, + + CommentNode: function(comment, strip, locInfo) { + this.loc = locInfo; + this.type = 'CommentStatement'; + this.value = comment; + + this.strip = strip; + strip.inlineStandalone = true; + }, + SexprNode: function(rawParams, hash, locInfo) { this.loc = locInfo; @@ -51,37 +86,6 @@ var AST = { // pass or at runtime. }, - PartialNode: function(partialName, context, hash, strip, locInfo) { - this.loc = locInfo; - this.type = "partial"; - this.partialName = partialName; - this.context = context; - this.hash = hash; - this.strip = strip; - - this.strip.inlineStandalone = true; - }, - - BlockNode: function(sexpr, program, inverse, strip, locInfo) { - this.loc = locInfo; - - this.type = 'block'; - this.sexpr = sexpr; - this.program = program; - this.inverse = inverse; - this.strip = strip; - - if (inverse && !program) { - this.isInverse = true; - } - }, - - ContentNode: function(string, locInfo) { - this.loc = locInfo; - this.type = "content"; - this.original = this.string = string; - }, - HashNode: function(pairs, locInfo) { this.loc = locInfo; this.type = "hash"; @@ -128,12 +132,6 @@ var AST = { this.stringModeValue = this.string; }, - PartialNameNode: function(name, locInfo) { - this.loc = locInfo; - this.type = "PARTIAL_NAME"; - this.name = name.original; - }, - DataNode: function(id, locInfo) { this.loc = locInfo; this.type = "DATA"; @@ -163,15 +161,6 @@ var AST = { this.type = "BOOLEAN"; this.bool = bool; this.stringModeValue = bool === "true"; - }, - - CommentNode: function(comment, strip, locInfo) { - this.loc = locInfo; - this.type = "comment"; - this.comment = comment; - - this.strip = strip; - strip.inlineStandalone = true; } }; diff --git a/lib/handlebars/compiler/compiler.js b/lib/handlebars/compiler/compiler.js index 69937a5..ea2272a 100644 --- a/lib/handlebars/compiler/compiler.js +++ b/lib/handlebars/compiler/compiler.js @@ -107,24 +107,19 @@ Compiler.prototype = { return guid; }, - block: function(block) { + BlockStatement: function(block) { var sexpr = block.sexpr, program = block.program, inverse = block.inverse; - if (program) { - program = this.compileProgram(program); - } - - if (inverse) { - inverse = this.compileProgram(inverse); - } + program = program && this.compileProgram(program); + inverse = inverse && this.compileProgram(inverse); var type = this.classifySexpr(sexpr); - if (type === "helper") { + if (type === 'helper') { this.helperSexpr(sexpr, program, inverse); - } else if (type === "simple") { + } else if (type === 'simple') { this.simpleSexpr(sexpr); // now that the simple mustache is resolved, we need to @@ -147,32 +142,23 @@ Compiler.prototype = { this.opcode('append', block); }, - hash: function(hash) { - var pairs = hash.pairs, i, l; - - this.opcode('pushHash', hash); - - for(i=0, l=pairs.length; i<l; i++) { - this.pushParam(pairs[i][1]); - } - while(i--) { - this.opcode('assignToHash', hash, pairs[i][0]); - } - this.opcode('popHash', hash); - }, - - partial: function(partial) { - var partialName = partial.partialName; + PartialStatement: function(partial) { + var partialName = partial.sexpr.id.original; this.usePartial = true; - if (partial.hash) { - this.accept(partial.hash); + if (partial.sexpr.hash) { + this.accept(partial.sexpr.hash); } else { this.opcode('pushLiteral', partial, 'undefined'); } - if (partial.context) { - this.accept(partial.context); + var params = partial.sexpr.params; + if (params.length) { + if (params.length > 1) { + throw new Exception('Unsupported number of partial arguments: ' + params.length, partial); + } + + this.pushParam(params[0]); } else { this.opcode('getContext', partial, 0); this.opcode('pushContext', partial); @@ -183,16 +169,10 @@ Compiler.prototype = { this.opcode('appendContent', partial, indent); indent = ''; } - this.opcode('invokePartial', partial, partialName.name, indent); + this.opcode('invokePartial', partial, partialName, indent); this.opcode('append', partial); }, - content: function(content) { - if (content.string) { - this.opcode('appendContent', content, content.string); - } - }, - MustacheStatement: function(mustache) { this.sexpr(mustache.sexpr); @@ -203,6 +183,25 @@ Compiler.prototype = { } }, + ContentStatement: function(content) { + if (content.value) { + this.opcode('appendContent', content, content.value); + } + }, + + CommentStatement: function() {}, + + sexpr: function(sexpr) { + var type = this.classifySexpr(sexpr); + + if (type === "simple") { + this.simpleSexpr(sexpr); + } else if (type === "helper") { + this.helperSexpr(sexpr); + } else { + this.ambiguousSexpr(sexpr); + } + }, ambiguousSexpr: function(sexpr, program, inverse) { var id = sexpr.id, name = id.parts[0], @@ -252,16 +251,18 @@ Compiler.prototype = { } }, - sexpr: function(sexpr) { - var type = this.classifySexpr(sexpr); + hash: function(hash) { + var pairs = hash.pairs, i, l; - if (type === "simple") { - this.simpleSexpr(sexpr); - } else if (type === "helper") { - this.helperSexpr(sexpr); - } else { - this.ambiguousSexpr(sexpr); + this.opcode('pushHash', hash); + + for(i=0, l=pairs.length; i<l; i++) { + this.pushParam(pairs[i][1]); + } + while(i--) { + this.opcode('assignToHash', hash, pairs[i][0]); } + this.opcode('popHash', hash); }, ID: function(id) { @@ -294,8 +295,6 @@ Compiler.prototype = { this.opcode('pushLiteral', bool, bool.bool); }, - comment: function() {}, - // HELPERS opcode: function(name, node) { this.opcodes.push({ opcode: name, args: slice.call(arguments, 2), loc: node.loc }); @@ -339,12 +338,14 @@ Compiler.prototype = { }, pushParam: function(val) { + var stringModeValue = val.stringModeValue != null ? val.stringModeValue : ''; + if (this.stringParams) { if(val.depth) { this.addDepth(val.depth); } this.opcode('getContext', val, val.depth || 0); - this.opcode('pushStringParam', val, val.stringModeValue, val.type); + this.opcode('pushStringParam', val, stringModeValue, val.type); if (val.type === 'sexpr') { // Subexpressions get evaluated and passed in @@ -353,7 +354,7 @@ Compiler.prototype = { } } else { if (this.trackIds) { - this.opcode('pushId', val, val.type, val.idName || val.stringModeValue); + this.opcode('pushId', val, val.type, val.idName || stringModeValue); } this.accept(val); } diff --git a/lib/handlebars/compiler/helpers.js b/lib/handlebars/compiler/helpers.js index 2685f45..023566b 100644 --- a/lib/handlebars/compiler/helpers.js +++ b/lib/handlebars/compiler/helpers.js @@ -144,7 +144,7 @@ export function prepareProgram(body, isRoot) { if (omitLeft(body, i)) { // If we are on a standalone node, save the indent info for partials - if (current.type === 'partial') { + if (current.type === 'PartialStatement') { // Pull out the whitespace from the final line current.indent = (/([ \t]+$)/).exec(body[i-1].original)[1]; } @@ -180,7 +180,7 @@ function isPrevWhitespace(body, i, isRoot) { return isRoot; } - if (prev.type === 'content') { + if (prev.type === 'ContentStatement') { return (sibling || !isRoot ? (/\r?\n\s*?$/) : (/(^|\r?\n)\s*?$/)).test(prev.original); } } @@ -195,7 +195,7 @@ function isNextWhitespace(body, i, isRoot) { return isRoot; } - if (next.type === 'content') { + if (next.type === 'ContentStatement') { return (sibling || !isRoot ? (/^\s*?\r?\n/) : (/^\s*?(\r?\n|$)/)).test(next.original); } } @@ -209,13 +209,13 @@ function isNextWhitespace(body, i, isRoot) { // content is met. function omitRight(body, i, multiple) { var current = body[i == null ? 0 : i + 1]; - if (!current || current.type !== 'content' || (!multiple && current.rightStripped)) { + if (!current || current.type !== 'ContentStatement' || (!multiple && current.rightStripped)) { return; } - var original = current.string; - current.string = current.string.replace(multiple ? (/^\s+/) : (/^[ \t]*\r?\n?/), ''); - current.rightStripped = current.string !== original; + var original = current.value; + current.value = current.value.replace(multiple ? (/^\s+/) : (/^[ \t]*\r?\n?/), ''); + current.rightStripped = current.value !== original; } // Marks the node to the left of the position as omitted. @@ -227,13 +227,13 @@ function omitRight(body, i, multiple) { // content is met. function omitLeft(body, i, multiple) { var current = body[i == null ? body.length - 1 : i - 1]; - if (!current || current.type !== 'content' || (!multiple && current.leftStripped)) { + if (!current || current.type !== 'ContentStatement' || (!multiple && current.leftStripped)) { return; } // We omit the last node if it's whitespace only and not preceeded by a non-content node. - var original = current.string; - current.string = current.string.replace(multiple ? (/\s+$/) : (/[ \t]+$/), ''); - current.leftStripped = current.string !== original; + var original = current.value; + current.value = current.value.replace(multiple ? (/\s+$/) : (/[ \t]+$/), ''); + current.leftStripped = current.value !== original; return current.leftStripped; } diff --git a/lib/handlebars/compiler/printer.js b/lib/handlebars/compiler/printer.js index 481c7be..dac8ec2 100644 --- a/lib/handlebars/compiler/printer.js +++ b/lib/handlebars/compiler/printer.js @@ -48,21 +48,21 @@ PrintVisitor.prototype.MustacheStatement = function(mustache) { return this.pad('{{ ' + this.accept(mustache.sexpr) + ' }}'); }; -PrintVisitor.prototype.block = function(block) { +PrintVisitor.prototype.BlockStatement = function(block) { var out = ""; - out = out + this.pad("BLOCK:"); + out = out + this.pad('BLOCK:'); this.padding++; out = out + this.pad(this.accept(block.sexpr)); if (block.program) { - out = out + this.pad("PROGRAM:"); + out = out + this.pad('PROGRAM:'); this.padding++; out = out + this.accept(block.program); this.padding--; } if (block.inverse) { if (block.program) { this.padding++; } - out = out + this.pad("{{^}}"); + out = out + this.pad('{{^}}'); this.padding++; out = out + this.accept(block.inverse); this.padding--; @@ -73,6 +73,26 @@ PrintVisitor.prototype.block = function(block) { return out; }; +PrintVisitor.prototype.PartialStatement = function(partial) { + var sexpr = partial.sexpr, + content = 'PARTIAL:' + sexpr.id.original; + if(sexpr.params[0]) { + content += ' ' + this.accept(sexpr.params[0]); + } + if (sexpr.hash) { + content += ' ' + this.accept(sexpr.hash); + } + return this.pad('{{> ' + content + ' }}'); +}; + +PrintVisitor.prototype.ContentStatement = function(content) { + return this.pad("CONTENT[ '" + content.value + "' ]"); +}; + +PrintVisitor.prototype.CommentStatement = function(comment) { + return this.pad("{{! '" + comment.value + "' }}"); +}; + PrintVisitor.prototype.sexpr = function(sexpr) { var params = sexpr.params, paramStrings = [], hash; @@ -87,17 +107,6 @@ PrintVisitor.prototype.sexpr = function(sexpr) { return this.accept(sexpr.id) + " " + params + hash; }; -PrintVisitor.prototype.partial = function(partial) { - var content = this.accept(partial.partialName); - if(partial.context) { - content += " " + this.accept(partial.context); - } - if (partial.hash) { - content += " " + this.accept(partial.hash); - } - return this.pad("{{> " + content + " }}"); -}; - PrintVisitor.prototype.hash = function(hash) { var pairs = hash.pairs; var joinedPairs = [], left, right; @@ -132,19 +141,7 @@ PrintVisitor.prototype.ID = function(id) { } }; -PrintVisitor.prototype.PARTIAL_NAME = function(partialName) { - return "PARTIAL:" + partialName.name; -}; - PrintVisitor.prototype.DATA = function(data) { return "@" + this.accept(data.id); }; -PrintVisitor.prototype.content = function(content) { - return this.pad("CONTENT[ '" + content.string + "' ]"); -}; - -PrintVisitor.prototype.comment = function(comment) { - return this.pad("{{! '" + comment.comment + "' }}"); -}; - diff --git a/lib/handlebars/compiler/visitor.js b/lib/handlebars/compiler/visitor.js index dc7f527..e48c9bc 100644 --- a/lib/handlebars/compiler/visitor.js +++ b/lib/handlebars/compiler/visitor.js @@ -4,7 +4,7 @@ Visitor.prototype = { constructor: Visitor, accept: function(object) { - return object && this[object.type] && this[object.type](object); + return object && this[object.type](object); }, Program: function(program) { @@ -20,12 +20,21 @@ Visitor.prototype = { this.accept(mustache.sexpr); }, - block: function(block) { - this.accept(block.mustache); + BlockStatement: function(block) { + this.accept(block.sexpr); this.accept(block.program); this.accept(block.inverse); }, + PartialStatement: function(partial) { + this.accept(partial.partialName); + this.accept(partial.context); + this.accept(partial.hash); + }, + + ContentStatement: function(content) {}, + CommentStatement: function(comment) {}, + sexpr: function(sexpr) { var params = sexpr.params, paramStrings = [], hash; @@ -44,13 +53,6 @@ Visitor.prototype = { } }, - partial: function(partial) { - this.accept(partial.partialName); - this.accept(partial.context); - this.accept(partial.hash); - }, - PARTIAL_NAME: function(partialName) {}, - DATA: function(data) { this.accept(data.id); }, @@ -58,10 +60,7 @@ Visitor.prototype = { STRING: function(string) {}, NUMBER: function(number) {}, BOOLEAN: function(bool) {}, - ID: function(id) {}, - - content: function(content) {}, - comment: function(comment) {} + ID: function(id) {} }; export default Visitor; diff --git a/spec/ast.js b/spec/ast.js index d41a591..dc6e136 100644 --- a/spec/ast.js +++ b/spec/ast.js @@ -168,18 +168,9 @@ describe('ast', function() { }); }); - describe("PartialNameNode", function(){ - - it('stores location info', function(){ - var pnn = new handlebarsEnv.AST.PartialNameNode({original: "YES"}, LOCATION_INFO); - testLocationInfoStorage(pnn); - }); - }); - describe("PartialNode", function(){ - it('stores location info', function(){ - var pn = new handlebarsEnv.AST.PartialNode("so_partial", {}, {}, {}, LOCATION_INFO); + var pn = new handlebarsEnv.AST.PartialNode('so_partial', {}, LOCATION_INFO); testLocationInfoStorage(pn); }); }); @@ -248,8 +239,8 @@ describe('ast', function() { describe('mustache', function() { it('does not mark mustaches as standalone', function() { var ast = Handlebars.parse(' {{comment}} '); - equals(!!ast.body[0].string, true); - equals(!!ast.body[2].string, true); + equals(!!ast.body[0].value, true); + equals(!!ast.body[2].value, true); }); }); describe('blocks', function() { @@ -257,38 +248,38 @@ describe('ast', function() { var ast = Handlebars.parse(' {{# comment}} \nfoo\n {{else}} \n bar \n {{/comment}} '), block = ast.body[1]; - equals(ast.body[0].string, ''); + equals(ast.body[0].value, ''); - equals(block.program.body[0].string, 'foo\n'); - equals(block.inverse.body[0].string, ' bar \n'); + equals(block.program.body[0].value, 'foo\n'); + equals(block.inverse.body[0].value, ' bar \n'); - equals(ast.body[2].string, ''); + equals(ast.body[2].value, ''); }); it('marks initial block mustaches as standalone', function() { var ast = Handlebars.parse('{{# comment}} \nfoo\n {{/comment}}'), block = ast.body[0]; - equals(block.program.body[0].string, 'foo\n'); + equals(block.program.body[0].value, 'foo\n'); }); it('marks mustaches with children as standalone', function() { var ast = Handlebars.parse('{{# comment}} \n{{foo}}\n {{/comment}}'), block = ast.body[0]; - equals(block.program.body[0].string, ''); + equals(block.program.body[0].value, ''); equals(block.program.body[1].sexpr.id.original, 'foo'); - equals(block.program.body[2].string, '\n'); + equals(block.program.body[2].value, '\n'); }); it('marks nested block mustaches as standalone', function() { var ast = Handlebars.parse('{{#foo}} \n{{# comment}} \nfoo\n {{else}} \n bar \n {{/comment}} \n{{/foo}}'), body = ast.body[0].program.body, block = body[1]; - equals(body[0].string, ''); + equals(body[0].value, ''); - equals(block.program.body[0].string, 'foo\n'); - equals(block.inverse.body[0].string, ' bar \n'); + equals(block.program.body[0].value, 'foo\n'); + equals(block.inverse.body[0].value, ' bar \n'); - equals(body[0].string, ''); + equals(body[0].value, ''); }); it('does not mark nested block mustaches as standalone', function() { var ast = Handlebars.parse('{{#foo}} {{# comment}} \nfoo\n {{else}} \n bar \n {{/comment}} {{/foo}}'), @@ -297,8 +288,8 @@ describe('ast', function() { equals(body[0].omit, undefined); - equals(block.program.body[0].string, ' \nfoo\n'); - equals(block.inverse.body[0].string, ' bar \n '); + equals(block.program.body[0].value, ' \nfoo\n'); + equals(block.inverse.body[0].value, ' bar \n '); equals(body[0].omit, undefined); }); @@ -307,8 +298,8 @@ describe('ast', function() { body = ast.body[0].program.body, block = body[0]; - equals(block.program.body[0].string, ' \nfoo\n'); - equals(block.inverse.body[0].string, ' bar \n '); + equals(block.program.body[0].value, ' \nfoo\n'); + equals(block.inverse.body[0].value, ' bar \n '); equals(body[0].omit, undefined); }); @@ -319,22 +310,22 @@ describe('ast', function() { equals(ast.body[0].omit, undefined); - equals(block.program.body[0].string, 'foo\n'); - equals(block.inverse.body[0].string, ' bar \n'); + equals(block.program.body[0].value, 'foo\n'); + equals(block.inverse.body[0].value, ' bar \n'); - equals(ast.body[2].string, ''); + equals(ast.body[2].value, ''); }); }); describe('partials', function() { it('marks partial as standalone', function() { var ast = Handlebars.parse('{{> partial }} '); - equals(ast.body[1].string, ''); + equals(ast.body[1].value, ''); }); it('marks indented partial as standalone', function() { var ast = Handlebars.parse(' {{> partial }} '); - equals(ast.body[0].string, ''); + equals(ast.body[0].value, ''); equals(ast.body[1].indent, ' '); - equals(ast.body[2].string, ''); + equals(ast.body[2].value, ''); }); it('marks those around content as not standalone', function() { var ast = Handlebars.parse('a{{> partial }}'); @@ -347,12 +338,12 @@ describe('ast', function() { describe('comments', function() { it('marks comment as standalone', function() { var ast = Handlebars.parse('{{! comment }} '); - equals(ast.body[1].string, ''); + equals(ast.body[1].value, ''); }); it('marks indented comment as standalone', function() { var ast = Handlebars.parse(' {{! comment }} '); - equals(ast.body[0].string, ''); - equals(ast.body[2].string, ''); + equals(ast.body[0].value, ''); + equals(ast.body[2].value, ''); }); it('marks those around content as not standalone', function() { var ast = Handlebars.parse('a{{! comment }}'); diff --git a/spec/parser.js b/spec/parser.js index 0569229..f2b6e41 100644 --- a/spec/parser.js +++ b/spec/parser.js @@ -82,6 +82,8 @@ describe('parser', function() { it('parses a partial', function() { equals(ast_for("{{> foo }}"), "{{> PARTIAL:foo }}\n"); + equals(ast_for("{{> 'foo' }}"), "{{> PARTIAL:foo }}\n"); + equals(ast_for("{{> 1 }}"), "{{> PARTIAL:1 }}\n"); }); it('parses a partial with context', function() { diff --git a/spec/partials.js b/spec/partials.js index a1e0538..b150942 100644 --- a/spec/partials.js +++ b/spec/partials.js @@ -23,6 +23,12 @@ describe('partials', function() { shouldCompileToWithPartials(string, [hash, {}, {dude: partial}], true, "Dudes: Empty"); }); + it('partials with duplicate parameters', function() { + shouldThrow(function() { + CompilerContext.compile('Dudes: {{>dude dudes foo bar=baz}}'); + }, Error, 'Unsupported number of partial arguments: 2 - 1:7'); + }); + it("partials with parameters", function() { var string = "Dudes: {{#dudes}}{{> dude others=..}}{{/dudes}}"; var partial = "{{others.foo}}{{name}} ({{url}}) "; diff --git a/spec/visitor.js b/spec/visitor.js index b64dc56..15a0f02 100644 --- a/spec/visitor.js +++ b/spec/visitor.js @@ -14,16 +14,12 @@ describe('Visitor', function() { // Simply run the thing and make sure it does not fail and that all of the // stub methods are executed var visitor = new Handlebars.Visitor(); - visitor.accept(Handlebars.parse('{{#foo (bar 1 "1" true) foo=@data}}{{!comment}}{{> bar }} {{/foo}}')); + visitor.accept(Handlebars.parse('{{foo}}{{#foo (bar 1 "1" true) foo=@data}}{{!comment}}{{> bar }} {{/foo}}')); }); it('should traverse to stubs', function() { var visitor = new Handlebars.Visitor(); - visitor.PARTIAL_NAME = function(partialName) { - equal(partialName.name, 'bar'); - }; - visitor.STRING = function(string) { equal(string.string, '2'); }; @@ -36,11 +32,11 @@ describe('Visitor', function() { visitor.ID = function(id) { equal(id.original, 'foo.bar'); }; - visitor.content = function(content) { - equal(content.string, ' '); + visitor.ContentStatement = function(content) { + equal(content.value, ' '); }; - visitor.comment = function(comment) { - equal(comment.comment, 'comment'); + visitor.CommentStatement = function(comment) { + equal(comment.value, 'comment'); }; visitor.accept(Handlebars.parse('{{#foo.bar (foo.bar 1 "2" true) foo=@foo.bar}}{{!comment}}{{> bar }} {{/foo.bar}}')); diff --git a/src/handlebars.yy b/src/handlebars.yy index d7d117c..0bd6fde 100644 --- a/src/handlebars.yy +++ b/src/handlebars.yy @@ -78,12 +78,11 @@ mustache ; partial - : OPEN_PARTIAL partialName param hash? CLOSE -> new yy.PartialNode($2, $3, $4, yy.stripFlags($1, $5), yy.locInfo(@$)) - | OPEN_PARTIAL partialName hash? CLOSE -> new yy.PartialNode($2, undefined, $3, yy.stripFlags($1, $4), yy.locInfo(@$)) + : OPEN_PARTIAL sexpr CLOSE -> new yy.PartialNode($2, yy.stripFlags($1, $3), yy.locInfo(@$)) ; sexpr - : path param* hash? -> new yy.SexprNode([$1].concat($2), $3, yy.locInfo(@$)) + : helperName param* hash? -> new yy.SexprNode([$1].concat($2), $3, yy.locInfo(@$)) | dataName -> new yy.SexprNode([$1], null, yy.locInfo(@$)) ; @@ -108,10 +107,10 @@ blockParams : OPEN_BLOCK_PARAMS ID+ CLOSE_BLOCK_PARAMS -> $2 ; -partialName - : path -> new yy.PartialNameNode($1, yy.locInfo(@$)) - | STRING -> new yy.PartialNameNode(new yy.StringNode($1, yy.locInfo(@$)), yy.locInfo(@$)) - | NUMBER -> new yy.PartialNameNode(new yy.NumberNode($1, yy.locInfo(@$))) +helperName + : path -> $1 + | STRING -> new yy.StringNode($1, yy.locInfo(@$)), yy.locInfo(@$) + | NUMBER -> new yy.NumberNode($1, yy.locInfo(@$)) ; dataName |