@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
+2
-2
@@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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 = {};
|
||||
|
||||
+4
-4
@@ -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');
|
||||
});
|
||||
|
||||
+14
-6
@@ -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']);
|
||||
});
|
||||
});
|
||||
|
||||
+1
-1
@@ -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';
|
||||
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user