diff options
author | kpdecker <kpdecker@gmail.com> | 2014-01-17 20:42:02 -0600 |
---|---|---|
committer | kpdecker <kpdecker@gmail.com> | 2014-01-17 20:42:02 -0600 |
commit | d4cfe90959c5a585e5d87e31038eb2f0432f87a5 (patch) | |
tree | 6a7699604f3165f7e089c899ca6b34d1f3a7def2 | |
parent | 051618c024333404746795304f5858f3ef56a215 (diff) | |
download | handlebars.js-d4cfe90959c5a585e5d87e31038eb2f0432f87a5.zip handlebars.js-d4cfe90959c5a585e5d87e31038eb2f0432f87a5.tar.gz handlebars.js-d4cfe90959c5a585e5d87e31038eb2f0432f87a5.tar.bz2 |
Allow decimal number values
Fixes #472
-rw-r--r-- | lib/handlebars/compiler/ast.js | 8 | ||||
-rw-r--r-- | lib/handlebars/compiler/compiler.js | 4 | ||||
-rw-r--r-- | lib/handlebars/compiler/printer.js | 4 | ||||
-rw-r--r-- | spec/ast.js | 4 | ||||
-rw-r--r-- | spec/helpers.js | 11 | ||||
-rw-r--r-- | spec/parser.js | 8 | ||||
-rw-r--r-- | spec/tokenizer.js | 20 | ||||
-rw-r--r-- | src/handlebars.l | 2 | ||||
-rw-r--r-- | src/handlebars.yy | 4 |
9 files changed, 42 insertions, 23 deletions
diff --git a/lib/handlebars/compiler/ast.js b/lib/handlebars/compiler/ast.js index 5538f40..8fa6495 100644 --- a/lib/handlebars/compiler/ast.js +++ b/lib/handlebars/compiler/ast.js @@ -201,12 +201,12 @@ var AST = { this.stringModeValue = string; }, - IntegerNode: function(integer, locInfo) { + NumberNode: function(number, locInfo) { LocationInfo.call(this, locInfo); - this.type = "INTEGER"; + this.type = "NUMBER"; this.original = - this.integer = integer; - this.stringModeValue = Number(integer); + this.number = number; + this.stringModeValue = Number(number); }, BooleanNode: function(bool, locInfo) { diff --git a/lib/handlebars/compiler/compiler.js b/lib/handlebars/compiler/compiler.js index b92289a..83eca24 100644 --- a/lib/handlebars/compiler/compiler.js +++ b/lib/handlebars/compiler/compiler.js @@ -321,8 +321,8 @@ Compiler.prototype = { this.opcode('pushString', string.string); }, - INTEGER: function(integer) { - this.opcode('pushLiteral', integer.integer); + NUMBER: function(number) { + this.opcode('pushLiteral', number.number); }, BOOLEAN: function(bool) { diff --git a/lib/handlebars/compiler/printer.js b/lib/handlebars/compiler/printer.js index b7b760f..be66d73 100644 --- a/lib/handlebars/compiler/printer.js +++ b/lib/handlebars/compiler/printer.js @@ -108,8 +108,8 @@ PrintVisitor.prototype.STRING = function(string) { return '"' + string.string + '"'; }; -PrintVisitor.prototype.INTEGER = function(integer) { - return "INTEGER{" + integer.integer + "}"; +PrintVisitor.prototype.NUMBER = function(number) { + return "NUMBER{" + number.number + "}"; }; PrintVisitor.prototype.BOOLEAN = function(bool) { diff --git a/spec/ast.js b/spec/ast.js index 430574e..17a982c 100644 --- a/spec/ast.js +++ b/spec/ast.js @@ -150,10 +150,10 @@ describe('ast', function() { }); }); - describe("IntegerNode", function(){ + describe("NumberNode", function(){ it('stores location info', function(){ - var integer = new handlebarsEnv.AST.IntegerNode("6", LOCATION_INFO); + var integer = new handlebarsEnv.AST.NumberNode("6", LOCATION_INFO); testLocationInfoStorage(integer); }); }); diff --git a/spec/helpers.js b/spec/helpers.js index 180fc98..904f56a 100644 --- a/spec/helpers.js +++ b/spec/helpers.js @@ -188,6 +188,17 @@ describe('helpers', function() { "found it! Goodbye cruel world!!"); }); + it("decimal number literals work", function() { + var string = 'Message: {{hello -1.2 1.2}}'; + var hash = {}; + var helpers = {hello: function(times, times2) { + if(typeof times !== 'number') { times = "NaN"; } + if(typeof times2 !== 'number') { times2 = "NaN"; } + return "Hello " + times + " " + times2 + " times"; + }}; + shouldCompileTo(string, [hash, helpers], "Message: Hello -1.2 1.2 times", "template with a negative integer literal"); + }); + it("negative number literals work", function() { var string = 'Message: {{hello -12}}'; var hash = {}; diff --git a/spec/parser.js b/spec/parser.js index 0f6ed31..5b6dc8a 100644 --- a/spec/parser.js +++ b/spec/parser.js @@ -41,8 +41,8 @@ describe('parser', function() { equals(ast_for("{{foo bar \"baz\" }}"), '{{ ID:foo [ID:bar, "baz"] }}\n'); }); - it('parses mustaches with INTEGER parameters', function() { - equals(ast_for("{{foo 1}}"), "{{ ID:foo [INTEGER{1}] }}\n"); + it('parses mustaches with NUMBER parameters', function() { + equals(ast_for("{{foo 1}}"), "{{ ID:foo [NUMBER{1}] }}\n"); }); it('parses mustaches with BOOLEAN parameters', function() { @@ -56,7 +56,7 @@ describe('parser', function() { it('parses mustaches with hash arguments', function() { equals(ast_for("{{foo bar=baz}}"), "{{ ID:foo [] HASH{bar=ID:baz} }}\n"); - equals(ast_for("{{foo bar=1}}"), "{{ ID:foo [] HASH{bar=INTEGER{1}} }}\n"); + equals(ast_for("{{foo bar=1}}"), "{{ ID:foo [] HASH{bar=NUMBER{1}} }}\n"); equals(ast_for("{{foo bar=true}}"), "{{ ID:foo [] HASH{bar=BOOLEAN{true}} }}\n"); equals(ast_for("{{foo bar=false}}"), "{{ ID:foo [] HASH{bar=BOOLEAN{false}} }}\n"); equals(ast_for("{{foo bar=@baz}}"), "{{ ID:foo [] HASH{bar=@ID:baz} }}\n"); @@ -67,7 +67,7 @@ describe('parser', function() { equals(ast_for("{{foo bat='bam'}}"), '{{ ID:foo [] HASH{bat="bam"} }}\n'); equals(ast_for("{{foo omg bar=baz bat=\"bam\"}}"), '{{ ID:foo [ID:omg] HASH{bar=ID:baz, bat="bam"} }}\n'); - equals(ast_for("{{foo omg bar=baz bat=\"bam\" baz=1}}"), '{{ ID:foo [ID:omg] HASH{bar=ID:baz, bat="bam", baz=INTEGER{1}} }}\n'); + equals(ast_for("{{foo omg bar=baz bat=\"bam\" baz=1}}"), '{{ ID:foo [ID:omg] HASH{bar=ID:baz, bat="bam", baz=NUMBER{1}} }}\n'); equals(ast_for("{{foo omg bar=baz bat=\"bam\" baz=true}}"), '{{ ID:foo [ID:omg] HASH{bar=ID:baz, bat="bam", baz=BOOLEAN{true}} }}\n'); equals(ast_for("{{foo omg bar=baz bat=\"bam\" baz=false}}"), '{{ ID:foo [ID:omg] HASH{bar=ID:baz, bat="bam", baz=BOOLEAN{false}} }}\n'); }); diff --git a/spec/tokenizer.js b/spec/tokenizer.js index 841a5ab..36a632b 100644 --- a/spec/tokenizer.js +++ b/spec/tokenizer.js @@ -295,12 +295,20 @@ describe('Tokenizer', function() { it('tokenizes numbers', function() { var result = tokenize('{{ foo 1 }}'); - shouldMatchTokens(result, ['OPEN', 'ID', 'INTEGER', 'CLOSE']); - shouldBeToken(result[2], "INTEGER", "1"); + shouldMatchTokens(result, ['OPEN', 'ID', 'NUMBER', 'CLOSE']); + shouldBeToken(result[2], "NUMBER", "1"); + + result = tokenize('{{ foo 1.1 }}'); + shouldMatchTokens(result, ['OPEN', 'ID', 'NUMBER', 'CLOSE']); + shouldBeToken(result[2], "NUMBER", "1.1"); result = tokenize('{{ foo -1 }}'); - shouldMatchTokens(result, ['OPEN', 'ID', 'INTEGER', 'CLOSE']); - shouldBeToken(result[2], "INTEGER", "-1"); + shouldMatchTokens(result, ['OPEN', 'ID', 'NUMBER', 'CLOSE']); + shouldBeToken(result[2], "NUMBER", "-1"); + + result = tokenize('{{ foo -1.1 }}'); + shouldMatchTokens(result, ['OPEN', 'ID', 'NUMBER', 'CLOSE']); + shouldBeToken(result[2], "NUMBER", "-1.1"); }); it('tokenizes booleans', function() { @@ -321,7 +329,7 @@ describe('Tokenizer', function() { shouldMatchTokens(result, ['OPEN', 'ID', 'ID', 'ID', 'EQUALS', 'ID', 'CLOSE']); result = tokenize("{{ foo bar baz=1 }}"); - shouldMatchTokens(result, ['OPEN', 'ID', 'ID', 'ID', 'EQUALS', 'INTEGER', 'CLOSE']); + shouldMatchTokens(result, ['OPEN', 'ID', 'ID', 'ID', 'EQUALS', 'NUMBER', 'CLOSE']); result = tokenize("{{ foo bar baz=true }}"); shouldMatchTokens(result, ['OPEN', 'ID', 'ID', 'ID', 'EQUALS', 'BOOLEAN', 'CLOSE']); @@ -389,6 +397,6 @@ describe('Tokenizer', function() { it('tokenizes nested subexpressions: literals', function() { var result = tokenize("{{foo (bar (lol true) false) (baz 1) (blah 'b') (blorg \"c\")}}"); - shouldMatchTokens(result, ['OPEN', 'ID', 'OPEN_SEXPR', 'ID', 'OPEN_SEXPR', 'ID', 'BOOLEAN', 'CLOSE_SEXPR', 'BOOLEAN', 'CLOSE_SEXPR', 'OPEN_SEXPR', 'ID', 'INTEGER', 'CLOSE_SEXPR', 'OPEN_SEXPR', 'ID', 'STRING', 'CLOSE_SEXPR', 'OPEN_SEXPR', 'ID', 'STRING', 'CLOSE_SEXPR', 'CLOSE']); + shouldMatchTokens(result, ['OPEN', 'ID', 'OPEN_SEXPR', 'ID', 'OPEN_SEXPR', 'ID', 'BOOLEAN', 'CLOSE_SEXPR', 'BOOLEAN', 'CLOSE_SEXPR', 'OPEN_SEXPR', 'ID', 'NUMBER', 'CLOSE_SEXPR', 'OPEN_SEXPR', 'ID', 'STRING', 'CLOSE_SEXPR', 'OPEN_SEXPR', 'ID', 'STRING', 'CLOSE_SEXPR', 'CLOSE']); }); }); diff --git a/src/handlebars.l b/src/handlebars.l index 996badb..630840e 100644 --- a/src/handlebars.l +++ b/src/handlebars.l @@ -77,7 +77,7 @@ ID [^\s!"#%-,\.\/;->@\[-\^`\{-~]+/{LOOKAHEAD} <mu>"@" return 'DATA'; <mu>"true"/{LITERAL_LOOKAHEAD} return 'BOOLEAN'; <mu>"false"/{LITERAL_LOOKAHEAD} return 'BOOLEAN'; -<mu>\-?[0-9]+/{LITERAL_LOOKAHEAD} return 'INTEGER'; +<mu>\-?[0-9]+(?:\.[0-9]+)?/{LITERAL_LOOKAHEAD} return 'NUMBER'; <mu>{ID} return 'ID'; diff --git a/src/handlebars.yy b/src/handlebars.yy index bac1cc9..40f68ce 100644 --- a/src/handlebars.yy +++ b/src/handlebars.yy @@ -79,7 +79,7 @@ sexpr param : path -> $1 | STRING -> new yy.StringNode($1, @$) - | INTEGER -> new yy.IntegerNode($1, @$) + | NUMBER -> new yy.NumberNode($1, @$) | BOOLEAN -> new yy.BooleanNode($1, @$) | dataName -> $1 | OPEN_SEXPR sexpr CLOSE_SEXPR {$2.isHelper = true; $$ = $2;} @@ -96,7 +96,7 @@ hashSegment partialName : path -> new yy.PartialNameNode($1, @$) | STRING -> new yy.PartialNameNode(new yy.StringNode($1, @$), @$) - | INTEGER -> new yy.PartialNameNode(new yy.IntegerNode($1, @$)) + | NUMBER -> new yy.PartialNameNode(new yy.NumberNode($1, @$)) ; dataName |