/[suikacvs]/www/test/html/progress/reqs/test.html
Suika

Contents of /www/test/html/progress/reqs/test.html

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.3 - (hide annotations) (download) (as text)
Sun Oct 18 08:14:37 2009 UTC (15 years, 9 months ago) by wakaba
Branch: MAIN
CVS Tags: HEAD
Changes since 1.2: +2 -0 lines
File MIME type: text/html
emphasizes that it is about meter, not progress :)

1 wakaba 1.1 <!DOCTYPE HTML>
2 wakaba 1.2 <title>&lt;meter> processing and authoring requirements</title>
3 wakaba 1.1
4 wakaba 1.3 <h1>&lt;meter></h1>
5    
6 wakaba 1.1 <script>
7    
8     // Web Applications 1.0 Revision 4116, 12 October 2009
9    
10     var whiteSpace = /\s/; // XXX White_Space != \s
11     var denominatorPunctuationCharacter = /[\u0025\u066A\uFE6A\uFF05\u2030\u2031]/;
12    
13     function findingOneOrTwoNumbersOfARatioInAString (string) {
14     // 1. If the string is empty, then return nothing and abort these steps.
15     if (string == '') {
16     return {isNothing: true, step: 1};
17     }
18    
19     // 2. Find a number in the string according to the algorithm below, starting at the start of the string.
20     var position = 0;
21     var s2 = findANumber (string, position);
22    
23     // 3. If the sub-algorithm in step 2 returned nothing or returned an error condition, return nothing and abort these steps.
24     if (s2.isNothing || s2.isError) {
25     return {isNothing: true, step: 3};
26     }
27    
28     // 4. Set number1 to the number returned by the sub-algorithm in step 2.
29     var number1 = s2.number;
30    
31     // 5. Starting with the character immediately after the last one examined by the sub-algorithm in step 2, skip all White_Space characters in the string (this might match zero characters).
32     position = s2.position;
33     while (position < string.length && string.charAt (position).match (whiteSpace)) {
34     position++;
35     }
36    
37     // 6. If there are still further characters in the string, and the next character in the string is a valid denominator punctuation character, set denominator to that character.
38     var denominator = null;
39     if (position < string.length && string.charAt (position).match (denominatorPunctuationCharacter)) {
40     denominator = string.charAt (position);
41     }
42    
43     // 7. If the string contains any other characters in the range U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9), but denominator was given a value in the step 6, return nothing and abort these steps.
44     if (string.substring (position).match (/[0-9]/) && denominator != null) {
45     return {isNothing: true, step: 7};
46     }
47    
48     // 8. Otherwise, if denominator was given a value in step 6, return number1 and denominator and abort these steps.
49     if (denominator != null) {
50     return {number1: number1, denominator: denominator, step: 8};
51     }
52    
53     // 9. Find a number in the string again, starting immediately after the last character that was examined by the sub-algorithm in step 2.
54     var s9 = findANumber (string, position);
55    
56     // 10. If the sub-algorithm in step 9 returned nothing or an error condition, return number1 and abort these steps.
57     if (s9.isNothing || s9.isError) {
58     return {number1: number1, step: 10};
59     }
60    
61     // 11. Set number2 to the number returned by the sub-algorithm in step 9.
62     var number2 = s9.number;
63    
64     // 12. Starting with the character immediately after the last one examined by the sub-algorithm in step 9, skip all White_Space characters in the string (this might match zero characters).
65     position = s9.position;
66     while (position < string.length && string.charAt (position).match (whiteSpace)) {
67     position++;
68     }
69    
70     // 13. If there are still further characters in the string, and the next character in the string is a valid denominator punctuation character, return nothing and abort these steps.
71     if (position < string.length && string.charAt (position).match (denominatorPunctuationCharacter)) {
72     return {isNothing: true, step: 13};
73     }
74    
75     // 14. If the string contains any other characters in the range U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9), return nothing and abort these steps.
76     if (string.substring (position).match (/[0-9]/)) {
77     return {isNothing: true, step: 14};
78     }
79    
80     // 15. Otherwise, return number1 and number2.
81     return {number1: number1, number2: number2, step: 15};
82     } // findingOneOrTwoNumbersOfARatioInAString
83    
84     function findANumber (givenString, position) {
85     // 1. Starting at the given starting position, ignore all characters in the given string until the first character that is either a U+002E FULL STOP or one of the ten characters in the range U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9).
86     while (position < givenString.length && !givenString.charAt (position).match (/[0-9.]/)) {
87     position++;
88     }
89    
90     // 2. If there are no such characters, return nothing and abort these steps.
91     if (position < givenString.length && givenString.charAt (position).match (/[0-9.]/)) {
92     //
93     } else {
94     return {isNothing: true, position: position};
95     }
96    
97     // 3. Starting with the character matched in step 1, collect all the consecutive characters that are either a U+002E FULL STOP or one of the ten characters in the range U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9), and assign this string of one or more characters to string.
98     var string = '';
99     while (position < givenString.length && givenString.charAt (position).match (/[0-9.]/)) {
100     string += givenString.charAt (position);
101     position++;
102     }
103    
104     // 4. If string consists of just a single U+002E FULL STOP character or if it contains more than one U+002E FULL STOP character then return an error condition and abort these steps.
105     if (string == '.' || string.match (/\..*\./)) {
106     return {isError: true, position: position};
107     }
108    
109     // 5. Parse string according to the rules for parsing floating point number values, to obtain number. This step cannot fail (string is guaranteed to be a valid floating point number).
110     var s5 = parseFloatingPointNumberValue (string);
111     var number = s5.value;
112    
113     // 6. Return number.
114     return {number: number, position: position};
115     } // findANumber
116    
117     function parseFloatingPointNumberValue (input) {
118     // 1. Let input be the string being parsed.
119     //
120    
121     // 2. Let position be a pointer into input, initially pointing at the start of the string.
122     var position = 0;
123    
124     // 3. Let value have the value 1.
125     var value = 1;
126    
127     // 4. Let divisor have the value 1.
128     var divisor = 1;
129    
130     // 5. Let exponent have the value 1.
131     var exponent = 1;
132    
133     // 6. Skip whitespace.
134     var s6 = skipWhitespace (input, position);
135     position = s6.position;
136    
137     // 7. If position is past the end of input, return an error.
138     if (position >= input.length) {
139     return {isError: true};
140     }
141    
142     // 8. If the character indicated by position is a U+002D HYPHEN-MINUS character (-):
143     if (input.charAt (position) == '-') {
144     // 1. Change value and divisor to −1.
145     value = -1;
146     divisor = -1;
147    
148     // 2. Advance position to the next character.
149     position++;
150    
151     // 3. If position is past the end of input, return an error.
152     if (position >= input.length) {
153     return {isError: true};
154     }
155     }
156    
157     // 9. If the character indicated by position is not one of U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9), then return an error.
158     if (!input.charAt (position).match (/[0-9]/)) {
159     return {isError: true};
160     }
161    
162     // 10. Collect a sequence of characters in the range U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9), and interpret the resulting sequence as a base-ten integer. Multiply value by that integer.
163     var s10 = collectASequenceOfCharacters (/[0-9]/, input, position);
164     position = s10.position;
165     value *= parseInt (s10.result);
166    
167     // 11. If position is past the end of input, return value.
168     if (position >= input.length) {
169     return {value: value};
170     }
171    
172     // 12. If the character indicated by position is a U+002E FULL STOP (.), run these substeps:
173     if (input.charAt (position) == '.') {
174     // 1. Advance position to the next character.
175     position++;
176    
177     // 2. If position is past the end of input, or if the character indicated by position is not one of U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9), then return value.
178     if (position >= input.length ||
179     !input.charAt (position).match (/[0-9]/)) {
180     return {value: value};
181     }
182    
183     // 3. Fraction loop: Multiply divisor by ten.
184     var fractionLoop = true;
185     while (fractionLoop) {
186     divisor *= 10;
187    
188     // 4. Add the value of the current character interpreted as a base-ten digit (0..9) divided by divisor, to value.
189     value += parseInt (input.charAt (position)) / divisor;
190    
191     // 5. Advance position to the next character.
192     position++;
193    
194     // 6. If position is past the end of input, then return value.
195     if (position >= input.length) {
196     return {value: value};
197     }
198    
199     // 7. If the character indicated by position is one of U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9), return to the step labeled fraction loop in these substeps.
200     if (input.charAt (position).match (/[0-9]/)) {
201     fractionLoop = true;
202     } else {
203     fractionLoop = false;
204     }
205     }
206     }
207    
208     // 13. If the character indicated by position is a U+0065 LATIN SMALL LETTER E character (e) or a U+0045 LATIN CAPITAL LETTER E character (E), run these substeps:
209     if (input.charAt (position).match (/[eE]/)) {
210     // 1. Advance position to the next character.
211     position++;
212    
213     // 2. If position is past the end of input, then return value.
214     if (position >= input.length) {
215     return {value: value};
216     }
217    
218     // 3. If the character indicated by position is a U+002D HYPHEN-MINUS character (-):
219     if (input.charAt (position) == '-') {
220     // 1. Change exponent to −1.
221     exponent = -1;
222    
223     // 2. Advance position to the next character.
224     position++;
225    
226     // 3. If position is past the end of input, then return value.
227     if (position >= input.length) {
228     return {value: value};
229     }
230    
231     // Otherwise, if the character indicated by position is a U+002B PLUS SIGN character (+):
232     } else if (input.charAt (position) == '+') {
233     // 1. Advance position to the next character.
234     position++;
235    
236     // 2. If position is past the end of input, then return value.
237     if (position >= input.length) {
238     return {value: value};
239     }
240     }
241    
242     // 4. If the character indicated by position is not one of U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9), then return value.
243     if (!input.charAt (position).match (/[0-9]/)) {
244     return {value: value};
245     }
246    
247     // 5. Collect a sequence of characters in the range U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9), and interpret the resulting sequence as a base-ten integer. Multiply exponent by that integer.
248     var s13_5 = collectASequenceOfCharacters (/[0-9]/, input, position);
249     position = s13_5.position;
250     exponent *= parseInt (s13_5.result);
251    
252     // 6. Multiply value by ten raised to the exponentth power.
253     value *= Math.pow (10, exponent);
254     }
255    
256     // 14. Return value.
257     return {value: value};
258     } // parseFloatingPointNumberValue
259    
260     function skipWhitespace (input, position) {
261     return collectASequenceOfCharacters (/[\u0009\u000A\u000C\u000D\u0020]/, input, position);
262     } // skipWhitespace
263    
264     function collectASequenceOfCharacters (characters, input, position) {
265     // 1. Let input and position be the same variables as those of the same name in the algorithm that invoked these steps.
266     //
267    
268     // 2. Let result be the empty string.
269     var result = '';
270    
271     // 3. While position doesn't point past the end of input and the character at position is one of the characters, append that character to the end of result and advance position to the next character in input.
272     while (position < input.length && input.charAt (position).match (characters)) {
273     result += input.charAt (position);
274     position++;
275     }
276    
277     // 4. Return result.
278     return {result: result, position: position};
279     } // collectASequenceOfCharacters
280    
281 wakaba 1.2 function tokenizeMeterContent (string) {
282 wakaba 1.1 var position = 0;
283     var tokens = [];
284     var lastToken = {type: 'initial', value: ''};
285     while (position < string.length) {
286     var char = string.charAt (position);
287     var tokenType;
288     if (char.match (/[0-9]/)) {
289     tokenType = 'number';
290     } else if (char.match (/\./)) {
291     if (lastToken.type == 'number' && !lastToken.value.match (/\./)) {
292     tokenType = 'number';
293     } else {
294     tokenType = 'dot';
295     }
296     } else if (char.match (whiteSpace)) {
297     if (lastToken.type == 'number' || lastToken.type == 'whitespace') {
298     tokenType = 'whitespace';
299     } else {
300     tokenType = 'string';
301     }
302     } else if (char.match (denominatorPunctuationCharacter) && (lastToken.type == 'whitespace' || lastToken.type == 'number')) {
303     tokenType = 'denominator';
304     } else {
305     tokenType = 'string';
306     }
307     if (tokenType == lastToken.type) {
308     lastToken.value += char;
309     } else {
310     lastToken = {type: tokenType, value: char};
311     tokens.push (lastToken);
312     }
313     position++;
314     }
315    
316     return tokens;
317 wakaba 1.2 } // tokenizeMeterContent
318 wakaba 1.1
319     function extractNumbersFromTokens (tokens) {
320     var number1 = undefined;
321     var number2 = undefined;
322     var denominator = undefined;
323     for (var i = 0; i < tokens.length; i++) {
324     var token = tokens[i];
325     if (token.type == 'number') {
326     if (number1 == undefined) {
327     number1 = parseFloat (token.value);
328     } else if (denominator != undefined) {
329     return {isNothing: true};
330     } else if (number2 == undefined) {
331     number2 = parseFloat (token.value);
332     } else {
333     return {isNothing: true};
334     }
335     } else if (token.type == 'denominator') {
336     if (number2 != undefined) {
337     return {isNothing: true};
338     } else {
339     denominator = token.value;
340     }
341     } else if (token.type == 'dot') {
342     return {isNothing: true};
343     }
344     }
345    
346     if (number1 == undefined) {
347     return {isNothing: true};
348     } else {
349     return {number1: number1, number2: number2, denominator: denominator};
350     }
351     } // extractNumbersFromTokens
352    
353     function objectToString (object) {
354     return self.JSON ? JSON.stringify (object) : object.toSource ? object.toSource () : object.toString ();
355     } // objectToString
356    
357 wakaba 1.2 function processMeterContent (string) {
358 wakaba 1.1 var result = {};
359    
360     var ua = findingOneOrTwoNumbersOfARatioInAString (string);
361     for (var i in ua) {
362     result['ua-' + i] = ua[i];
363     }
364    
365 wakaba 1.2 var tokens = tokenizeMeterContent (string);
366 wakaba 1.1 result['author-tokens'] = objectToString (tokens);
367     var author = extractNumbersFromTokens (tokens);
368     for (var i in author) {
369     result['author-' + i] = author[i];
370     }
371    
372     return result;
373 wakaba 1.2 } // processMeterContent
374 wakaba 1.1
375     function update (form) {
376     var input = form.elements.input.value;
377    
378 wakaba 1.2 var result = processMeterContent (input);
379 wakaba 1.1
380     var outputs = form.getElementsByTagName ('output');
381     for (var i = 0; i < outputs.length; i++) {
382     var output = outputs[i];
383     var name = output.getAttribute ('name');
384     var value = result[name];
385     if (value === undefined) {
386     output.textContent = '(undefined)';
387     } else if (value === null) {
388     output.textContent = '(null)';
389     } else if (value === '') {
390     output.textContent = '(empty)';
391     } else {
392     output.textContent = value;
393     }
394     }
395     } // update
396    
397     </script>
398    
399     <form>
400     <p><input name=input onchange="update (this.form)">
401    
402     <fieldset>
403     <legend>From UA parsing rules</legend>
404    
405     <p><code>step</code>: <output name=ua-step></output>
406     <p><code>isNothing</code>: <output name=ua-isNothing></output>
407     <p><code>number1</code>: <output name=ua-number1></output>
408     <p><code>number2</code>: <output name=ua-number2></output>
409     <p><code>denominator</code>: <output name=ua-denominator></output>
410     </fieldset>
411    
412     <fieldset>
413     <legend>From author requirements</legend>
414    
415     <p><code>isNothing</code>: <output name=author-isNothing></output>
416     <p><code>number1</code>: <output name=author-number1></output>
417     <p><code>number2</code>: <output name=author-number2></output>
418     <p><code>denominator</code>: <output name=author-denominator></output>
419     <p>Tokens: <output name=author-tokens></output>
420     </fieldset>
421     </form>
422    
423     <script>
424     if (location.href.match (/#/)) {
425     var fragment = decodeURIComponent (location.href.split (/#/, 2)[1]);
426     document.forms[0].elements.input.value = fragment;
427     update (document.forms[0]);
428     }
429     </script>

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24