Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / LayoutTests / http / tests / w3c / resources / WebIDLParser.js
blob2693934c854976d9cf1c7eaf87c73d96ecc6ccb5
3 (function () {
4 var tokenise = function (str) {
5 var tokens = []
6 , re = {
7 "float": /^-?(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][-+]?[0-9]+)?|[0-9]+[Ee][-+]?[0-9]+)/
8 , "integer": /^-?(0([Xx][0-9A-Fa-f]+|[0-7]*)|[1-9][0-9]*)/
9 , "identifier": /^[A-Z_a-z][0-9A-Z_a-z]*/
10 , "string": /^"[^"]*"/
11 , "whitespace": /^(?:[\t\n\r ]+|[\t\n\r ]*((\/\/.*|\/\*(.|\n|\r)*?\*\/)[\t\n\r ]*))+/
12 , "other": /^[^\t\n\r 0-9A-Z_a-z]/
14 , types = []
16 for (var k in re) types.push(k);
17 while (str.length > 0) {
18 var matched = false;
19 for (var i = 0, n = types.length; i < n; i++) {
20 var type = types[i];
21 str = str.replace(re[type], function (tok) {
22 tokens.push({ type: type, value: tok });
23 matched = true;
24 return "";
25 });
26 if (matched) break;
28 if (matched) continue;
29 throw new Error("Token stream not progressing");
31 return tokens;
34 var parse = function (tokens, opt) {
35 var line = 1;
36 tokens = tokens.slice();
38 var FLOAT = "float"
39 , INT = "integer"
40 , ID = "identifier"
41 , STR = "string"
42 , OTHER = "other"
45 var WebIDLParseError = function (str, line, input, tokens) {
46 this.message = str;
47 this.line = line;
48 this.input = input;
49 this.tokens = tokens;
51 WebIDLParseError.prototype.toString = function () {
52 return this.message + ", line " + this.line + " (tokens: '" + this.input + "')\n" +
53 JSON.stringify(this.tokens, null, 4);
56 var error = function (str) {
57 var tok = "", numTokens = 0, maxTokens = 5;
58 while (numTokens < maxTokens && tokens.length > numTokens) {
59 tok += tokens[numTokens].value;
60 numTokens++;
62 throw new WebIDLParseError(str, line, tok, tokens.slice(0, 5));
65 var last_token = null;
67 var consume = function (type, value) {
68 if (!tokens.length || tokens[0].type !== type) return;
69 if (typeof value === "undefined" || tokens[0].value === value) {
70 last_token = tokens.shift();
71 if (type === ID) last_token.value = last_token.value.replace(/^_/, "");
72 return last_token;
76 var ws = function () {
77 if (!tokens.length) return;
78 if (tokens[0].type === "whitespace") {
79 var t = tokens.shift();
80 t.value.replace(/\n/g, function (m) { line++; return m; });
81 return t;
85 var all_ws = function (store, pea) { // pea == post extended attribute, tpea = same for types
86 var t = { type: "whitespace", value: "" };
87 while (true) {
88 var w = ws();
89 if (!w) break;
90 t.value += w.value;
92 if (t.value.length > 0) {
93 if (store) {
94 var w = t.value
95 , re = {
96 "ws": /^([\t\n\r ]+)/
97 , "line-comment": /^\/\/(.*)\n?/m
98 , "multiline-comment": /^\/\*((?:.|\n|\r)*?)\*\//
100 , wsTypes = []
102 for (var k in re) wsTypes.push(k);
103 while (w.length) {
104 var matched = false;
105 for (var i = 0, n = wsTypes.length; i < n; i++) {
106 var type = wsTypes[i];
107 w = w.replace(re[type], function (tok, m1) {
108 store.push({ type: type + (pea ? ("-" + pea) : ""), value: m1 });
109 matched = true;
110 return "";
112 if (matched) break;
114 if (matched) continue;
115 throw new Error("Surprising white space construct."); // this shouldn't happen
118 return t;
122 var integer_type = function () {
123 var ret = "";
124 all_ws();
125 if (consume(ID, "unsigned")) ret = "unsigned ";
126 all_ws();
127 if (consume(ID, "short")) return ret + "short";
128 if (consume(ID, "long")) {
129 ret += "long";
130 all_ws();
131 if (consume(ID, "long")) return ret + " long";
132 return ret;
134 if (ret) error("Failed to parse integer type");
137 var float_type = function () {
138 var ret = "";
139 all_ws();
140 if (consume(ID, "unrestricted")) ret = "unrestricted ";
141 all_ws();
142 if (consume(ID, "float")) return ret + "float";
143 if (consume(ID, "double")) return ret + "double";
144 if (ret) error("Failed to parse float type");
147 var primitive_type = function () {
148 var num_type = integer_type() || float_type();
149 if (num_type) return num_type;
150 all_ws();
151 if (consume(ID, "boolean")) return "boolean";
152 if (consume(ID, "byte")) return "byte";
153 if (consume(ID, "octet")) return "octet";
156 var const_value = function () {
157 if (consume(ID, "true")) return { type: "boolean", value: true };
158 if (consume(ID, "false")) return { type: "boolean", value: false };
159 if (consume(ID, "null")) return { type: "null" };
160 if (consume(ID, "Infinity")) return { type: "Infinity", negative: false };
161 if (consume(ID, "NaN")) return { type: "NaN" };
162 var ret = consume(FLOAT) || consume(INT);
163 if (ret) return { type: "number", value: 1 * ret.value };
164 var tok = consume(OTHER, "-");
165 if (tok) {
166 if (consume(ID, "Infinity")) return { type: "Infinity", negative: true };
167 else tokens.unshift(tok);
171 var type_suffix = function (obj) {
172 while (true) {
173 all_ws();
174 if (consume(OTHER, "?")) {
175 if (obj.nullable) error("Can't nullable more than once");
176 obj.nullable = true;
178 else if (consume(OTHER, "[")) {
179 all_ws();
180 consume(OTHER, "]") || error("Unterminated array type");
181 if (!obj.array) {
182 obj.array = 1;
183 obj.nullableArray = [obj.nullable];
185 else {
186 obj.array++;
187 obj.nullableArray.push(obj.nullable);
189 obj.nullable = false;
191 else return;
195 var single_type = function () {
196 var prim = primitive_type()
197 , ret = { sequence: false, generic: null, nullable: false, array: false, union: false }
198 , name
199 , value
201 if (prim) {
202 ret.idlType = prim;
204 else if (name = consume(ID)) {
205 value = name.value;
206 all_ws();
207 // Generic types
208 if (consume(OTHER, "<")) {
209 // backwards compat
210 if (value === "sequence") {
211 ret.sequence = true;
213 ret.generic = value;
214 ret.idlType = type() || error("Error parsing generic type " + value);
215 all_ws();
216 if (!consume(OTHER, ">")) error("Unterminated generic type " + value);
217 all_ws();
218 if (consume(OTHER, "?")) ret.nullable = true;
219 return ret;
221 else {
222 ret.idlType = value;
225 else {
226 return;
228 type_suffix(ret);
229 if (ret.nullable && !ret.array && ret.idlType === "any") error("Type any cannot be made nullable");
230 return ret;
233 var union_type = function () {
234 all_ws();
235 if (!consume(OTHER, "(")) return;
236 var ret = { sequence: false, generic: null, nullable: false, array: false, union: true, idlType: [] };
237 var fst = type() || error("Union type with no content");
238 ret.idlType.push(fst);
239 while (true) {
240 all_ws();
241 if (!consume(ID, "or")) break;
242 var typ = type() || error("No type after 'or' in union type");
243 ret.idlType.push(typ);
245 if (!consume(OTHER, ")")) error("Unterminated union type");
246 type_suffix(ret);
247 return ret;
250 var type = function () {
251 return single_type() || union_type();
254 var argument = function (store) {
255 var ret = { optional: false, variadic: false };
256 ret.extAttrs = extended_attrs(store);
257 all_ws(store, "pea");
258 var opt_token = consume(ID, "optional");
259 if (opt_token) {
260 ret.optional = true;
261 all_ws();
263 ret.idlType = type();
264 if (!ret.idlType) {
265 if (opt_token) tokens.unshift(opt_token);
266 return;
268 var type_token = last_token;
269 if (!ret.optional) {
270 all_ws();
271 if (tokens.length >= 3 &&
272 tokens[0].type === "other" && tokens[0].value === "." &&
273 tokens[1].type === "other" && tokens[1].value === "." &&
274 tokens[2].type === "other" && tokens[2].value === "."
276 tokens.shift();
277 tokens.shift();
278 tokens.shift();
279 ret.variadic = true;
282 all_ws();
283 var name = consume(ID);
284 if (!name) {
285 if (opt_token) tokens.unshift(opt_token);
286 tokens.unshift(type_token);
287 return;
289 ret.name = name.value;
290 if (ret.optional) {
291 all_ws();
292 ret["default"] = default_();
294 return ret;
297 var argument_list = function (store) {
298 var ret = []
299 , arg = argument(store ? ret : null)
301 if (!arg) return;
302 ret.push(arg);
303 while (true) {
304 all_ws(store ? ret : null);
305 if (!consume(OTHER, ",")) return ret;
306 var nxt = argument(store ? ret : null) || error("Trailing comma in arguments list");
307 ret.push(nxt);
311 var type_pair = function () {
312 all_ws();
313 var k = type();
314 if (!k) return;
315 all_ws()
316 if (!consume(OTHER, ",")) return;
317 all_ws();
318 var v = type();
319 if (!v) return;
320 return [k, v];
323 var simple_extended_attr = function (store) {
324 all_ws();
325 var name = consume(ID);
326 if (!name) return;
327 var ret = {
328 name: name.value
329 , "arguments": null
331 all_ws();
332 var eq = consume(OTHER, "=");
333 if (eq) {
334 all_ws();
335 ret.rhs = consume(ID);
336 if (!ret.rhs) return error("No right hand side to extended attribute assignment");
338 all_ws();
339 if (consume(OTHER, "(")) {
340 var args, pair;
341 // [Constructor(DOMString str)]
342 if (args = argument_list(store)) {
343 ret["arguments"] = args;
345 // [MapClass(DOMString, DOMString)]
346 else if (pair = type_pair()) {
347 ret.typePair = pair;
349 // [Constructor()]
350 else {
351 ret["arguments"] = [];
353 all_ws();
354 consume(OTHER, ")") || error("Unexpected token in extended attribute argument list or type pair");
356 return ret;
359 // Note: we parse something simpler than the official syntax. It's all that ever
360 // seems to be used
361 var extended_attrs = function (store) {
362 var eas = [];
363 all_ws(store);
364 if (!consume(OTHER, "[")) return eas;
365 eas[0] = simple_extended_attr(store) || error("Extended attribute with not content");
366 all_ws();
367 while (consume(OTHER, ",")) {
368 eas.push(simple_extended_attr(store) || error("Trailing comma in extended attribute"));
369 all_ws();
371 consume(OTHER, "]") || error("No end of extended attribute");
372 return eas;
375 var default_ = function () {
376 all_ws();
377 if (consume(OTHER, "=")) {
378 all_ws();
379 var def = const_value();
380 if (def) {
381 return def;
383 else {
384 var str = consume(STR) || error("No value for default");
385 str.value = str.value.replace(/^"/, "").replace(/"$/, "");
386 return str;
391 var const_ = function (store) {
392 all_ws(store, "pea");
393 if (!consume(ID, "const")) return;
394 var ret = { type: "const", nullable: false };
395 all_ws();
396 var typ = primitive_type();
397 if (!typ) {
398 typ = consume(ID) || error("No type for const");
399 typ = typ.value;
401 ret.idlType = typ;
402 all_ws();
403 if (consume(OTHER, "?")) {
404 ret.nullable = true;
405 all_ws();
407 var name = consume(ID) || error("No name for const");
408 ret.name = name.value;
409 all_ws();
410 consume(OTHER, "=") || error("No value assignment for const");
411 all_ws();
412 var cnt = const_value();
413 if (cnt) ret.value = cnt;
414 else error("No value for const");
415 all_ws();
416 consume(OTHER, ";") || error("Unterminated const");
417 return ret;
420 var inheritance = function () {
421 all_ws();
422 if (consume(OTHER, ":")) {
423 all_ws();
424 var inh = consume(ID) || error ("No type in inheritance");
425 return inh.value;
429 var operation_rest = function (ret, store) {
430 all_ws();
431 if (!ret) ret = {};
432 var name = consume(ID);
433 ret.name = name ? name.value : null;
434 all_ws();
435 consume(OTHER, "(") || error("Invalid operation");
436 ret["arguments"] = argument_list(store) || [];
437 all_ws();
438 consume(OTHER, ")") || error("Unterminated operation");
439 all_ws();
440 consume(OTHER, ";") || error("Unterminated operation");
441 return ret;
444 var callback = function (store) {
445 all_ws(store, "pea");
446 var ret;
447 if (!consume(ID, "callback")) return;
448 all_ws();
449 var tok = consume(ID, "interface");
450 if (tok) {
451 tokens.unshift(tok);
452 ret = interface_();
453 ret.type = "callback interface";
454 return ret;
456 var name = consume(ID) || error("No name for callback");
457 ret = { type: "callback", name: name.value };
458 all_ws();
459 consume(OTHER, "=") || error("No assignment in callback");
460 all_ws();
461 ret.idlType = return_type();
462 all_ws();
463 consume(OTHER, "(") || error("No arguments in callback");
464 ret["arguments"] = argument_list(store) || [];
465 all_ws();
466 consume(OTHER, ")") || error("Unterminated callback");
467 all_ws();
468 consume(OTHER, ";") || error("Unterminated callback");
469 return ret;
472 var attribute = function (store) {
473 all_ws(store, "pea");
474 var grabbed = []
475 , ret = {
476 type: "attribute"
477 , "static": false
478 , stringifier: false
479 , inherit: false
480 , readonly: false
482 if (consume(ID, "static")) {
483 ret["static"] = true;
484 grabbed.push(last_token);
486 else if (consume(ID, "stringifier")) {
487 ret.stringifier = true;
488 grabbed.push(last_token);
490 var w = all_ws();
491 if (w) grabbed.push(w);
492 if (consume(ID, "inherit")) {
493 if (ret["static"] || ret.stringifier) error("Cannot have a static or stringifier inherit");
494 ret.inherit = true;
495 grabbed.push(last_token);
496 var w = all_ws();
497 if (w) grabbed.push(w);
499 if (consume(ID, "readonly")) {
500 ret.readonly = true;
501 grabbed.push(last_token);
502 var w = all_ws();
503 if (w) grabbed.push(w);
505 if (!consume(ID, "attribute")) {
506 tokens = grabbed.concat(tokens);
507 return;
509 all_ws();
510 ret.idlType = type() || error("No type in attribute");
511 if (ret.idlType.sequence) error("Attributes cannot accept sequence types");
512 all_ws();
513 var name = consume(ID) || error("No name in attribute");
514 ret.name = name.value;
515 all_ws();
516 consume(OTHER, ";") || error("Unterminated attribute");
517 return ret;
520 var return_type = function () {
521 var typ = type();
522 if (!typ) {
523 if (consume(ID, "void")) {
524 return "void";
526 else error("No return type");
528 return typ;
531 var operation = function (store) {
532 all_ws(store, "pea");
533 var ret = {
534 type: "operation"
535 , getter: false
536 , setter: false
537 , creator: false
538 , deleter: false
539 , legacycaller: false
540 , "static": false
541 , stringifier: false
543 while (true) {
544 all_ws();
545 if (consume(ID, "getter")) ret.getter = true;
546 else if (consume(ID, "setter")) ret.setter = true;
547 else if (consume(ID, "creator")) ret.creator = true;
548 else if (consume(ID, "deleter")) ret.deleter = true;
549 else if (consume(ID, "legacycaller")) ret.legacycaller = true;
550 else break;
552 if (ret.getter || ret.setter || ret.creator || ret.deleter || ret.legacycaller) {
553 all_ws();
554 ret.idlType = return_type();
555 operation_rest(ret, store);
556 return ret;
558 if (consume(ID, "static")) {
559 ret["static"] = true;
560 ret.idlType = return_type();
561 operation_rest(ret, store);
562 return ret;
564 else if (consume(ID, "stringifier")) {
565 ret.stringifier = true;
566 all_ws();
567 if (consume(OTHER, ";")) return ret;
568 ret.idlType = return_type();
569 operation_rest(ret, store);
570 return ret;
572 ret.idlType = return_type();
573 all_ws();
574 if (consume(ID, "iterator")) {
575 all_ws();
576 ret.type = "iterator";
577 if (consume(ID, "object")) {
578 ret.iteratorObject = "object";
580 else if (consume(OTHER, "=")) {
581 all_ws();
582 var name = consume(ID) || error("No right hand side in iterator");
583 ret.iteratorObject = name.value;
585 all_ws();
586 consume(OTHER, ";") || error("Unterminated iterator");
587 return ret;
589 else {
590 operation_rest(ret, store);
591 return ret;
595 var identifiers = function (arr) {
596 while (true) {
597 all_ws();
598 if (consume(OTHER, ",")) {
599 all_ws();
600 var name = consume(ID) || error("Trailing comma in identifiers list");
601 arr.push(name.value);
603 else break;
607 var serialiser = function (store) {
608 all_ws(store, "pea");
609 if (!consume(ID, "serializer")) return;
610 var ret = { type: "serializer" };
611 all_ws();
612 if (consume(OTHER, "=")) {
613 all_ws();
614 if (consume(OTHER, "{")) {
615 ret.patternMap = true;
616 all_ws();
617 var id = consume(ID);
618 if (id && id.value === "getter") {
619 ret.names = ["getter"];
621 else if (id && id.value === "inherit") {
622 ret.names = ["inherit"];
623 identifiers(ret.names);
625 else if (id) {
626 ret.names = [id.value];
627 identifiers(ret.names);
629 else {
630 ret.names = [];
632 all_ws();
633 consume(OTHER, "}") || error("Unterminated serializer pattern map");
635 else if (consume(OTHER, "[")) {
636 ret.patternList = true;
637 all_ws();
638 var id = consume(ID);
639 if (id && id.value === "getter") {
640 ret.names = ["getter"];
642 else if (id) {
643 ret.names = [id.value];
644 identifiers(ret.names);
646 else {
647 ret.names = [];
649 all_ws();
650 consume(OTHER, "]") || error("Unterminated serializer pattern list");
652 else {
653 var name = consume(ID) || error("Invalid serializer");
654 ret.name = name.value;
656 all_ws();
657 consume(OTHER, ";") || error("Unterminated serializer");
658 return ret;
660 else if (consume(OTHER, ";")) {
661 // noop, just parsing
663 else {
664 ret.idlType = return_type();
665 all_ws();
666 ret.operation = operation_rest(null, store);
668 return ret;
671 var interface_ = function (isPartial, store) {
672 all_ws(isPartial ? null : store, "pea");
673 if (!consume(ID, "interface")) return;
674 all_ws();
675 var name = consume(ID) || error("No name for interface");
676 var mems = []
677 , ret = {
678 type: "interface"
679 , name: name.value
680 , partial: false
681 , members: mems
683 if (!isPartial) ret.inheritance = inheritance() || null;
684 all_ws();
685 consume(OTHER, "{") || error("Bodyless interface");
686 while (true) {
687 all_ws(store ? mems : null);
688 if (consume(OTHER, "}")) {
689 all_ws();
690 consume(OTHER, ";") || error("Missing semicolon after interface");
691 return ret;
693 var ea = extended_attrs(store ? mems : null);
694 all_ws();
695 var cnt = const_(store ? mems : null);
696 if (cnt) {
697 cnt.extAttrs = ea;
698 ret.members.push(cnt);
699 continue;
701 var mem = serialiser(store ? mems : null) ||
702 attribute(store ? mems : null) ||
703 operation(store ? mems : null) ||
704 error("Unknown member");
705 mem.extAttrs = ea;
706 ret.members.push(mem);
710 var partial = function (store) {
711 all_ws(store, "pea");
712 if (!consume(ID, "partial")) return;
713 var thing = dictionary(true, store) ||
714 interface_(true, store) ||
715 error("Partial doesn't apply to anything");
716 thing.partial = true;
717 return thing;
720 var dictionary = function (isPartial, store) {
721 all_ws(isPartial ? null : store, "pea");
722 if (!consume(ID, "dictionary")) return;
723 all_ws();
724 var name = consume(ID) || error("No name for dictionary");
725 var mems = []
726 , ret = {
727 type: "dictionary"
728 , name: name.value
729 , partial: false
730 , members: mems
732 if (!isPartial) ret.inheritance = inheritance() || null;
733 all_ws();
734 consume(OTHER, "{") || error("Bodyless dictionary");
735 while (true) {
736 all_ws(store ? mems : null);
737 if (consume(OTHER, "}")) {
738 all_ws();
739 consume(OTHER, ";") || error("Missing semicolon after dictionary");
740 return ret;
742 var ea = extended_attrs(store ? mems : null);
743 all_ws(store ? mems : null, "pea");
744 var typ = type() || error("No type for dictionary member");
745 all_ws();
746 var name = consume(ID) || error("No name for dictionary member");
747 ret.members.push({
748 type: "field"
749 , name: name.value
750 , idlType: typ
751 , extAttrs: ea
752 , "default": default_()
754 all_ws();
755 consume(OTHER, ";") || error("Unterminated dictionary member");
759 var exception = function (store) {
760 all_ws(store, "pea");
761 if (!consume(ID, "exception")) return;
762 all_ws();
763 var name = consume(ID) || error("No name for exception");
764 var mems = []
765 , ret = {
766 type: "exception"
767 , name: name.value
768 , members: mems
770 ret.inheritance = inheritance() || null;
771 all_ws();
772 consume(OTHER, "{") || error("Bodyless exception");
773 while (true) {
774 all_ws(store ? mems : null);
775 if (consume(OTHER, "}")) {
776 all_ws();
777 consume(OTHER, ";") || error("Missing semicolon after exception");
778 return ret;
780 var ea = extended_attrs(store ? mems : null);
781 all_ws(store ? mems : null, "pea");
782 var cnt = const_();
783 if (cnt) {
784 cnt.extAttrs = ea;
785 ret.members.push(cnt);
787 else {
788 var typ = type();
789 all_ws();
790 var name = consume(ID);
791 all_ws();
792 if (!typ || !name || !consume(OTHER, ";")) error("Unknown member in exception body");
793 ret.members.push({
794 type: "field"
795 , name: name.value
796 , idlType: typ
797 , extAttrs: ea
803 var enum_ = function (store) {
804 all_ws(store, "pea");
805 if (!consume(ID, "enum")) return;
806 all_ws();
807 var name = consume(ID) || error("No name for enum");
808 var vals = []
809 , ret = {
810 type: "enum"
811 , name: name.value
812 , values: vals
814 all_ws();
815 consume(OTHER, "{") || error("No curly for enum");
816 var saw_comma = false;
817 while (true) {
818 all_ws(store ? vals : null);
819 if (consume(OTHER, "}")) {
820 all_ws();
821 if (saw_comma) error("Trailing comma in enum");
822 consume(OTHER, ";") || error("No semicolon after enum");
823 return ret;
825 var val = consume(STR) || error("Unexpected value in enum");
826 ret.values.push(val.value.replace(/"/g, ""));
827 all_ws(store ? vals : null);
828 if (consume(OTHER, ",")) {
829 if (store) vals.push({ type: "," });
830 all_ws(store ? vals : null);
831 saw_comma = true;
833 else {
834 saw_comma = false;
839 var typedef = function (store) {
840 all_ws(store, "pea");
841 if (!consume(ID, "typedef")) return;
842 var ret = {
843 type: "typedef"
845 all_ws();
846 ret.typeExtAttrs = extended_attrs();
847 all_ws(store, "tpea");
848 ret.idlType = type() || error("No type in typedef");
849 all_ws();
850 var name = consume(ID) || error("No name in typedef");
851 ret.name = name.value;
852 all_ws();
853 consume(OTHER, ";") || error("Unterminated typedef");
854 return ret;
857 var implements_ = function (store) {
858 all_ws(store, "pea");
859 var target = consume(ID);
860 if (!target) return;
861 var w = all_ws();
862 if (consume(ID, "implements")) {
863 var ret = {
864 type: "implements"
865 , target: target.value
867 all_ws();
868 var imp = consume(ID) || error("Incomplete implements statement");
869 ret["implements"] = imp.value;
870 all_ws();
871 consume(OTHER, ";") || error("No terminating ; for implements statement");
872 return ret;
874 else {
875 // rollback
876 tokens.unshift(w);
877 tokens.unshift(target);
881 var definition = function (store) {
882 return callback(store) ||
883 interface_(false, store) ||
884 partial(store) ||
885 dictionary(false, store) ||
886 exception(store) ||
887 enum_(store) ||
888 typedef(store) ||
889 implements_(store)
893 var definitions = function (store) {
894 if (!tokens.length) return [];
895 var defs = [];
896 while (true) {
897 var ea = extended_attrs(store ? defs : null)
898 , def = definition(store ? defs : null);
899 if (!def) {
900 if (ea.length) error("Stray extended attributes");
901 break;
903 def.extAttrs = ea;
904 defs.push(def);
906 return defs;
908 var res = definitions(opt.ws);
909 if (tokens.length) error("Unrecognised tokens");
910 return res;
913 var inNode = typeof module !== "undefined" && module.exports
914 , obj = {
915 parse: function (str, opt) {
916 if (!opt) opt = {};
917 var tokens = tokenise(str);
918 return parse(tokens, opt);
922 if (inNode) module.exports = obj;
923 else self.WebIDL2 = obj;
924 }());