1 |
|
2 | (function(){
|
3 | var reject, special, tokenRegex;
|
4 | reject = require('prelude-ls').reject;
|
5 | function consumeOp(tokens, op){
|
6 | if (tokens[0] === op) {
|
7 | return tokens.shift();
|
8 | } else {
|
9 | throw new Error("Expected '" + op + "', but got '" + tokens[0] + "' instead in " + JSON.stringify(tokens) + ".");
|
10 | }
|
11 | }
|
12 | function maybeConsumeOp(tokens, op){
|
13 | if (tokens[0] === op) {
|
14 | return tokens.shift();
|
15 | }
|
16 | }
|
17 | function consumeList(tokens, arg$, hasDelimiters){
|
18 | var open, close, result, untilTest;
|
19 | open = arg$[0], close = arg$[1];
|
20 | if (hasDelimiters) {
|
21 | consumeOp(tokens, open);
|
22 | }
|
23 | result = [];
|
24 | untilTest = "," + (hasDelimiters ? close : '');
|
25 | while (tokens.length && (hasDelimiters && tokens[0] !== close)) {
|
26 | result.push(consumeElement(tokens, untilTest));
|
27 | maybeConsumeOp(tokens, ',');
|
28 | }
|
29 | if (hasDelimiters) {
|
30 | consumeOp(tokens, close);
|
31 | }
|
32 | return result;
|
33 | }
|
34 | function consumeArray(tokens, hasDelimiters){
|
35 | return consumeList(tokens, ['[', ']'], hasDelimiters);
|
36 | }
|
37 | function consumeTuple(tokens, hasDelimiters){
|
38 | return consumeList(tokens, ['(', ')'], hasDelimiters);
|
39 | }
|
40 | function consumeFields(tokens, hasDelimiters){
|
41 | var result, untilTest, key;
|
42 | if (hasDelimiters) {
|
43 | consumeOp(tokens, '{');
|
44 | }
|
45 | result = {};
|
46 | untilTest = "," + (hasDelimiters ? '}' : '');
|
47 | while (tokens.length && (!hasDelimiters || tokens[0] !== '}')) {
|
48 | key = consumeValue(tokens, ':');
|
49 | consumeOp(tokens, ':');
|
50 | result[key] = consumeElement(tokens, untilTest);
|
51 | maybeConsumeOp(tokens, ',');
|
52 | }
|
53 | if (hasDelimiters) {
|
54 | consumeOp(tokens, '}');
|
55 | }
|
56 | return result;
|
57 | }
|
58 | function consumeValue(tokens, untilTest){
|
59 | var out;
|
60 | untilTest == null && (untilTest = '');
|
61 | out = '';
|
62 | while (tokens.length && -1 === untilTest.indexOf(tokens[0])) {
|
63 | out += tokens.shift();
|
64 | }
|
65 | return out;
|
66 | }
|
67 | function consumeElement(tokens, untilTest){
|
68 | switch (tokens[0]) {
|
69 | case '[':
|
70 | return consumeArray(tokens, true);
|
71 | case '(':
|
72 | return consumeTuple(tokens, true);
|
73 | case '{':
|
74 | return consumeFields(tokens, true);
|
75 | default:
|
76 | return consumeValue(tokens, untilTest);
|
77 | }
|
78 | }
|
79 | function consumeTopLevel(tokens, types, options){
|
80 | var ref$, type, structure, origTokens, result, finalResult, x$, y$;
|
81 | ref$ = types[0], type = ref$.type, structure = ref$.structure;
|
82 | origTokens = tokens.concat();
|
83 | if (!options.explicit && types.length === 1 && ((!type && structure) || (type === 'Array' || type === 'Object'))) {
|
84 | result = structure === 'array' || type === 'Array'
|
85 | ? consumeArray(tokens, tokens[0] === '[')
|
86 | : structure === 'tuple'
|
87 | ? consumeTuple(tokens, tokens[0] === '(')
|
88 | : consumeFields(tokens, tokens[0] === '{');
|
89 | finalResult = tokens.length ? consumeElement(structure === 'array' || type === 'Array'
|
90 | ? (x$ = origTokens, x$.unshift('['), x$.push(']'), x$)
|
91 | : (y$ = origTokens, y$.unshift('('), y$.push(')'), y$)) : result;
|
92 | } else {
|
93 | finalResult = consumeElement(tokens);
|
94 | }
|
95 | return finalResult;
|
96 | }
|
97 | special = /\[\]\(\)}{:,/.source;
|
98 | tokenRegex = RegExp('("(?:\\\\"|[^"])*")|(\'(?:\\\\\'|[^\'])*\')|(/(?:\\\\/|[^/])*/[a-zA-Z]*)|(#.*#)|([' + special + '])|([^\\s' + special + '](?:\\s*[^\\s' + special + ']+)*)|\\s*');
|
99 | module.exports = function(types, string, options){
|
100 | var tokens, node;
|
101 | options == null && (options = {});
|
102 | if (!options.explicit && types.length === 1 && types[0].type === 'String') {
|
103 | return string;
|
104 | }
|
105 | tokens = reject(not$, string.split(tokenRegex));
|
106 | node = consumeTopLevel(tokens, types, options);
|
107 | if (!node) {
|
108 | throw new Error("Error parsing '" + string + "'.");
|
109 | }
|
110 | return node;
|
111 | };
|
112 | function not$(x){ return !x; }
|
113 | }).call(this);
|