UNPKG

5.07 kBJavaScriptView Raw
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 consumed 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})(webAnimations1);