0a114c027e24fabc780ba4c81e48c22c18d822725916743a5852ce3b0e5030304992c14ce9c87e6d73c4e2c390306bb875c6f680298478e0d3518622542e17 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. // Generated by LiveScript 1.6.0
  2. (function(){
  3. var identifierRegex, tokenRegex;
  4. identifierRegex = /[\$\w]+/;
  5. function peek(tokens){
  6. var token;
  7. token = tokens[0];
  8. if (token == null) {
  9. throw new Error('Unexpected end of input.');
  10. }
  11. return token;
  12. }
  13. function consumeIdent(tokens){
  14. var token;
  15. token = peek(tokens);
  16. if (!identifierRegex.test(token)) {
  17. throw new Error("Expected text, got '" + token + "' instead.");
  18. }
  19. return tokens.shift();
  20. }
  21. function consumeOp(tokens, op){
  22. var token;
  23. token = peek(tokens);
  24. if (token !== op) {
  25. throw new Error("Expected '" + op + "', got '" + token + "' instead.");
  26. }
  27. return tokens.shift();
  28. }
  29. function maybeConsumeOp(tokens, op){
  30. var token;
  31. token = tokens[0];
  32. if (token === op) {
  33. return tokens.shift();
  34. } else {
  35. return null;
  36. }
  37. }
  38. function consumeArray(tokens){
  39. var types;
  40. consumeOp(tokens, '[');
  41. if (peek(tokens) === ']') {
  42. throw new Error("Must specify type of Array - eg. [Type], got [] instead.");
  43. }
  44. types = consumeTypes(tokens);
  45. consumeOp(tokens, ']');
  46. return {
  47. structure: 'array',
  48. of: types
  49. };
  50. }
  51. function consumeTuple(tokens){
  52. var components;
  53. components = [];
  54. consumeOp(tokens, '(');
  55. if (peek(tokens) === ')') {
  56. throw new Error("Tuple must be of at least length 1 - eg. (Type), got () instead.");
  57. }
  58. for (;;) {
  59. components.push(consumeTypes(tokens));
  60. maybeConsumeOp(tokens, ',');
  61. if (')' === peek(tokens)) {
  62. break;
  63. }
  64. }
  65. consumeOp(tokens, ')');
  66. return {
  67. structure: 'tuple',
  68. of: components
  69. };
  70. }
  71. function consumeFields(tokens){
  72. var fields, subset, ref$, key, types;
  73. fields = {};
  74. consumeOp(tokens, '{');
  75. subset = false;
  76. for (;;) {
  77. if (maybeConsumeOp(tokens, '...')) {
  78. subset = true;
  79. break;
  80. }
  81. ref$ = consumeField(tokens), key = ref$[0], types = ref$[1];
  82. fields[key] = types;
  83. maybeConsumeOp(tokens, ',');
  84. if ('}' === peek(tokens)) {
  85. break;
  86. }
  87. }
  88. consumeOp(tokens, '}');
  89. return {
  90. structure: 'fields',
  91. of: fields,
  92. subset: subset
  93. };
  94. }
  95. function consumeField(tokens){
  96. var key, types;
  97. key = consumeIdent(tokens);
  98. consumeOp(tokens, ':');
  99. types = consumeTypes(tokens);
  100. return [key, types];
  101. }
  102. function maybeConsumeStructure(tokens){
  103. switch (tokens[0]) {
  104. case '[':
  105. return consumeArray(tokens);
  106. case '(':
  107. return consumeTuple(tokens);
  108. case '{':
  109. return consumeFields(tokens);
  110. }
  111. }
  112. function consumeType(tokens){
  113. var token, wildcard, type, structure;
  114. token = peek(tokens);
  115. wildcard = token === '*';
  116. if (wildcard || identifierRegex.test(token)) {
  117. type = wildcard
  118. ? consumeOp(tokens, '*')
  119. : consumeIdent(tokens);
  120. structure = maybeConsumeStructure(tokens);
  121. if (structure) {
  122. return structure.type = type, structure;
  123. } else {
  124. return {
  125. type: type
  126. };
  127. }
  128. } else {
  129. structure = maybeConsumeStructure(tokens);
  130. if (!structure) {
  131. throw new Error("Unexpected character: " + token);
  132. }
  133. return structure;
  134. }
  135. }
  136. function consumeTypes(tokens){
  137. var lookahead, types, typesSoFar, typeObj, type, structure;
  138. if ('::' === peek(tokens)) {
  139. throw new Error("No comment before comment separator '::' found.");
  140. }
  141. lookahead = tokens[1];
  142. if (lookahead != null && lookahead === '::') {
  143. tokens.shift();
  144. tokens.shift();
  145. }
  146. types = [];
  147. typesSoFar = {};
  148. if ('Maybe' === peek(tokens)) {
  149. tokens.shift();
  150. types = [
  151. {
  152. type: 'Undefined'
  153. }, {
  154. type: 'Null'
  155. }
  156. ];
  157. typesSoFar = {
  158. Undefined: true,
  159. Null: true
  160. };
  161. }
  162. for (;;) {
  163. typeObj = consumeType(tokens), type = typeObj.type, structure = typeObj.structure;
  164. if (!typesSoFar[type]) {
  165. types.push(typeObj);
  166. }
  167. if (structure == null) {
  168. typesSoFar[type] = true;
  169. }
  170. if (!maybeConsumeOp(tokens, '|')) {
  171. break;
  172. }
  173. }
  174. return types;
  175. }
  176. tokenRegex = RegExp('\\.\\.\\.|::|->|' + identifierRegex.source + '|\\S', 'g');
  177. module.exports = function(input){
  178. var tokens, e;
  179. if (!input.length) {
  180. throw new Error('No type specified.');
  181. }
  182. tokens = input.match(tokenRegex) || [];
  183. if (in$('->', tokens)) {
  184. throw new Error("Function types are not supported.\ To validate that something is a function, you may use 'Function'.");
  185. }
  186. try {
  187. return consumeTypes(tokens);
  188. } catch (e$) {
  189. e = e$;
  190. throw new Error(e.message + " - Remaining tokens: " + JSON.stringify(tokens) + " - Initial input: '" + input + "'");
  191. }
  192. };
  193. function in$(x, xs){
  194. var i = -1, l = xs.length >>> 0;
  195. while (++i < l) if (x === xs[i]) return true;
  196. return false;
  197. }
  198. }).call(this);