feat($parse): add support for ternary operators to parser

Add '?' token to lexer, add ternary rule to parser at
(hopefully) proper precedence and associativity (based
on https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Operator_Precedence).
Since (exp1 && exp2 || exp3) is supported by the parser,
and (exp1 ? exp2 : exp3) works the same way, it seems
reasonable to add this minor form of control to templates
(see #719).
This commit is contained in:
Zach Snow
2013-04-22 17:42:34 -07:00
committed by Pete Bacon Darwin
parent cefbcd470d
commit 6798fec439
2 changed files with 83 additions and 3 deletions

View File

@@ -58,7 +58,7 @@ function lex(text, csp){
(token=tokens[tokens.length-1])) {
token.json = token.text.indexOf('.') == -1;
}
} else if (is('(){}[].,;:')) {
} else if (is('(){}[].,;:?')) {
tokens.push({
index:index,
text:ch,
@@ -359,6 +359,14 @@ function parser(text, json, $filter, csp){
});
}
function ternaryFn(left, middle, right){
return extend(function(self, locals){
return left(self, locals) ? middle(self, locals) : right(self, locals);
}, {
constant: left.constant && middle.constant && right.constant
});
}
function binaryFn(left, fn, right) {
return extend(function(self, locals) {
return fn(self, locals, left, right);
@@ -429,7 +437,7 @@ function parser(text, json, $filter, csp){
}
function _assignment() {
var left = logicalOR();
var left = ternary();
var right;
var token;
if ((token = expect('='))) {
@@ -437,7 +445,7 @@ function parser(text, json, $filter, csp){
throwError("implies assignment but [" +
text.substring(0, token.index) + "] can not be assigned to", token);
}
right = logicalOR();
right = ternary();
return function(scope, locals){
return left.assign(scope, right(scope, locals), locals);
};
@@ -446,6 +454,24 @@ function parser(text, json, $filter, csp){
}
}
function ternary() {
var left = logicalOR();
var middle;
var token;
if((token = expect('?'))){
middle = ternary();
if((token = expect(':'))){
return ternaryFn(left, middle, ternary());
}
else {
throwError('expected :', token);
}
}
else {
return left;
}
}
function logicalOR() {
var left = logicalAND();
var token;