docs: function parse_loop(input, customTags) {
      add_tag("default");    
      i = 0;
      while(!input.eos()) {
        if (look(/@class\b/))
          at_class();
        else if (look(/@extends?\b/))
          at_extends()
        else if (look(/@inherits?\b/))
          at_inherits()
        else if (look(/@mixins?\b/))
          class_list_at_tag(/@mixins?/, "mixins");
        else if (look(/@alternateClassNames?\b/))
          class_list_at_tag(/@alternateClassNames?/, "alternateClassNames");
        else if (look(/@uses\b/))
          class_list_at_tag(/@uses/, "uses");
        else if (look(/@requires\b/))
          class_list_at_tag(/@requires/, "requires");
        else if (look(/@singleton\b/))
          boolean_at_tag(/@singleton/, "singleton");
        else if (look(/@event\b/))
          at_event();
        else if (look(/@method\b/))
          at_method();
        else if (look(/@constructor\b/))
          at_method(true);
        else if (look(/@attribute\b/))
          at_attribute();
        else if (look(/@binding\b/))
          at_binding();
        else if (look(/@param\b/))
          at_param();
        else if (look(/@returns?\b/))
          at_return();
        else if (look(/@cfg\b/))
          at_cfg();
        else if (look(/@property\b/))
          at_property();
        else if (look(/@type\s/))
          at_type();
        else if (look(/@xtype\b/))
          at_xtype(/@xtype/, "widget");
        else if (look(/@ftype\b/))
          at_xtype(/@ftype/, "feature");
        else if (look(/@ptype\b/))
          at_xtype(/@ptype/, "plugin");
        else if (look(/@member\b/))
          at_member();
        else if (look(/@inherit[dD]oc\b/))
          at_inheritdoc();
        else if (look(/@alias/))
          at_alias();
        else if (look(/@see/))
          at_see();
        else if (look(/@todo/))
          at_todo();
        else if (look(/@link/))
          at_link();
        else if (look(/@var\b/))
          at_var();
        else if (look(/@throws?\b/))
          at_throws();
        else if (look(/@enum\b/))
          at_enum();
        else if (look(/@override\b/))
          at_override();
        else if (look(/@cancelable\b/))
          at_cancelable();
        else if (look(/@author\b/))
          at_author();
        else if (look(/@version\b/))
          at_version();
        else if (look(/@since\b/))
          at_since();
        else if (look(/@deprecated\b/))
          at_deprecated();
        else if (look(/@related\b/))
          at_related();
        else if (look(/@private\b/))
          boolean_at_tag(/@private/, "private");
        else if (look(/@ignore\b/))
          boolean_at_tag(/@ignore/, "ignore");
        else if (look(/@experimental\b/))
          boolean_at_tag(/@experimental/, "experimental");
        else if (look(/@chainable\b/))
          boolean_at_tag(/@chainable/, "chainable");
        else if (look(/@inheritable\b/))
          boolean_at_tag(/@inheritable/, "inheritable");
        else if (look(/@accessor\b/))
          boolean_at_tag(/@accessor/, "accessor");
        else if (look(/@evented\b/))
          boolean_at_tag(/@evented/, "evented");
        else if (look(/@bubbles\b/))
          boolean_at_tag(/@bubbles/, "bubbles");
        else if (look(/@read\-?only\b/))
          boolean_at_tag(/@read\-?only/, "readonly");
        else if (look(/@default_private\b/))
          boolean_at_tag(/@default_private/, "default_private");
        else if (look(/@/)) {
          match(/@/);
          var tagName = look(/\w+/);
  
          var found = _.find(customTags, function(tag) {
            return RegExp(tag).test(tagName);
          });
  
          if (found) {
            match(found);
            add_tag(tagName);
            skip_horiz_white();
  
            if (look(/.*/).length > 0) 
              current_tag["doc"] = strip(match(/.*/)); // no text means it's a boolean
          }
          else {
            // basically, "@" has to be the first dang thing after the *
            // this resolves false positives, like [@read] 
            var currPos = input.pointer();
            input.setPointer(currPos - (tagName.length + 3));
           
            var startingLine = input.peek(tagName.length + 3);
           
            if (!/.@/.test(startingLine)) {
              console.warn("Warning".yellow + ": I found @" + tagName + ", but I'm not sure what it ought to do.");
            }
  
            input.setPointer(currPos);
  
            current_tag["doc"] += "@";
          }
  
        }
        else if (look(/[^@]/)) {
          current_tag["doc"] += match(/[^@]+/);
        }
      }
  }