// Generated by LiveScript 1.2.0
(function(){
  var reject, tokenRegex;
  reject = require('prelude-ls').reject;
  function consumeWord(tokens){
    var token;
    token = tokens[0];
    if (!(token != null && /^[a-zA-Z]+$/.test(token))) {
      throw new Error("Exected textual string.");
    }
    return tokens.shift();
  }
  function consumeOp(tokens, op){
    var token;
    token = tokens[0];
    if (token !== op) {
      throw new Error("Expected " + op);
    }
    return tokens.shift();
  }
  function maybeConsumeOp(tokens, op){
    var token;
    token = tokens[0];
    if (token === op) {
      return tokens.shift();
    } else {
      return null;
    }
  }
  function consumeArray(tokens){
    var contentType;
    consumeOp(tokens, '[');
    contentType = consumeTypes(tokens);
    if (!contentType) {
      throw new Error("Must specify content type for Array.");
    }
    consumeOp(tokens, ']');
    return {
      type: 'Array',
      contentType: contentType
    };
  }
  function consumeTuple(tokens){
    var contentTypes, that;
    contentTypes = [];
    consumeOp(tokens, '(');
    while (that = consumeTypes(tokens)) {
      contentTypes.push(that);
      if (!maybeConsumeOp(tokens, ',')) {
        break;
      }
    }
    consumeOp(tokens, ')');
    return {
      type: 'Tuple',
      contentTypes: contentTypes
    };
  }
  function consumeProperty(tokens){
    var key, type;
    key = consumeWord(tokens);
    consumeOp(tokens, ':');
    type = consumeTypes(tokens);
    return {
      key: key,
      type: type
    };
  }
  function consumeObject(tokens){
    var properties, that;
    properties = [];
    consumeOp(tokens, '{');
    while (that = consumeProperty(tokens)) {
      properties.push(that);
      if (!maybeConsumeOp(tokens, ',')) {
        break;
      }
    }
    consumeOp(tokens, '}');
    return {
      type: 'Object',
      properties: properties
    };
  }
  function consumeType(tokens){
    switch (tokens[0]) {
    case '[':
      return consumeArray(tokens);
    case '{':
      return consumeObject(tokens);
    case '(':
      return consumeTuple(tokens);
    default:
      return {
        type: consumeWord(tokens)
      };
    }
  }
  function consumeMaybe(tokens){
    var maybe, type;
    if (tokens[0] === 'Maybe') {
      tokens.shift();
      maybe = true;
    }
    type = consumeType(tokens);
    if (maybe) {
      return {
        type: 'Maybe',
        contentType: type
      };
    } else {
      return type;
    }
  }
  function consumeTypes(tokens){
    var types;
    types = [];
    for (;;) {
      types.push(consumeMaybe(tokens));
      if (!maybeConsumeOp('|')) {
        break;
      }
    }
    if (!types.length) {
      throw new Error("Expected type(s).");
    }
    return types;
  }
  tokenRegex = /[:,\[\]\(\)}{]|[a-zA-Z]+/g;
  module.exports = function(input){
    var tokens, e;
    tokens = reject(function(it){
      return /^\s*$/.test(it);
    })(
    input.match(tokenRegex));
    try {
      return consumeTypes(tokens);
    } catch (e$) {
      e = e$;
      throw new Error(e.message + " - '" + tokens.join('#') + "' - '" + input + "'");
    }
  };
}).call(this);
