OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 Google Inc. All rights reserved. |
| 2 // |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 // you may not use this file except in compliance with the License. |
| 5 // You may obtain a copy of the License at |
| 6 // |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 // |
| 9 // Unless required by applicable law or agreed to in writing, software |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 // See the License for the specific language governing permissions and |
| 13 // limitations under the License. |
| 14 |
| 15 (function(scope) { |
| 16 |
| 17 // consume* functions return a 2 value array of [parsed-data, '' or not-yet co
nsumed input] |
| 18 |
| 19 // Regex should be anchored with /^ |
| 20 function consumeToken(regex, string) { |
| 21 var result = regex.exec(string); |
| 22 if (result) { |
| 23 result = regex.ignoreCase ? result[0].toLowerCase() : result[0]; |
| 24 return [result, string.substr(result.length)]; |
| 25 } |
| 26 } |
| 27 |
| 28 function consumeTrimmed(consumer, string) { |
| 29 string = string.replace(/^\s*/, ''); |
| 30 var result = consumer(string); |
| 31 if (result) { |
| 32 return [result[0], result[1].replace(/^\s*/, '')]; |
| 33 } |
| 34 } |
| 35 |
| 36 function consumeRepeated(consumer, separator, string) { |
| 37 consumer = consumeTrimmed.bind(null, consumer); |
| 38 var list = []; |
| 39 while (true) { |
| 40 var result = consumer(string); |
| 41 if (!result) { |
| 42 return [list, string]; |
| 43 } |
| 44 list.push(result[0]); |
| 45 string = result[1]; |
| 46 result = consumeToken(separator, string); |
| 47 if (!result || result[1] == '') { |
| 48 return [list, string]; |
| 49 } |
| 50 string = result[1]; |
| 51 } |
| 52 } |
| 53 |
| 54 // Consumes a token or expression with balanced parentheses |
| 55 function consumeParenthesised(parser, string) { |
| 56 var nesting = 0; |
| 57 for (var n = 0; n < string.length; n++) { |
| 58 if (/\s|,/.test(string[n]) && nesting == 0) { |
| 59 break; |
| 60 } else if (string[n] == '(') { |
| 61 nesting++; |
| 62 } else if (string[n] == ')') { |
| 63 nesting--; |
| 64 if (nesting == 0) |
| 65 n++; |
| 66 if (nesting <= 0) |
| 67 break; |
| 68 } |
| 69 } |
| 70 var parsed = parser(string.substr(0, n)); |
| 71 return parsed == undefined ? undefined : [parsed, string.substr(n)]; |
| 72 } |
| 73 |
| 74 function lcm(a, b) { |
| 75 var c = a; |
| 76 var d = b; |
| 77 while (c && d) |
| 78 c > d ? c %= d : d %= c; |
| 79 c = (a * b) / (c + d); |
| 80 return c; |
| 81 } |
| 82 |
| 83 function ignore(value) { |
| 84 return function(input) { |
| 85 var result = value(input); |
| 86 if (result) |
| 87 result[0] = undefined; |
| 88 return result; |
| 89 } |
| 90 } |
| 91 |
| 92 function optional(value, defaultValue) { |
| 93 return function(input) { |
| 94 var result = value(input); |
| 95 if (result) |
| 96 return result; |
| 97 return [defaultValue, input]; |
| 98 } |
| 99 } |
| 100 |
| 101 function consumeList(list, input) { |
| 102 var output = []; |
| 103 for (var i = 0; i < list.length; i++) { |
| 104 var result = scope.consumeTrimmed(list[i], input); |
| 105 if (!result || result[0] == '') |
| 106 return; |
| 107 if (result[0] !== undefined) |
| 108 output.push(result[0]); |
| 109 input = result[1]; |
| 110 } |
| 111 if (input == '') { |
| 112 return output; |
| 113 } |
| 114 } |
| 115 |
| 116 function mergeWrappedNestedRepeated(wrap, nestedMerge, separator, left, right)
{ |
| 117 var matchingLeft = []; |
| 118 var matchingRight = []; |
| 119 var reconsititution = []; |
| 120 var length = lcm(left.length, right.length); |
| 121 for (var i = 0; i < length; i++) { |
| 122 var thing = nestedMerge(left[i % left.length], right[i % right.length]); |
| 123 if (!thing) { |
| 124 return; |
| 125 } |
| 126 matchingLeft.push(thing[0]); |
| 127 matchingRight.push(thing[1]); |
| 128 reconsititution.push(thing[2]); |
| 129 } |
| 130 return [matchingLeft, matchingRight, function(positions) { |
| 131 var result = positions.map(function(position, i) { |
| 132 return reconsititution[i](position); |
| 133 }).join(separator); |
| 134 return wrap ? wrap(result) : result; |
| 135 }]; |
| 136 } |
| 137 |
| 138 function mergeList(left, right, list) { |
| 139 var lefts = []; |
| 140 var rights = []; |
| 141 var functions = []; |
| 142 var j = 0; |
| 143 for (var i = 0; i < list.length; i++) { |
| 144 if (typeof list[i] == 'function') { |
| 145 var result = list[i](left[j], right[j++]); |
| 146 lefts.push(result[0]); |
| 147 rights.push(result[1]); |
| 148 functions.push(result[2]); |
| 149 } else { |
| 150 (function(pos) { |
| 151 lefts.push(false); |
| 152 rights.push(false); |
| 153 functions.push(function() { return list[pos]; }); |
| 154 })(i); |
| 155 } |
| 156 } |
| 157 return [lefts, rights, function(results) { |
| 158 var result = ''; |
| 159 for (var i = 0; i < results.length; i++) { |
| 160 result += functions[i](results[i]); |
| 161 } |
| 162 return result; |
| 163 }]; |
| 164 } |
| 165 |
| 166 scope.consumeToken = consumeToken; |
| 167 scope.consumeTrimmed = consumeTrimmed; |
| 168 scope.consumeRepeated = consumeRepeated; |
| 169 scope.consumeParenthesised = consumeParenthesised; |
| 170 scope.ignore = ignore; |
| 171 scope.optional = optional; |
| 172 scope.consumeList = consumeList; |
| 173 scope.mergeNestedRepeated = mergeWrappedNestedRepeated.bind(null, null); |
| 174 scope.mergeWrappedNestedRepeated = mergeWrappedNestedRepeated; |
| 175 scope.mergeList = mergeList; |
| 176 |
| 177 })(webAnimationsMinifill); |
OLD | NEW |