whole_func_string: function () {
                  var index = parserInput.i, name, value, rules, nonVendorSpecificName,
                      hasIdentifier, hasExpression, hasUnknown, hasBlock = true, isRooted = true;
  
                  if (parserInput.currentChar() !== '@') { return; }
  
                  value = this['import']() || this.plugin() || this.media();
                  if (value) {
                      return value;
                  }
  
                  parserInput.save();
  
                  name = parserInput.$re(/^@[a-z-]+/);
  
                  if (!name) { return; }
  
                  nonVendorSpecificName = name;
                  if (name.charAt(1) == '-' && name.indexOf('-', 2) > 0) {
                      nonVendorSpecificName = '@' + name.slice(name.indexOf('-', 2) + 1);
                  }
  
                  switch (nonVendorSpecificName) {
                      case '@charset':
                          hasIdentifier = true;
                          hasBlock = false;
                          break;
                      case '@namespace':
                          hasExpression = true;
                          hasBlock = false;
                          break;
                      case '@keyframes':
                      case '@counter-style':
                          hasIdentifier = true;
                          break;
                      case '@document':
                      case '@supports':
                          hasUnknown = true;
                          isRooted = false;
                          break;
                      default:
                          hasUnknown = true;
                          break;
                  }
  
                  parserInput.commentStore.length = 0;
  
                  if (hasIdentifier) {
                      value = this.entity();
                      if (!value) {
                          error('expected ' + name + ' identifier');
                      }
                  } else if (hasExpression) {
                      value = this.expression();
                      if (!value) {
                          error('expected ' + name + ' expression');
                      }
                  } else if (hasUnknown) {
                      value = this.permissiveValue(/^[{;]/);
                      hasBlock = (parserInput.currentChar() === '{');
                      if (!value) {
                          if (!hasBlock && parserInput.currentChar() !== ';') {
                              error(name + ' rule is missing block or ending semi-colon');
                          }
                      }
                      else if (!value.value) {
                          value = null;
                      }
                  }
  
                  if (hasBlock) {
                      rules = this.blockRuleset();
                  }
  
                  if (rules || (!hasBlock && value && parserInput.$char(';'))) {
                      parserInput.forget();
                      return new (tree.AtRule)(name, value, rules, index, fileInfo,
                          context.dumpLineNumbers ? getDebugInfo(index) : null,
                          isRooted
                      );
                  }
  
                  parserInput.restore('at-rule options not recognised');
              }
func_code_string: function () {
                  var index = parserInput.i, name, value, rules, nonVendorSpecificName,
                      hasIdentifier, hasExpression, hasUnknown, hasBlock = true, isRooted = true;
  
                  if (parserInput.currentChar() !== '@') { return; }
  
                  value = this['import']() || this.plugin() || this.media();
                  if (value) {
                      return value;
                  }
  
                  parserInput.save();
  
                  name = parserInput.$re(/^@[a-z-]+/);
  
                  if (!name) { return; }
  
                  nonVendorSpecificName = name;
                  if (name.charAt(1) == '-' && name.indexOf('-', 2) > 0) {
                      nonVendorSpecificName = '@' + name.slice(name.indexOf('-', 2) + 1);
                  }
  
                  switch (nonVendorSpecificName) {
                      case '@charset':
                          hasIdentifier = true;
                          hasBlock = false;
                          break;
                      case '@namespace':
                          hasExpression = true;
                          hasBlock = false;
                          break;
                      case '@keyframes':
                      case '@counter-style':
                          hasIdentifier = true;
                          break;
                      case '@document':
                      case '@supports':
                          hasUnknown = true;
                          isRooted = false;
                          break;
                      default:
                          hasUnknown = true;
                          break;
                  }
  
                  parserInput.commentStore.length = 0;
  
                  if (hasIdentifier) {
                      value = this.entity();
                      if (!value) {
                          error('expected ' + name + ' identifier');
                      }
                  } else if (hasExpression) {
                      value = this.expression();
                      if (!value) {
                          error('expected ' + name + ' expression');
                      }
                  } else if (hasUnknown) {
                      value = this.permissiveValue(/^[{;]/);
                      hasBlock = (parserInput.currentChar() === '{');
                      if (!value) {
                          if (!hasBlock && parserInput.currentChar() !== ';') {
                              error(name + ' rule is missing block or ending semi-colon');
                          }
                      }
                      else if (!value.value) {
                          value = null;
                      }
                  }
  
                  if (hasBlock) {
                      rules = this.blockRuleset();
                  }
  
                  if (rules || (!hasBlock && value && parserInput.$char(';'))) {
                      parserInput.forget();
                      return new (tree.AtRule)(name, value, rules, index, fileInfo,
                          context.dumpLineNumbers ? getDebugInfo(index) : null,
                          isRooted
                      );
                  }
  
                  parserInput.restore('at-rule options not recognised');
              }
func_documentation_string: A CSS AtRule  @charset "utf-8";