Skip to content

Commit

Permalink
Allow decimal number values
Browse files Browse the repository at this point in the history
Fixes #472
  • Loading branch information
kpdecker committed Jan 18, 2014
1 parent 051618c commit d4cfe90
Show file tree
Hide file tree
Showing 9 changed files with 42 additions and 23 deletions.
8 changes: 4 additions & 4 deletions lib/handlebars/compiler/ast.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
4 changes: 2 additions & 2 deletions lib/handlebars/compiler/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
4 changes: 2 additions & 2 deletions lib/handlebars/compiler/printer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
4 changes: 2 additions & 2 deletions spec/ast.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
});
Expand Down
11 changes: 11 additions & 0 deletions spec/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {};
Expand Down
8 changes: 4 additions & 4 deletions spec/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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");
Expand All @@ -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');
});
Expand Down
20 changes: 14 additions & 6 deletions spec/tokenizer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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']);
Expand Down Expand Up @@ -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']);
});
});
2 changes: 1 addition & 1 deletion src/handlebars.l
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
4 changes: 2 additions & 2 deletions src/handlebars.yy
Original file line number Diff line number Diff line change
Expand Up @@ -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;}
Expand All @@ -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
Expand Down

0 comments on commit d4cfe90

Please sign in to comment.