[
  {
    "path": ".codeintel/config",
    "content": "{\n\t\"Python\": {\n\t\t\"pythonExtraPaths\": [\n\t\t\t\"libs\",\n\t\t\t\"~/Applications/Sublime Text 2.app/Contents/MacOS\",\n\t\t\t\"/Applications/Sublime Text 2.app/Contents/MacOS\"\n\t\t]\n\t}\n}\n"
  },
  {
    "path": ".gitignore",
    "content": ".git\n.hg\n.svn\n\n*.pyc\n*.pyo\n\n.DS_Store\n"
  },
  {
    "path": "Default (Linux).sublime-keymap",
    "content": "[\n    { \"keys\": [\"ctrl+alt+l\"], \"command\": \"sublimelinter\", \"args\": {\"action\": \"lint\"} },\n    { \"keys\": [\"ctrl+alt+e\"], \"command\": \"find_next_lint_error\" },\n    { \"keys\": [\"ctrl+alt+shift+e\"], \"command\": \"find_previous_lint_error\" }\n]\n"
  },
  {
    "path": "Default (OSX).sublime-keymap",
    "content": "[\n    { \"keys\": [\"ctrl+super+l\"], \"command\": \"sublimelinter\", \"args\": {\"action\": \"lint\"} },\n    { \"keys\": [\"ctrl+super+e\"], \"command\": \"find_next_lint_error\" },\n    { \"keys\": [\"ctrl+super+shift+e\"], \"command\": \"find_previous_lint_error\" }\n]\n"
  },
  {
    "path": "Default (Windows).sublime-keymap",
    "content": "[\n    { \"keys\": [\"ctrl+alt+l\"], \"command\": \"sublimelinter\", \"args\": {\"action\": \"lint\"} },\n    { \"keys\": [\"ctrl+alt+e\"], \"command\": \"find_next_lint_error\" },\n    { \"keys\": [\"ctrl+alt+shift+e\"], \"command\": \"find_previous_lint_error\" }\n]\n"
  },
  {
    "path": "Default.sublime-commands",
    "content": "[\n    {\n        \"caption\": \"SublimeLinter: Lint Current File\",\n        \"command\": \"sublimelinter_lint\",\n        \"args\": {\"action\": \"lint\"}\n    },\n    {\n        \"caption\": \"SublimeLinter: Show Error List\",\n        \"command\": \"sublimelinter_show_errors\",\n        \"args\": {\"action\": \"lint\", \"show_popup\": true}\n    },\n    {\n        \"caption\": \"SublimeLinter: Background Linting\",\n        \"command\": \"sublimelinter_lint\",\n        \"args\": {\"action\": \"on\"}\n    },\n    {\n        \"caption\": \"SublimeLinter: Load-Save Linting\",\n        \"command\": \"sublimelinter_enable_load_save\",\n        \"args\": {\"action\": \"load-save\"}\n    },\n    {\n        \"caption\": \"SublimeLinter: Save-Only Linting\",\n        \"command\": \"sublimelinter_enable_save_only\",\n        \"args\": {\"action\": \"save-only\"}\n    },\n    {\n        \"caption\": \"SublimeLinter: Disable Linting\",\n        \"command\": \"sublimelinter_disable\",\n        \"args\": {\"action\": \"off\"}\n    },\n    {\n        \"caption\": \"SublimeLinter: Extract Annotations\",\n        \"command\": \"sublimelinter_annotations\",\n        \"args\": {}\n    },\n    {\n        \"caption\": \"SublimeLinter: Reset\",\n        \"command\": \"sublimelinter_lint\",\n        \"args\": {\"action\": \"reset\"}\n    },\n    {\n        \"caption\": \"Preferences: SublimeLinter Settings – Default\",\n        \"command\": \"open_file\", \"args\":\n        {\n            \"file\": \"${packages}/SublimeLinter/SublimeLinter.sublime-settings\"\n        }\n    },\n    {\n        \"caption\": \"Preferences: SublimeLinter Settings – User\",\n        \"command\": \"open_file\", \"args\":\n        {\n            \"file\": \"${packages}/User/SublimeLinter.sublime-settings\"\n        }\n    }\n]\n"
  },
  {
    "path": "LICENSE",
    "content": "Copyright Germán M. Bravo, Aparajita Fishman, Jacob Swartwood, and other\ncontributors.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "Main.sublime-menu",
    "content": "[\n    {\n        \"caption\": \"Preferences\",\n        \"mnemonic\": \"n\",\n        \"id\": \"preferences\",\n        \"children\":\n        [\n            {\n                \"caption\": \"Package Settings\",\n                \"mnemonic\": \"P\",\n                \"id\": \"package-settings\",\n                \"children\":\n                [\n                    {\n                        \"caption\": \"SublimeLinter\",\n                        \"children\":\n                        [\n                            {\n                                \"command\": \"open_file\",\n                                \"args\": {\"file\": \"${packages}/SublimeLinter/README.md\"},\n                                \"caption\": \"README\"\n                            },\n                            {\n                                \"command\": \"open_file\",\n                                \"args\": {\"file\": \"${packages}/SublimeLinter/changelog.txt\"},\n                                \"caption\": \"Change Log\"\n                            },\n                            { \"caption\": \"-\" },\n                            {\n                                \"command\": \"open_file\",\n                                \"args\": {\"file\": \"${packages}/SublimeLinter/SublimeLinter.sublime-settings\"},\n                                \"caption\": \"Settings – Default\"\n                            },\n                            {\n                                \"command\": \"open_file\",\n                                \"args\": {\"file\": \"${packages}/User/SublimeLinter.sublime-settings\"},\n                                \"caption\": \"Settings – User\"\n                            },\n                            {\n                                \"command\": \"open_file_settings\",\n                                \"caption\": \"Settings – Syntax Specific – User\"\n                            },\n                            { \"caption\": \"-\" },\n                            {\n                                \"command\": \"open_file\",\n                                \"args\": {\n                                    \"file\": \"${packages}/SublimeLinter/Default (OSX).sublime-keymap\",\n                                    \"platform\": \"OSX\"\n                                },\n                                \"caption\": \"Key Bindings – Default\"\n                            },\n                            {\n                                \"command\": \"open_file\",\n                                \"args\": {\n                                    \"file\": \"${packages}/SublimeLinter/Default (Linux).sublime-keymap\",\n                                    \"platform\": \"Linux\"\n                                },\n                                \"caption\": \"Key Bindings – Default\"\n                            },\n                            {\n                                \"command\": \"open_file\",\n                                \"args\": {\n                                    \"file\": \"${packages}/SublimeLinter/Default (Windows).sublime-keymap\",\n                                    \"platform\": \"Windows\"\n                                },\n                                \"caption\": \"Key Bindings – Default\"\n                            },\n                            {\n                                \"command\": \"open_file\",\n                                \"args\": {\n                                    \"file\": \"${packages}/User/Default (OSX).sublime-keymap\",\n                                    \"platform\": \"OSX\"\n                                },\n                                \"caption\": \"Key Bindings – User\"\n                            },\n                            {\n                                \"command\": \"open_file\",\n                                \"args\": {\n                                    \"file\": \"${packages}/User/Default (Linux).sublime-keymap\",\n                                    \"platform\": \"Linux\"\n                                },\n                                \"caption\": \"Key Bindings – User\"\n                            },\n                            {\n                                \"command\": \"open_file\",\n                                \"args\": {\n                                    \"file\": \"${packages}/User/Default (Windows).sublime-keymap\",\n                                    \"platform\": \"Windows\"\n                                },\n                                \"caption\": \"Key Bindings – User\"\n                            },\n                            { \"caption\": \"-\" }\n                        ]\n                    }\n                ]\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "README.md",
    "content": "SublimeLinter\n=============\n\n## SublimeLinter 3 has landed!\n\nSublimeLinter for Sublime Text 3 is [here](https://github.com/SublimeLinter/SublimeLinter3), and it’s soooooo much better than before! Install it from Package Control and enjoy!\n\nUnless someone else comes forward, SublimeLinter for Sublime Text 2 will no longer be supported. I strongly encourage everyone to upgrade to Sublime Text 3 and SublimeLinter 3 — you’ll be glad you did! Take a look at the [extensive documentation](http://sublimelinter.readthedocs.org/) to see the great new features in SublimeLinter 3.\n\n## Share the love!\n\nI spent hundreds of hours writing and documenting SublimeLinter 3 to make it the best it can be — easy to use, easy to configure, easy to update, easy to extend. If you use SublimeLinter and feel it is making your coding life better and easier, please consider making a donation to help fund development and support. Thank you!\n\nTo donate: https://github.com/SublimeLinter/SublimeLinter3#share-the-love\n\nThank you for your support!\n\n---\n\nSublimeLinter v1.7 Overview\n---------\n\nSublimeLinter is a plugin that supports \"lint\" programs (known as \"linters\"). SublimeLinter highlights\nlines of code the linter deems to contain (potential) errors. It also\nsupports highlighting special annotations (for example: TODO) so that they\ncan be quickly located.\n\nSublimeLinter has built in linters for the following languages:\n\n* C/C++ - lint via `cppcheck`\n* CoffeeScript - lint via `coffee -s -l`\n* CSS - lint via built-in [csslint](http://csslint.net)\n* Git Commit Messages - lint via built-in module based on [A Note About Git Commit Messages](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).\n* Haml - syntax check via `haml -c`\n* HTML - lint via `tidy` (actually [tidy for HTML5](http://w3c.github.com/tidy-html5/))\n* Java - lint via `javac -Xlint`\n* JavaScript - lint via built in [jshint](http://jshint.org), [jslint](http://jslint.com), or the [closure linter (gjslint)](https://developers.google.com/closure/utilities/docs/linter_howto) (if installed)\n* Lua - syntax check via `luac`\n* Objective-J - lint via built-in [capp_lint](https://github.com/aparajita/capp_lint)\n* Perl - lint via [Perl::Critic](http://perlcritic.com/) or syntax+deprecation check via `perl -c`\n* PHP - syntax check via `php -l`\n* Puppet - syntax check via `puppet parser validate` or `puppet-lint`\n* Python - native, moderately-complete lint\n* Ruby - syntax check via `ruby -wc`\n* Squirrel - syntax check via `sq`\n* XML - lint via `xmllint`\n\nQuickstart\n------------\n\n* Install using [Package Control ST2 plugin](http://wbond.net/sublime_packages/package_control/installation).\n* `SublimeLinter` runs in the background (by default), linting files for style and potential errors.\n* Season to taste (edit configuration) by editing `Preferences->Package Settings->SublimeLinter->Settings - User`.\n* Produce better code!\n\n\nInstalling\n----------\n**With the Package Control plugin:** The easiest way to install SublimeLinter is through Package Control, which can be found at this site: http://wbond.net/sublime_packages/package_control\n\nOnce you install Package Control, restart ST2 and bring up the Command Palette (`Command+Shift+P` on OS X, `Control+Shift+P` on Linux/Windows). Select \"Package Control: Install Package\", wait while Package Control fetches the latest package list, then select SublimeLinter when the list appears. The advantage of using this method is that Package Control will automatically keep SublimeLinter up to date with the latest version.\n\n**Without Git:** Download the latest source from [GitHub](https://github.com/SublimeLinter/SublimeLinter) and copy the SublimeLinter folder to your Sublime Text \"Packages\" directory.\n\n**With Git:** Clone the repository in your Sublime Text \"Packages\" directory:\n\n    git clone https://github.com/SublimeLinter/SublimeLinter.git\n\n\nThe \"Packages\" directory is located at:\n\n* OS X:\n\n        ~/Library/Application Support/Sublime Text 2/Packages/\n\n* Linux:\n\n        ~/.config/sublime-text-2/Packages/\n\n* Windows:\n\n        %APPDATA%/Sublime Text 2/Packages/\n\n### JavaScript-based linters\nIf you plan to edit files that use a JavaScript-based linter (JavaScript, CSS), your system\nmust have a JavaScript engine installed. Mac OS X comes with a preinstalled JavaScript engine called\nJavaScriptCore, which is used if Node.js is not installed. On Windows, you **must** install the\nJavaScript engine Node.js, which can be downloaded from [the Node.js site](http://nodejs.org/#download).\n\nOn Mac OS X, you **must** install Node.js if you plan to edit JavaScript or CSS files that\nuse non-ASCII characters in strings or comments, because JavaScriptCore is not Unicode-aware.\n\nAfter installing Node.js, if the Node.js executable (\"node\" on Mac OS X, \"node.exe\" on Windows)\ncannot be found by SublimeLinter, you may have to set the path to the executable in the\n\"sublimelinter\\_executable\\_map\" setting. See the \"Configuring\" section below for info on\nSublimeLinter settings.\n\n\nUsing\n-----\nSublimeLinter runs in one of three modes, which is determined by the \"sublimelinter\" user setting:\n\n* **Background mode (the default)** - When the \"sublimelinter\" setting is true, linting is performed in the background as you modify a file (if the relevant linter supports it). If you like instant feedback, this is the best way to use SublimeLinter. If you want feedback, but not instantly, you can try another mode or set a minimum queue delay with the \"sublimelinter_delay\" setting, so that the linter will only run after a certain amount of idle time.\n* **Load-save mode** - When the \"sublimelinter\" setting is \"load-save\", linting is performed only when a file is loaded and after saving. Errors are cleared as soon as the file is modified.\n* **Save-only mode** - When the \"sublimelinter\" setting is \"save-only\", linting is performed only after a file is saved. Errors are cleared as soon as the file is modified.\n* **On demand mode** - When the \"sublimelinter\" setting is false, linting is performed only when initiated by you. Use the `Control+Command+L` (OS X) or `Control+Alt+L` (Linux/Windows) key equivalent or the Command Palette to lint the current file. If the current file has no associated linter, the command will not be available.\n\nWithin a file whose language/syntax is supported by SublimeLinter, you can control SublimeLinter via the Command Palette (`Command+Shift+P` on OS X, `Control+Shift+P` on Linux/Windows). The available commands are:\n\n* **SublimeLinter: Lint Current File** - Lints the current file, highlights any errors and displays how many errors were found.\n* **SublimeLinter: Show Error List** - Lints the current file, highlights any errors and displays a quick panel with any errors that are found. Selecting an item from the quick panel jumps to that line.\n* **SublimeLinter: Background Linting** - Enables background linting mode for the current view and lints it.\n* **SublimeLinter: Disable Linting** - Disables linting mode for the current view and clears all lint errors.\n* **SublimeLinter: Load-Save Linting** - Enables load-save linting mode for the current view and clears all lint errors.\n* **SublimeLinter: Save-Only Linting** - Enables save-only linting mode for the current view and clears all lint errors.\n* **SublimeLinter: Reset** - Clears all lint errors and sets the linting mode to the value in the SublimeLinter.sublime-settings file.\n\nDepending on the file and the current state of background enabling, some of the commands will not be available.\n\nWhen an error is highlighted by the linter, putting the cursor on the offending line will result in the error message being displayed on the status bar.\n\nIf you want to be shown a popup list of all errors whenever a file is saved, modify the user setting:\n\n    \"sublimelinter_popup_errors_on_save\": true\n\nIf there are errors in the file, a quick panel will appear which shows the error message, line number and source code for each error. The starting location of all errors on the line are marked with \"^\". Selecting an error in the quick panel jumps directly to the location of the first error on that line.\n\nWhile editing a file, you can quickly move to the next/previous lint error with the following key equivalents:\n\n* **OS X**:\n\n        next: Control+Command+E\n        prev: Control+Command+Shift+E\n\n* **Linux, Windows**:\n\n        next: Control+Alt+E\n        prev: Control+Alt+Shift+E\n\nBy default the search will wrap. You can turn wrapping off with the user setting:\n\n    \"sublimelinter_wrap_find\": false\n\nPlease note: these key commands may conflict with other important cmds (such as generating the € character - this was discussed in issue [#182](https://github.com/SublimeLinter/SublimeLinter/issues/182)). If these controls are problematic, you may always adjust your settings by copying the defaults stored in `Preferences->Package Settings->SublimeLinter->Key Bindings - Default` into `Preferences->Key Bindings - User` and then modifying the values appropriately.\n\nConfiguring\n-----------\nThere are a number of settings available to customize the behavior of SublimeLinter and its linters. For the latest information on what settings are available, select the menu item `Preferences->Package Settings->SublimeLinter->Settings - Default`.\n\nDo **NOT** edit the default SublimeLinter settings. Your changes will be lost when SublimeLinter is updated. ALWAYS edit the user SublimeLinter settings by selecting `Preferences->Package Settings->SublimeLinter->Settings - User`. Note that individual settings you include in your user settings will _completely_ replace the corresponding default setting, so you must provide that setting in its entirety.\n\n### Linter-specific notes\nFollowing are notes specific to individual linters that you should be aware of:\n\n* **C/C++** - The default C/C++ linter is [cppcheck](http://cppcheck.sourceforge.net/), however Google's [cpplint.py](http://google-styleguide.googlecode.com/svn/trunk/cpplint/) is also supported.\n\n  To swap `cppcheck` out for `cpplint.py` you will need to adjust `sublimelinter_syntax_map` and possibly `sublimelinter_executable_map` also. First change the _linter language_ for `C` and `C++` to `c_cpplint` via `sublimelinter_syntax_map`. If `cpplint.py` is not on your system `PATH`, then add an entry for `c_cpplint` into `sublimelinter_executable_map` with the path to the file. As usual add these adjustments to the SublimeLinter **User Settings** file. An example:\n\n      \"sublimelinter_syntax_map\":\n      {\n        \"Python Django\": \"python\",\n        \"Ruby on Rails\": \"ruby\",\n        \"C++\": \"c_cpplint\",\n        \"C\": \"c_cpplint\"\n      },\n      \"sublimelinter_executable_map\":\n      {\n        \"c_cpplint\": \"/Users/[my username]/Desktop/cpplint.py\"\n      }\n\n* **CSS** - This linter runs [csslint](http://csslint.net). This linter requires a JavaScript engine (like Node.js) to be installed (see notes above for the JavaScript linters: \"jshint\" or \"jslint\").\n\n  By default all CSSLint settings are turned on. You may customize CSSLint behavior with the \"csslint_options\" setting. Please select `Preferences->Package Settings->SublimeLinter->Settings - Default` for more information on turning off or adjusting severity of tests. For more information about options available to CSSLint, see https://github.com/stubbornella/csslint/wiki/Rules.\n\n* **HTML** - This linter will not run unless you have a version of tidy with HTML5 support. To use this linter, please see: https://github.com/w3c/tidy-html5\n\n* **Java** - Because it uses `javac` to do linting, each time you run the linter the entire dependency graph of the current file will be checked. Depending on the number of classes you import, this can be **extremely** slow. Also note that you **must** provide the `-sourcepath`, `-classpath`, `-Xlint` and `{filename}` arguments to `javac` in your per-project settings. See \"Per-project settings\" below for more information.\n\n* **JavaScript** - If the \"javascript_linter\" setting is \"jshint\" or \"jslint\", this linter runs [jshint](http://jshint.org) (or [jslint](http://jslint.com) respectively) using Node.js. See \"JavaScript-based linters\" above for information on how to install Node.js.\n\n  If the \"javascript_linter\" setting is \"gjslint\", this linter runs the [closure linter (gjslint)](https://developers.google.com/closure/utilities/docs/linter_howto). After installation, if gjslint cannot be found by SublimeLinter, you may have to set the path to gjslint in the \"sublimelinter\\_executable\\_map\" setting.\n\n  You may want to modify the options passed to jshint, jslint, or gjslint. This can be done by using the **jshint_options**, **jslint_options**, or **gjslint_options** setting. Refer to the jshint.org site, the jslint.com site, or run `gjslint --help` for more information on the configuration options available.\n\n  SublimeLinter supports `.jshintrc` files. If using JSHint, SublimeLinter will recursively search the directory tree (from the file location to the file-system root directory). This functionality is specified in the [JSHint README](https://github.com/jshint/node-jshint/#within-your-projects-directory-tree).\n\n* **Perl** - Due to a vulnerability (issue [#77](https://github.com/SublimeLinter/SublimeLinter/issues/77)) with the Perl linter, Perl syntax checking is no longer enabled by default. The default linter for Perl has been replaced by Perl::Critic. The standard Perl syntax checker can still be invoked by switching the \"perl_linter\" setting to \"perl\".\n\n* **Puppet** - Optional alternative linter using puppet-lint. Install with `gem install puppet-lint`. Add these adjustments to the SublimeLinter **User Settings** file. An example:\n\"sublimelinter_syntax_map\": { \"Puppet\": \"puppet-lint\" }. Note this only lints on file save.\n\n* **Ruby** - If you are using rvm or rbenv, you will probably have to specify the full path to the ruby you are using in the \"sublimelinter_executable_map\" setting. See \"Configuring\" below for more info.\n\n### Per-project settings\nSublimeLinter supports per-project/per-language settings. This is useful if a linter requires path configuration on a per-project basis. To edit your project settings, select the menu item `Project->Edit Project`. If there is no \"settings\" object at the top level, add one and then add a \"SublimeLinter\" sub-object, like this:\n\n    {\n        \"folders\":\n        [\n            {\n                \"path\": \"/Users/aparajita/Projects/foo/src\"\n            }\n        ],\n        \"settings\":\n        {\n            \"SublimeLinter\":\n            {\n            }\n        }\n    }\n\nWithin the \"SublimeLinter\" object, you can add a settings object for each language. The language name must match the language item in the linter's CONFIG object, which can be found in the linter's source file in the SublimeLinter/sublimelinter/modules folder. Each language can have two settings:\n\n* \"working_directory\" - If present and a valid absolute directory path, the working directory is set to this path before the linter executes. This is useful if you are providing linter arguments that contain paths and you want to use working directory-relative paths instead of absolute paths.\n* \"lint_args\" - If present, it must be a sequence of string arguments to pass to the linter. If your linter expects a filename as an argument, use the argument \"{filename}\" as a placeholder. If it expects stdin, use \"-\". Note that if you provide this item, you are responsible for passing **all** required arguments to the linter, as it will override default arguments.\n\nFor example, let's say we are editing a Java project and want to use the \"java\" linter, which requires a source path and class path. In addition, we want to ignore serialization errors. Our project settings might look like this:\n\n    {\n        \"folders\":\n        [\n            {\n                \"path\": \"/Users/aparajita/Projects/foo/src\"\n            }\n        ],\n        \"settings\":\n        {\n            \"SublimeLinter\":\n            {\n                \"Java\":\n                {\n                    \"working_directory\": \"/Users/aparajita/Projects/foo\",\n\n                    \"lint_args\":\n                    [\n                        \"-sourcepath\", \"src\",\n                        \"-classpath\", \"libs/log4j-1.2.9.jar:libs/commons-logging-1.1.jar\",\n                        \"-Xlint\", \"-Xlint:-serial\",\n                        \"{filename}\"\n                    ]\n                }\n            }\n        }\n    }\n\nThe jshint follows convention set by node-jshint (though node is not required) and will attempt to locate the configuration file for you starting in pwd. (or \"present working directory\") If this does not yield a .jshintrc file, it will move one level up (..) the directory tree all the way up to the filesystem root. If a file is found, it stops immediately and uses that set of configuration instead of \"jshint_options\".\n\n### Customizing colors\n**IMPORTANT** - The theme style names have recently changed. The old and new color\nnames are:\n\n    Old                     New\n    ---------------------   -----------------------------\n    sublimelinter.<type>    sublimelinter.outline.<type>\n    invalid.<type>          sublimelinter.underline.<type>\n\nPlease change the names in your color themes accordingly.\n\nThere are three types of \"errors\" flagged by SublimeLinter: illegal,\nviolation, and warning. For each type, SublimeLinter will indicate the offending\nline and the character position at which the error occurred on the line.\n\nBy default SublimeLinter will outline offending lines using the background color\nof the \"sublimelinter.outline.<type>\" theme style, and underline the character position\nusing the background color of the \"sublimelinter.underline.<type>\" theme style, where <type>\nis one of the three error types.\n\nIf these styles are not defined, the color will be black when there is a light\nbackground color and black when there is a dark background color. You may\ndefine a single \"sublimelinter.outline\" or \"sublimelinter.underline\" style to color all three types,\nor define separate substyles for one or more types to color them differently.\n\nIf you want to make the offending lines glaringly obvious (perhaps for those\nwho tend to ignore lint errors), you can set the user setting:\n\n    \"sublimelinter_mark_style\": \"fill\"\n\nWhen this is set true, lines that have errors will be colored with the background\nand foreground color of the \"sublime.outline.<type>\" theme style. Unless you have defined\nthose styles, this setting should be left as \"outline\".\n\nYou may want to disable drawing of outline boxes entirely. If so, change\nusing the user setting to:\n\n    \"sublimelinter_mark_style\": \"none\"\n\nYou may also mark lines with errors by putting an \"x\" in the gutter with the user setting:\n\n    \"sublimelinter_gutter_marks\": true\n\nTo customize the colors used for highlighting errors and user notes, add the following\nto your theme (adapting the color to your liking):\n\n    <dict>\n        <key>name</key>\n        <string>SublimeLinter Annotations</string>\n        <key>scope</key>\n        <string>sublimelinter.annotations</string>\n        <key>settings</key>\n        <dict>\n            <key>background</key>\n            <string>#FFFFAA</string>\n            <key>foreground</key>\n            <string>#FFFFFF</string>\n        </dict>\n    </dict>\n    <dict>\n        <key>name</key>\n        <string>SublimeLinter Error Outline</string>\n        <key>scope</key>\n        <string>sublimelinter.outline.illegal</string>\n        <key>settings</key>\n        <dict>\n            <key>background</key>\n            <string>#FF4A52</string>\n            <key>foreground</key>\n            <string>#FFFFFF</string>\n        </dict>\n    </dict>\n    <dict>\n        <key>name</key>\n        <string>SublimeLinter Error Underline</string>\n        <key>scope</key>\n        <string>sublimelinter.underline.illegal</string>\n        <key>settings</key>\n        <dict>\n            <key>background</key>\n            <string>#FF0000</string>\n        </dict>\n    </dict>\n    <dict>\n        <key>name</key>\n        <string>SublimeLinter Warning Outline</string>\n        <key>scope</key>\n        <string>sublimelinter.outline.warning</string>\n        <key>settings</key>\n        <dict>\n            <key>background</key>\n            <string>#DF9400</string>\n            <key>foreground</key>\n            <string>#FFFFFF</string>\n        </dict>\n    </dict>\n    <dict>\n        <key>name</key>\n        <string>SublimeLinter Warning Underline</string>\n        <key>scope</key>\n        <string>sublimelinter.underline.warning</string>\n        <key>settings</key>\n        <dict>\n            <key>background</key>\n            <string>#FF0000</string>\n        </dict>\n    </dict>\n    <dict>\n        <key>name</key>\n        <string>SublimeLinter Violation Outline</string>\n        <key>scope</key>\n        <string>sublimelinter.outline.violation</string>\n        <key>settings</key>\n        <dict>\n            <key>background</key>\n            <string>#ffffff33</string>\n            <key>foreground</key>\n            <string>#FFFFFF</string>\n        </dict>\n    </dict>\n    <dict>\n        <key>name</key>\n        <string>SublimeLinter Violation Underline</string>\n        <key>scope</key>\n        <string>sublimelinter.underline.violation</string>\n        <key>settings</key>\n        <dict>\n            <key>background</key>\n            <string>#FF0000</string>\n        </dict>\n    </dict>\n\nTroubleshooting\n---------------\nIf a linter does not seem to be working, you can check the ST2 console to see if it was enabled. When SublimeLinter is loaded, you will see messages in the console like this:\n\n    Reloading plugin /Users/aparajita/Library/Application Support/Sublime Text 2/Packages/SublimeLinter/sublimelinter_plugin.py\n    SublimeLinter: JavaScript loaded\n    SublimeLinter: annotations loaded\n    SublimeLinter: Objective-J loaded\n    SublimeLinter: perl loaded\n    SublimeLinter: php loaded\n    SublimeLinter: python loaded\n    SublimeLinter: ruby loaded\n    SublimeLinter: pylint loaded\n\nThe first time a linter is asked to lint, it will check to see if it can be enabled. You will then see messages like this:\n\n    SublimeLinter: JavaScript enabled (using JavaScriptCore)\n    SublimeLinter: Ruby enabled (using \"ruby\" for executable)\n\nLet's say the ruby linter is not working. If you look at the console, you may see a message like this:\n\n    SublimeLinter: ruby disabled (\"ruby\" cannot be found)\n\nThis means that the ruby executable cannot be found on your system, which means it is not installed or not in your executable path.\n\nCreating New Linters\n--------------------\nIf you wish to create a new linter to support a new language, SublimeLinter makes it easy. Here are the steps involved:\n\n* Create a new file in sublimelinter/modules. If your linter uses an external executable, you will probably want to copy perl.py. If your linter uses built in code, copy objective-j.py. The convention is to name the file the same as the language that will be linted.\n\n* Configure the CONFIG dict in your module. See the comments in base\\_linter.py for information on the values in that dict. You only need to set the values in your module that differ from the defaults in base\\_linter.py, as your module's CONFIG is merged with the default. Note that if your linter uses an external executable that does not take stdin, setting 'input\\_method' to INPUT\\_METHOD\\_TEMP\\_FILE will allow interactive linting with that executable.\n\n* If your linter uses built in code, override `built_in_check()` and return the errors found.\n\n* Override `parse_errors()` and process the errors. If your linter overrides `built_in_check()`, `parse_errors()` will receive the result of that method. If your linter uses an external executable, `parse_errors()` receives the raw output of the executable, stripped of leading and trailing whitespace.\n\n* If you linter is powered via JavaScript (eg. Node.js), there are few steps that will simplify the integration.\n\n  Create a folder matching your linter name in the `SublimeLinter/sublimelinter/modules/lib` directory. This folder should include the linting library JS file (eg. jshint.js, csslint-Node.js) and a **linter.js** file. The **linter.js** file should `require()` the actual linter library file and export a `lint()` function. The `lint()` function should return a list of errors back to the python language handler file (via the `errors` parameter to the `parse_errors()` method).\n\n  Although **linter.js** should follow the Node.js api, the linter may also be run via JavaScriptCore on OS X if Node.js is not installed. In the case where JavaScriptCore is used, require + export are shimmed to keep things consistent. However, it is important not to assume that a full Node.js api is available. If you must know what JS engine you are using, you may check for `USING_JSC` to be set as `true` when JavaScriptCore is used.\n\n  For examples of using the JS engines, see **csslint**, **jslint**, and **jshint** in `SublimeLinter/sublimelinter/modules/libs` and the respective python code of **css.py** and **javascript.py** in `SublimeLinter/sublimelinter/modules`.\n\n\nIf your linter has more complex requirements, see the comments for CONFIG in base\\_linter.py, and use the existing linters as guides.\n\nBeta\n----\nThe SublimeLinter Beta package is available via Package Control. The beta version is considered unstable and should only be used for testing the next release. If you like living on the edge, please report any bugs you find on the [SublimeLinter issues](https://github.com/SublimeLinter/SublimeLinter/issues) page.\n"
  },
  {
    "path": "SublimeLinter.py",
    "content": "from functools import partial\nimport os\nimport re\nimport sys\nimport time\nimport threading\n\nimport sublime\nimport sublime_plugin\n\nfrom sublimelinter.loader import Loader\nfrom sublimelinter.modules.base_linter import INPUT_METHOD_FILE\n\nLINTERS = {}     # mapping of language name to linter module\nQUEUE = {}       # views waiting to be processed by linter\nERRORS = {}      # error messages on given line obtained from linter; they are\n                 # displayed in the status bar when cursor is on line with error\nVIOLATIONS = {}  # violation messages, they are displayed in the status bar\nWARNINGS = {}    # warning messages, they are displayed in the status bar\nUNDERLINES = {}  # underline regions related to each lint message\nTIMES = {}       # collects how long it took the linting to complete\nMOD_LOAD = Loader(os.getcwdu(), LINTERS)  # utility to load (and reload\n                 # if necessary) linter modules [useful when working on plugin]\n\n\n# For snappier linting, different delays are used for different linting times:\n# (linting time, delays)\nDELAYS = (\n    (50, (50, 100)),\n    (100, (100, 300)),\n    (200, (200, 500)),\n    (400, (400, 1000)),\n    (800, (800, 2000)),\n    (1600, (1600, 3000)),\n)\n\n# Select one of the predefined gutter mark themes, the options are:\n# \"alpha\", \"bright\", \"dark\", \"hard\" and \"simple\"\nMARK_THEMES = ('alpha', 'bright', 'dark', 'hard', 'simple')\n# The path to the built-in gutter mark themes\nMARK_THEMES_PATH = os.path.join('..', 'SublimeLinter', 'gutter_mark_themes')\n# The original theme for anyone interested the previous minimalist approach\nORIGINAL_MARK_THEME = {\n    'violation': 'dot',\n    'warning': 'dot',\n    'illegal': 'circle'\n}\n\n# All available settings for SublimeLinter;\n# only these are inherited from SublimeLinter.sublime-settings\nALL_SETTINGS = [\n    'annotations',\n    'csslint_options',\n    'gjslint_ignore',\n    'gjslint_options',\n    'javascript_linter',\n    'jshint_options',\n    'jslint_options',\n    'pep8',\n    'pep8_ignore',\n    'perl_linter',\n    'pyflakes_ignore',\n    'pyflakes_ignore_import_*',\n    'sublimelinter',\n    'sublimelinter_delay',\n    'sublimelinter_disable',\n    'sublimelinter_executable_map',\n    'sublimelinter_fill_outlines',\n    'sublimelinter_gutter_marks',\n    'sublimelinter_gutter_marks_theme',\n    'sublimelinter_mark_style',\n    'sublimelinter_notes',\n    'sublimelinter_objj_check_ascii',\n    'sublimelinter_popup_errors_on_save',\n    'sublimelinter_syntax_map',\n    'sublimelinter_wrap_find',\n]\n\n\nWHITESPACE_RE = re.compile(r'\\s+')\n\n\ndef get_delay(t, view):\n    delay = 0\n\n    for _t, d in DELAYS:\n        if _t <= t:\n            delay = d\n        else:\n            break\n\n    delay = delay or DELAYS[0][1]\n\n    # If the user specifies a delay greater than the built in delay,\n    # figure they only want to see marks when idle.\n    minDelay = int(view.settings().get('sublimelinter_delay', 0) * 1000)\n\n    if minDelay > delay[1]:\n        erase_lint_marks(view)\n\n    return (minDelay, minDelay) if minDelay > delay[1] else delay\n\n\ndef last_selected_lineno(view):\n    viewSel = view.sel()\n    if not viewSel:\n        return None\n    return view.rowcol(viewSel[0].end())[0]\n\n\ndef update_statusbar(view):\n    vid = view.id()\n    lineno = last_selected_lineno(view)\n    errors = []\n\n    if lineno is not None:\n        if vid in ERRORS and lineno in ERRORS[vid]:\n            errors.extend(ERRORS[vid][lineno])\n\n        if vid in VIOLATIONS and lineno in VIOLATIONS[vid]:\n            errors.extend(VIOLATIONS[vid][lineno])\n\n        if vid in WARNINGS and lineno in WARNINGS[vid]:\n            errors.extend(WARNINGS[vid][lineno])\n\n    if errors:\n        view.set_status('Linter', '; '.join(errors))\n    else:\n        view.erase_status('Linter')\n\n\ndef run_once(linter, view, **kwargs):\n    '''run a linter on a given view regardless of user setting'''\n    if not linter:\n        return\n\n    vid = view.id()\n    ERRORS[vid] = {}\n    VIOLATIONS[vid] = {}\n    WARNINGS[vid] = {}\n    start = time.time()\n    text = view.substr(sublime.Region(0, view.size())).encode('utf-8')\n    lines, error_underlines, violation_underlines, warning_underlines, ERRORS[vid], VIOLATIONS[vid], WARNINGS[vid] = linter.run(view, text, (view.file_name() or '').encode('utf-8'))\n\n    UNDERLINES[vid] = error_underlines[:]\n    UNDERLINES[vid].extend(violation_underlines)\n    UNDERLINES[vid].extend(warning_underlines)\n\n    add_lint_marks(view, lines, error_underlines, violation_underlines, warning_underlines)\n\n    if view.settings().get('sublimelinter_notes'):\n        highlight_notes(view)\n\n    update_statusbar(view)\n    end = time.time()\n    TIMES[vid] = (end - start) * 1000  # Keep how long it took to lint\n\n    if kwargs.get('event', None) == 'on_post_save' and view.settings().get('sublimelinter_popup_errors_on_save'):\n        popup_error_list(view)\n\n\ndef popup_error_list(view):\n    vid = view.id()\n    errors = ERRORS[vid].copy()\n\n    for message_map in [VIOLATIONS[vid], WARNINGS[vid]]:\n        for line, messages in message_map.items():\n            if line in errors:\n                errors[line].extend(messages)\n            else:\n                errors[line] = messages\n\n    # Flatten the errors into a list\n    error_list = []\n\n    for line in sorted(errors.keys()):\n        for index, message in enumerate(errors[line]):\n            error_list.append({'line': line, 'message': message})\n\n    panel_items = []\n\n    for error in error_list:\n        line_text = view.substr(view.full_line(view.text_point(error['line'], 0)))\n        item = [error['message'], u'{0}: {1}'.format(error['line'] + 1, line_text.strip())]\n        panel_items.append(item)\n\n    def on_done(selected_item):\n        if selected_item == -1:\n            return\n\n        selected = view.sel()\n        selected.clear()\n\n        error = error_list[selected_item]\n        region_begin = view.text_point(error['line'], 0)\n\n        # Go to the first non-whitespace character of the line\n        line_text = view.substr(view.full_line(region_begin))\n        match = WHITESPACE_RE.match(line_text)\n\n        if (match):\n            region_begin += len(match.group(0))\n\n        selected.add(sublime.Region(region_begin, region_begin))\n        # We have to force a move to update the cursor position\n        view.run_command('move', {'by': 'characters', 'forward': True})\n        view.run_command('move', {'by': 'characters', 'forward': False})\n        view.show_at_center(region_begin)\n\n    view.window().show_quick_panel(panel_items, on_done)\n\n\ndef add_lint_marks(view, lines, error_underlines, violation_underlines, warning_underlines):\n    '''Adds lint marks to view.'''\n    vid = view.id()\n    erase_lint_marks(view)\n    types = {'warning': warning_underlines, 'violation': violation_underlines, 'illegal': error_underlines}\n\n    for type_name, underlines in types.items():\n        if underlines:\n            view.add_regions('lint-underline-' + type_name, underlines, 'sublimelinter.underline.' + type_name, sublime.DRAW_EMPTY_AS_OVERWRITE)\n\n    if lines:\n        outline_style = view.settings().get('sublimelinter_mark_style', 'outline')\n\n        # This test is for the legacy \"fill\" setting; it will be removed\n        # in a future version (likely v1.7).\n        if view.settings().get('sublimelinter_fill_outlines', False):\n            outline_style = 'fill'\n\n        gutter_mark_enabled = True if view.settings().get('sublimelinter_gutter_marks', False) else False\n\n        gutter_mark_theme = view.settings().get('sublimelinter_gutter_marks_theme', 'simple')\n\n        outlines = {'warning': [], 'violation': [], 'illegal': []}\n\n        for line in ERRORS[vid]:\n            outlines['illegal'].append(view.full_line(view.text_point(line, 0)))\n\n        for line in WARNINGS[vid]:\n            outlines['warning'].append(view.full_line(view.text_point(line, 0)))\n\n        for line in VIOLATIONS[vid]:\n            outlines['violation'].append(view.full_line(view.text_point(line, 0)))\n\n        for lint_type in outlines:\n            if outlines[lint_type]:\n                args = [\n                    'lint-outlines-{0}'.format(lint_type),\n                    outlines[lint_type],\n                    'sublimelinter.outline.{0}'.format(lint_type)\n                ]\n\n                gutter_mark_image = ''\n\n                if gutter_mark_enabled:\n                    if gutter_mark_theme == 'original':\n                        gutter_mark_image = ORIGINAL_MARK_THEME[lint_type]\n                    elif gutter_mark_theme in MARK_THEMES:\n                        gutter_mark_image = os.path.join(MARK_THEMES_PATH, gutter_mark_theme + '-' + lint_type)\n                    else:\n                        gutter_mark_image = gutter_mark_theme + '-' + lint_type\n\n                args.append(gutter_mark_image)\n\n                if outline_style == 'none':\n                    args.append(sublime.HIDDEN)\n                elif outline_style == 'fill':\n                    pass  # outlines are filled by default\n                else:\n                    args.append(sublime.DRAW_OUTLINED)\n                view.add_regions(*args)\n\n\ndef erase_lint_marks(view):\n    '''erase all \"lint\" error marks from view'''\n    view.erase_regions('lint-underline-illegal')\n    view.erase_regions('lint-underline-violation')\n    view.erase_regions('lint-underline-warning')\n    view.erase_regions('lint-outlines-illegal')\n    view.erase_regions('lint-outlines-violation')\n    view.erase_regions('lint-outlines-warning')\n    view.erase_regions('lint-annotations')\n\n\ndef get_lint_regions(view, reverse=False, coalesce=False):\n    vid = view.id()\n    underlines = UNDERLINES.get(vid, [])[:]\n\n    if (coalesce):\n        # Each of these regions is one character, so transform it into the character points\n        points = sorted([region.begin() for region in underlines])\n\n        # Now coalesce adjacent characters into a single region\n        underlines = []\n        last_point = -999\n\n        for point in points:\n            if point != last_point + 1:\n                underlines.append(sublime.Region(point, point))\n            else:\n                region = underlines[-1]\n                underlines[-1] = sublime.Region(region.begin(), point)\n\n            last_point = point\n\n    # Now get all outlines, which includes the entire line where underlines are\n    outlines = view.get_regions('lint-outlines-illegal')\n    outlines.extend(view.get_regions('lint-outlines-violation'))\n    outlines.extend(view.get_regions('lint-outlines-warning'))\n    outlines.extend(view.get_regions('lint-annotations'))\n\n    # If an outline region contains an underline region, use only the underline\n    regions = underlines\n\n    for outline in outlines:\n        contains_underlines = False\n\n        for underline in underlines:\n            if outline.contains(underline):\n                contains_underlines = True\n                break\n\n        if not contains_underlines:\n            regions.append(outline)\n\n    return sorted(regions, key=lambda x: x.begin(), reverse=reverse)\n\n\ndef select_lint_region(view, region):\n    selected = view.sel()\n    selected.clear()\n\n    # Find the first underline region within the region to select.\n    # If there are none, put the cursor at the beginning of the line.\n    underlineRegion = find_underline_within(view, region)\n\n    if underlineRegion is None:\n        underlineRegion = sublime.Region(region.begin(), region.begin())\n\n    selected.add(underlineRegion)\n    view.show(underlineRegion, True)\n\n\ndef find_underline_within(view, region):\n    underlines = view.get_regions('lint-underline-illegal')\n    underlines.extend(view.get_regions('lint-underline-violation'))\n    underlines.extend(view.get_regions('lint-underline-warning'))\n    underlines.sort(key=lambda x: x.begin())\n\n    for underline in underlines:\n        if region.contains(underline):\n            return underline\n\n    return None\n\n\ndef syntax_name(view):\n    syntax = os.path.basename(view.settings().get('syntax'))\n    syntax = os.path.splitext(syntax)[0]\n    return syntax\n\n\ndef select_linter(view, ignore_disabled=False):\n    '''selects the appropriate linter to use based on language in current view'''\n    syntax = syntax_name(view)\n    lc_syntax = syntax.lower()\n    language = None\n    linter = None\n    syntaxMap = view.settings().get('sublimelinter_syntax_map', {})\n\n    if syntax in syntaxMap:\n        language = syntaxMap.get(syntax, '').lower()\n    elif lc_syntax in syntaxMap:\n        language = syntaxMap.get(lc_syntax, '').lower()\n    elif lc_syntax in LINTERS:\n        language = lc_syntax\n\n    if language:\n        if ignore_disabled:\n            disabled = []\n        else:\n            disabled = view.settings().get('sublimelinter_disable', [])\n\n        if language not in disabled:\n            linter = LINTERS.get(language)\n\n            # If the enabled state is False, it must be checked.\n            # Enabled checking has to be deferred to first view use because\n            # user settings cannot be loaded during plugin startup.\n            if linter is not None and not linter.enabled:\n                enabled, message = linter.check_enabled(view)\n                print 'SublimeLinter: {0} {1} ({2})'.format(language, 'enabled' if enabled else 'disabled', message)\n\n                if not enabled:\n                    del LINTERS['' + language]\n                    linter = None\n\n    return linter\n\n\ndef highlight_notes(view):\n    '''highlight user-specified annotations in a file'''\n    view.erase_regions('lint-annotations')\n    text = view.substr(sublime.Region(0, view.size()))\n    regions = LINTERS['annotations'].built_in_check(view, text, '')\n\n    if regions:\n        view.add_regions('lint-annotations', regions, 'sublimelinter.annotations', sublime.DRAW_EMPTY_AS_OVERWRITE)\n\n\ndef _update_view(view, filename, **kwargs):\n    # It is possible that by the time the queue is run,\n    # the original file is no longer being displayed in the view,\n    # or the view may be gone. This happens especially when\n    # viewing files temporarily by single-clicking on a filename\n    # in the sidebar or when selecting a file through the choose file palette.\n    valid_view = False\n    view_id = view.id()\n\n    for window in sublime.windows():\n        for v in window.views():\n            if v.id() == view_id:\n                valid_view = True\n                break\n\n    if not valid_view or view.is_loading() or (view.file_name() or '').encode('utf-8') != filename:\n        return\n\n    try:\n        run_once(select_linter(view), view, **kwargs)\n    except RuntimeError, ex:\n        print ex\n\n\ndef queue_linter(linter, view, timeout=-1, preemptive=False, event=None):\n    '''Put the current view in a queue to be examined by a linter'''\n    if linter is None:\n        erase_lint_marks(view)  # may have changed file type and left marks behind\n\n        # No point in queuing anything if no linters will run\n        if not view.settings().get('sublimelinter_notes'):\n            return\n\n    if preemptive:\n        timeout = busy_timeout = 0\n    elif timeout == -1:\n        timeout, busy_timeout = get_delay(TIMES.get(view.id(), 100), view)\n    else:\n        busy_timeout = timeout\n\n    kwargs = {'timeout': timeout, 'busy_timeout': busy_timeout, 'preemptive': preemptive, 'event': event}\n    queue(view, partial(_update_view, view, (view.file_name() or '').encode('utf-8'), **kwargs), kwargs)\n\n\ndef _callback(view, filename, kwargs):\n    kwargs['callback'](view, filename, **kwargs)\n\n\ndef background_linter():\n    __lock_.acquire()\n\n    try:\n        callbacks = QUEUE.values()\n        QUEUE.clear()\n    finally:\n        __lock_.release()\n\n    for callback in callbacks:\n        sublime.set_timeout(callback, 0)\n\n################################################################################\n# Queue dispatcher system:\n\nqueue_dispatcher = background_linter\nqueue_thread_name = 'background linter'\nMAX_DELAY = 10\n\n\ndef queue_loop():\n    '''An infinite loop running the linter in a background thread meant to\n       update the view after user modifies it and then does no further\n       modifications for some time as to not slow down the UI with linting.'''\n    global __signaled_, __signaled_first_\n\n    while __loop_:\n        #print 'acquire...'\n        __semaphore_.acquire()\n        __signaled_first_ = 0\n        __signaled_ = 0\n        #print 'DISPATCHING!', len(QUEUE)\n        queue_dispatcher()\n\n\ndef queue(view, callback, kwargs):\n    global __signaled_, __signaled_first_\n    now = time.time()\n    __lock_.acquire()\n\n    try:\n        QUEUE[view.id()] = callback\n        timeout = kwargs['timeout']\n        busy_timeout = kwargs['busy_timeout']\n\n        if now < __signaled_ + timeout * 4:\n            timeout = busy_timeout or timeout\n\n        __signaled_ = now\n        _delay_queue(timeout, kwargs['preemptive'])\n\n        if not __signaled_first_:\n            __signaled_first_ = __signaled_\n            #print 'first',\n        #print 'queued in', (__signaled_ - now)\n    finally:\n        __lock_.release()\n\n\ndef _delay_queue(timeout, preemptive):\n    global __signaled_, __queued_\n    now = time.time()\n\n    if not preemptive and now <= __queued_ + 0.01:\n        return  # never delay queues too fast (except preemptively)\n\n    __queued_ = now\n    _timeout = float(timeout) / 1000\n\n    if __signaled_first_:\n        if MAX_DELAY > 0 and now - __signaled_first_ + _timeout > MAX_DELAY:\n            _timeout -= now - __signaled_first_\n            if _timeout < 0:\n                _timeout = 0\n            timeout = int(round(_timeout * 1000, 0))\n\n    new__signaled_ = now + _timeout - 0.01\n\n    if __signaled_ >= now - 0.01 and (preemptive or new__signaled_ >= __signaled_ - 0.01):\n        __signaled_ = new__signaled_\n        #print 'delayed to', (preemptive, __signaled_ - now)\n\n        def _signal():\n            if time.time() < __signaled_:\n                return\n            __semaphore_.release()\n\n        sublime.set_timeout(_signal, timeout)\n\n\ndef delay_queue(timeout):\n    __lock_.acquire()\n    try:\n        _delay_queue(timeout, False)\n    finally:\n        __lock_.release()\n\n\n# only start the thread once - otherwise the plugin will get laggy\n# when saving it often.\n__semaphore_ = threading.Semaphore(0)\n__lock_ = threading.Lock()\n__queued_ = 0\n__signaled_ = 0\n__signaled_first_ = 0\n\n# First finalize old standing threads:\n__loop_ = False\n__pre_initialized_ = False\n\n\ndef queue_finalize(timeout=None):\n    global __pre_initialized_\n\n    for thread in threading.enumerate():\n        if thread.isAlive() and thread.name == queue_thread_name:\n            __pre_initialized_ = True\n            thread.__semaphore_.release()\n            thread.join(timeout)\nqueue_finalize()\n\n# Initialize background thread:\n__loop_ = True\n__active_linter_thread = threading.Thread(target=queue_loop, name=queue_thread_name)\n__active_linter_thread.__semaphore_ = __semaphore_\n__active_linter_thread.start()\n\n################################################################################\n\nUNRECOGNIZED = '''\n* Unrecognized option * :  %s\n==============================================\n\n'''\n\n\ndef view_in_tab(view, title, text, file_type):\n    '''Helper function to display information in a tab.\n    '''\n    tab = view.window().new_file()\n    tab.set_name(title)\n    _id = tab.buffer_id()\n    tab.set_scratch(_id)\n    tab.settings().set('gutter', True)\n    tab.settings().set('line_numbers', False)\n    tab.set_syntax_file(file_type)\n    ed = tab.begin_edit()\n    tab.insert(ed, 0, text)\n    tab.end_edit(ed)\n    return tab, _id\n\n\ndef lint_views(linter):\n    if not linter:\n        return\n\n    viewsToLint = []\n\n    for window in sublime.windows():\n        for view in window.views():\n            viewLinter = select_linter(view)\n\n            if viewLinter == linter:\n                viewsToLint.append(view)\n\n    for view in viewsToLint:\n        queue_linter(linter, view, preemptive=True)\n\n\ndef reload_view_module(view):\n    for name, linter in LINTERS.items():\n        module = sys.modules[linter.__module__]\n\n        if module.__file__.encode('utf-8') == (view.file_name() or '').encode('utf-8'):\n            print 'SublimeLinter: reloading language:', linter.language\n            MOD_LOAD.reload_module(module)\n            lint_views(linter)\n            break\n\n\ndef settings_changed():\n    for window in sublime.windows():\n        for view in window.views():\n            linter = select_linter(view)\n\n            if (linter):\n                reload_settings(view)\n\n\ndef reload_settings(view):\n    '''Restores user settings.'''\n    settings = sublime.load_settings(__name__ + '.sublime-settings')\n    settings.clear_on_change(__name__)\n    settings.add_on_change(__name__, settings_changed)\n\n    for setting in ALL_SETTINGS:\n        if settings.get(setting) != None:\n            view.settings().set(setting, settings.get(setting))\n\n    if view.settings().get('sublimelinter') == None:\n        view.settings().set('sublimelinter', True)\n\n\nclass LintCommand(sublime_plugin.TextCommand):\n    '''command to interact with linters'''\n\n    def __init__(self, view):\n        self.view = view\n        self.help_called = False\n\n    def run_(self, action):\n        '''method called by default via view.run_command;\n           used to dispatch to appropriate method'''\n        if not action:\n            return\n\n        try:\n            lc_action = action.lower()\n        except AttributeError:\n            return\n\n        if lc_action == 'reset':\n            self.reset()\n        elif lc_action == 'on':\n            self.on()\n        elif lc_action == 'load-save':\n            self.enable_load_save()\n        elif lc_action == 'save-only':\n            self.enable_save_only()\n        elif lc_action == 'off':\n            self.off()\n        elif action.lower() in LINTERS:\n            self._run(lc_action)\n\n    def reset(self):\n        '''Removes existing lint marks and restores user settings.'''\n        erase_lint_marks(self.view)\n        reload_settings(self.view)\n\n    def on(self):\n        '''Turns background linting on.'''\n        self.view.settings().set('sublimelinter', True)\n        queue_linter(select_linter(self.view), self.view, preemptive=True)\n\n    def enable_load_save(self):\n        '''Turns load-save linting on.'''\n        self.view.settings().set('sublimelinter', 'load-save')\n        erase_lint_marks(self.view)\n\n    def enable_save_only(self):\n        '''Turns save-only linting on.'''\n        self.view.settings().set('sublimelinter', 'save-only')\n        erase_lint_marks(self.view)\n\n    def off(self):\n        '''Turns background linting off.'''\n        self.view.settings().set('sublimelinter', False)\n        erase_lint_marks(self.view)\n\n    def _run(self, name):\n        '''runs an existing linter'''\n        run_once(LINTERS[name.lower()], self.view)\n\n\nclass BackgroundLinter(sublime_plugin.EventListener):\n    '''This plugin controls a linter meant to work in the background\n    to provide interactive feedback as a file is edited. It can be\n    turned off via a setting.\n    '''\n\n    def __init__(self):\n        super(BackgroundLinter, self).__init__()\n        self.lastSelectedLineNo = -1\n\n    def on_modified(self, view):\n        if view.is_scratch():\n            return\n\n        if view.settings().get('sublimelinter') != True:\n            erase_lint_marks(view)\n            return\n\n        linter = select_linter(view)\n\n        # File-based linters are not invoked during a modify\n        if linter and linter.input_method == INPUT_METHOD_FILE:\n            erase_lint_marks(view)\n            return\n\n        # Reset the last selected line number so that the current line will show error messages\n        # when update_statusbar is called.\n        self.lastSelectedLineNo = -1\n        queue_linter(linter, view)\n\n    def on_load(self, view):\n        reload_settings(view)\n\n        sublimelinter_setting = view.settings().get('sublimelinter')\n\n        if view.is_scratch() or sublimelinter_setting == False or sublimelinter_setting == 'save-only':\n            return\n\n        queue_linter(select_linter(view), view, event='on_load')\n\n    def on_post_save(self, view):\n        sublimelinter_setting = view.settings().get('sublimelinter')\n\n        if sublimelinter_setting == None:\n            reload_settings(view)\n\n        if view.is_scratch() or sublimelinter_setting == False:\n            return\n\n        reload_view_module(view)\n        queue_linter(select_linter(view), view, preemptive=True, event='on_post_save')\n\n    def on_selection_modified(self, view):\n        if view.is_scratch():\n            return\n        delay_queue(1000)  # on movement, delay queue (to make movement responsive)\n\n        # We only display errors in the status bar for the last line in the current selection.\n        # If that line number has not changed, there is no point in updating the status bar.\n        lastSelectedLineNo = last_selected_lineno(view)\n\n        if lastSelectedLineNo != self.lastSelectedLineNo:\n            self.lastSelectedLineNo = lastSelectedLineNo\n            update_statusbar(view)\n\n\nclass FindLintErrorCommand(sublime_plugin.TextCommand):\n    '''This command is just a superclass for other commands, it is never enabled.'''\n    def is_enabled(self):\n        return select_linter(self.view) is not None\n\n    def find_lint_error(self, forward):\n        linter = select_linter(self.view, ignore_disabled=True)\n\n        if not linter:\n            return\n\n        self.view.run_command('lint', linter.language)\n        regions = get_lint_regions(self.view, reverse=not forward, coalesce=True)\n\n        if len(regions) == 0:\n            sublime.error_message('No lint errors.')\n            return\n\n        selected = self.view.sel()\n        point = selected[0].begin() if forward else selected[-1].end()\n        regionToSelect = None\n\n        # If going forward, find the first region beginning after the point.\n        # If going backward, find the first region ending before the point.\n        # If nothing is found in the given direction, wrap to the first/last region.\n        if forward:\n            for index, region in enumerate(regions):\n                if point < region.begin():\n                    regionToSelect = region\n                    break\n        else:\n            for index, region in enumerate(regions):\n                if point > region.end():\n                    regionToSelect = region\n                    break\n\n        # If there is only one error line and the cursor is in that line, we cannot move.\n        # Otherwise wrap to the first/last error line unless settings disallow that.\n        if regionToSelect is None and (len(regions) > 1 or not regions[0].contains(point)):\n            if self.view.settings().get('sublimelinter_wrap_find', True):\n                regionToSelect = regions[0]\n\n        if regionToSelect is not None:\n            select_lint_region(self.view, regionToSelect)\n        else:\n            sublime.error_message('No {0} lint errors.'.format('next' if forward else 'previous'))\n\n        return regionToSelect\n\n\nclass FindNextLintErrorCommand(FindLintErrorCommand):\n    def run(self, edit):\n        '''\n        Move the cursor to the next lint error in the current view.\n        The search will wrap to the top unless the sublimelinter_wrap_find\n        setting is set to false.\n        '''\n        self.find_lint_error(forward=True)\n\n\nclass FindPreviousLintErrorCommand(FindLintErrorCommand):\n    def run(self, edit):\n        '''\n        Move the cursor to the previous lint error in the current view.\n        The search will wrap to the bottom unless the sublimelinter_wrap_find\n        setting is set to false.\n        '''\n        self.find_lint_error(forward=False)\n\n\nclass SublimelinterWindowCommand(sublime_plugin.WindowCommand):\n    def is_enabled(self):\n        view = self.window.active_view()\n\n        if view:\n            if view.is_scratch():\n                return False\n            else:\n                return True\n        else:\n            return False\n\n    def run_(self, args):\n        pass\n\n\nclass SublimelinterAnnotationsCommand(SublimelinterWindowCommand):\n    '''Commands to extract annotations and display them in\n       a file\n    '''\n    def run_(self, args):\n        linter = LINTERS.get('annotations', None)\n\n        if linter is None:\n            return\n\n        view = self.window.active_view()\n\n        if not view:\n            return\n\n        text = view.substr(sublime.Region(0, view.size())).encode('utf-8')\n        filename = (view.file_name() or '').encode('utf-8')\n        notes = linter.extract_annotations(text, view, filename)\n        _, filename = os.path.split(filename)\n        annotations_view, _id = view_in_tab(view, 'Annotations from {0}'.format(filename), notes, '')\n\n\nclass SublimelinterCommand(SublimelinterWindowCommand):\n    def is_enabled(self):\n        enabled = super(SublimelinterCommand, self).is_enabled()\n\n        if not enabled:\n            return False\n\n        linter = select_linter(self.window.active_view(), ignore_disabled=True)\n        return linter is not None\n\n    def run_(self, args={}):\n        view = self.window.active_view()\n        action = args.get('action', '')\n\n        if view and action:\n            if action == 'lint':\n                self.lint_view(view, show_popup_list=args.get('show_popup', False))\n            else:\n                view.run_command('lint', action)\n\n    def lint_view(self, view, show_popup_list):\n        linter = select_linter(view, ignore_disabled=True)\n\n        if linter:\n            view.run_command('lint', linter.language)\n            regions = get_lint_regions(view, coalesce=True)\n\n            if regions:\n                if show_popup_list:\n                    popup_error_list(view)\n                else:\n                    sublime.error_message('{0} lint error{1}.'.format(len(regions), 's' if len(regions) != 1 else ''))\n            else:\n                sublime.error_message('No lint errors.')\n        else:\n            syntax = syntax_name(view)\n            sublime.error_message('No linter for the syntax \"{0}\"'.format(syntax))\n\n\nclass SublimelinterLintCommand(SublimelinterCommand):\n    def is_enabled(self):\n        enabled = super(SublimelinterLintCommand, self).is_enabled()\n\n        if enabled:\n            view = self.window.active_view()\n\n            if view and view.settings().get('sublimelinter') == True:\n                return False\n\n        return enabled\n\n\nclass SublimelinterShowErrorsCommand(SublimelinterCommand):\n    def is_enabled(self):\n        return super(SublimelinterShowErrorsCommand, self).is_enabled()\n\n\nclass SublimelinterEnableLoadSaveCommand(SublimelinterCommand):\n    def is_enabled(self):\n        enabled = super(SublimelinterEnableLoadSaveCommand, self).is_enabled()\n\n        if enabled:\n            view = self.window.active_view()\n\n            if view and view.settings().get('sublimelinter') == 'load-save':\n                return False\n\n        return enabled\n\n\nclass SublimelinterEnableSaveOnlyCommand(SublimelinterCommand):\n    def is_enabled(self):\n        enabled = super(SublimelinterEnableSaveOnlyCommand, self).is_enabled()\n\n        if enabled:\n            view = self.window.active_view()\n\n            if view and view.settings().get('sublimelinter') == 'save-only':\n                return False\n\n        return enabled\n\n\nclass SublimelinterDisableCommand(SublimelinterCommand):\n    def is_enabled(self):\n        enabled = super(SublimelinterDisableCommand, self).is_enabled()\n\n        if enabled:\n            view = self.window.active_view()\n\n            if view and view.settings().get('sublimelinter') == False:\n                return False\n\n        return enabled\n"
  },
  {
    "path": "SublimeLinter.sublime-settings",
    "content": "/*\n    SublimeLinter default settings\n*/\n{\n    /*\n        Sets the mode in which SublimeLinter runs:\n\n        true - Linting occurs in the background as you type.\n        false - Linting only occurs when you initiate it.\n        \"load-save\" - Linting occurs only when a file is loaded and saved (the default).\n        \"save-only\" - Linting occurs only when a file is saved.\n    */\n    \"sublimelinter\": \"load-save\",\n\n    /*\n        Maps language names **as listed at the beginning of the README** (but all lowercase)\n        to executables for non-built in linters. If the executable is not in the default system path,\n        or on posix systems is not in /usr/local/bin or ~/bin, then you must specify\n        the full path to the executable. Note that paths in Windows must use double\n        backslashes, for example \"C:\\\\Program Files (x86)\\\\nodejs\\\\node.exe\".\n\n        Please note that the map _keys_ do not always match the name of the\n        executable, but rather the language syntax for the executable to lint.\n\n        This is the effective default map; your mappings may override these.\n\n        \"sublimelinter_executable_map\":\n        {\n            \"perl\": \"perl\",\n            \"php\": \"php\",\n            \"ruby\": \"ruby\"\n        },\n    */\n    \"sublimelinter_executable_map\":\n    {\n    },\n\n    /*\n        Maps syntax names to linters. This allows variations on a syntax\n        (for example \"Python (Django)\") to be linted. The key is\n        the name of the syntax **as it appears in the syntax list\n        at the bottom right of the window**, and the value\n        is the linter name **as listed in the README** (all lowercase)\n        that the syntax maps to.\n    */\n    \"sublimelinter_syntax_map\":\n    {\n        \"Python Django\": \"python\",\n        \"Ruby on Rails\": \"ruby\",\n        \"C++\": \"c\"\n    },\n\n    // An array of linter names to disable. Names should be lowercase.\n    \"sublimelinter_disable\":\n    [\n    ],\n\n    /*\n        The minimum delay in seconds (fractional seconds are okay) before\n        a linter is run when the \"sublimelinter\" setting is true. This allows\n        you to have background linting active, but defer the actual linting\n        until you are idle. When this value is greater than the built in linting delay,\n        errors are erased when the file is modified, since the assumption is\n        you don't want to see errors while you type.\n    */\n    \"sublimelinter_delay\": 2,\n\n    /*\n        Selects the way the lines with errors or warnings are marked; \"outline\" draws\n        outline boxes around the lines, \"fill\" fills the lines with the outline color,\n        and \"none\" (default) disables all outline styles.\n    */\n    \"sublimelinter_mark_style\": \"none\",\n\n    /*\n        If true, lines with errors or warnings will be filled in with the\n        outline color.\n\n        This setting is DEPRECATED and will be ignored in future\n        versions. Use \"sublimelinter_mark_style\" instead. For backwards\n        compatibility reasons, this setting overrides \"sublimelinter_mark_style\"\n        if that one is set to \"outline\", but has no effect if it's set to \"none\".\n    */\n    \"sublimelinter_fill_outlines\": false,\n\n    // If true, lines with errors or warnings will have a gutter mark.\n    \"sublimelinter_gutter_marks\": true,\n\n    /*\n        Choose the theme for gutter marks; available built-in options are:\n        \"alpha\", \"bright\", \"dark\", \"hard\" and \"simple\"\n\n        Anything else will be treated as a path to a set of images.\n        For instance, setting the value to \"../User/my-awesome-theme\"\n        would cause SublimeLinter to look for the images:\n        \"../User/my-awesome-theme-illegal.png\",\n        \"../User/my-awesome-theme-violation.png\",\n        \"../User/my-awesome-theme-warning.png\"\n        These images should all be approximately 32x32px.\n    */\n    \"sublimelinter_gutter_marks_theme\": \"simple\",\n\n    // If true, the find next/previous error commands will wrap.\n    \"sublimelinter_wrap_find\": true,\n\n    // If true, when the file is saved any errors will appear in a popup list\n    \"sublimelinter_popup_errors_on_save\": false,\n\n    // JavaScript linter: \"gjslint\" to use the closure javascript linter (if available),\n    // or either \"jshint\" or \"jslint\" to use a built in linter.\n    \"javascript_linter\": \"jshint\",\n\n    // jshint: options for linting JavaScript. See http://www.jshint.com/docs/#options for more info.\n    // By deault, eval is allowed.\n    \"jshint_options\":\n    {\n        // To fix column positions for JSHint errors you may want to add `\"indent\": 1` to your\n        // **User** \"jshint_options\". This issue affects users with tabs for indentation.\n        // This fix was reverted due to a conflict with using the `\"white\": true` option.\n        // \"indent\": 1,\n        \"evil\": true,\n        \"regexdash\": true,\n        \"browser\": true,\n        \"wsh\": true,\n        \"trailing\": true,\n        \"sub\": true,\n        \"devel\": true\n    },\n\n    // A list of command line options to send to gjslint. --nobeep is always sent.\n    \"gjslint_options\":\n    [\n    ],\n\n    // A list of gjslint error numbers to ignore. The list of error codes is here:\n    // http://closure-linter.googlecode.com/svn/trunk/closure_linter/errors.py\n    \"gjslint_ignore\":\n    [\n        110  // line too long\n    ],\n\n    // CSSLint options:\n    // Each rule can have three values: error|warning|true|false\n    // false => rule is disabled.\n    // true => alias to 'error'\n    // All rules are enabled by default.\n    // Currently the only difference between warnings and errors is in the prefix of the message in the Sublime status bar.\n    \"csslint_options\":\n    {\n        \"adjoining-classes\": \"warning\",\n        \"box-model\": true,\n        \"box-sizing\": \"warning\",\n        \"compatible-vendor-prefixes\": \"warning\",\n        \"display-property-grouping\": true,\n        \"duplicate-background-images\": \"warning\",\n        \"duplicate-properties\": true,\n        \"empty-rules\": true,\n        \"errors\": true,\n        \"fallback-colors\": \"warning\",\n        \"floats\": \"warning\",\n        \"font-faces\": \"warning\",\n        \"font-sizes\": \"warning\",\n        \"gradients\": \"warning\",\n        \"ids\": \"warning\",\n        \"import\": \"warning\",\n        \"important\": \"warning\",\n        \"known-properties\": true,\n        \"outline-none\": \"warning\",\n        \"overqualified-elements\": \"warning\",\n        \"qualified-headings\": \"warning\",\n        \"regex-selectors\": \"warning\",\n        \"rules-count\": \"warning\",\n        \"shorthand\": \"warning\",\n        \"star-property-hack\": \"warning\",\n        \"text-indent\": \"warning\",\n        \"underscore-property-hack\": \"warning\",\n        \"unique-headings\": \"warning\",\n        \"universal-selector\": \"warning\",\n        \"vendor-prefix\": true,\n        \"zero-units\": \"warning\"\n    },\n\n    // Set this to false to turn pep8 checking off completely\n    \"pep8\": true,\n\n    /*\n        A list of pep8 error numbers to ignore. By default \"line too long\" errors are ignored.\n        The list of error codes is in this file: https://github.com/jcrocholl/pep8/blob/master/pep8.py.\n        Search for \"Ennn:\", where nnn is a 3-digit number.\n    */\n    \"pep8_ignore\":\n    [\n        \"E501\"\n    ],\n\n    /*\n        If you use SublimeLinter for pyflakes checks, you can ignore some of the \"undefined name xxx\"\n        errors (comes in handy if you work with post-processors, globals/builtins available only at runtime, etc.).\n        You can control what names will be ignored with the user setting \"pyflakes_ignore\".\n\n        Example:\n\n        \"pyflakes_ignore\":\n            [\n                \"some_custom_builtin_o_mine\",\n                \"A_GLOBAL_CONSTANT\"\n            ],\n    */\n    \"pyflakes_ignore\":\n    [\n    ],\n\n    /*\n        Ordinarily pyflakes will issue a warning when 'from foo import *' is used,\n        but it is ignored since the warning is not that helpful. If you want to see this warning,\n        set this option to false.\n    */\n    \"pyflakes_ignore_import_*\": true,\n\n    /*\n        Perl linter: \"perl\" to use the Perl language syntax check, or \"perlcritic\" to use Perl::Critic linting.\n        Perl is now set to use \"perlcritic\" by default due to a vulnerability with blindly running `perl -c`\n        on files with `BEGIN` or `CHECK` blocks.\n    */\n    \"perl_linter\": \"perlcritic\",\n\n    // Objective-J: if true, non-ascii characters are flagged as an error.\n    \"sublimelinter_objj_check_ascii\": false,\n\n    // Set to true to highlight annotations\n    \"sublimelinter_notes\": false,\n\n    // The set of annotation phrases to highlight\n    \"annotations\": [\"TODO\", \"README\", \"FIXME\"]\n}\n"
  },
  {
    "path": "changelog.txt",
    "content": "SublimeLinter 1.5.1 changelog\n=============================\n\nNEW FEATURES\n------------\n- SublimeLinter keeps its settings in its own settings file now:\n  SublimeLinter.sublime-settings. You will need to copy your\n  user settings to this file. To do so, follow these steps:\n\n  1. Select \"Preferences->Settings - User\" in one tab/window.\n     The title of this tab should be \"Preferences.sublime-settings\".\n  2. Open another tab/window and select\n     `Preferences->Package Settings->SublimeLinter->Settings - User`.\n     The title of this window should be\n     `SublimeLinter.sublime-settings`.\n  3. Copy/cut any of the following settings from\n     Preferences.sublime-settings to SublimeLinter.sublime-settings:\n\n        sublimelinter\n        sublimelinter_executable_map\n        sublimelinter_syntax_map\n        sublimelinter_disable\n        sublimelinter_delay\n        sublimelinter_fill_outlines\n        sublimelinter_gutter_marks\n        sublimelinter_wrap_find\n        sublimelinter_popup_errors_on_save\n        javascript_linter\n        jshint_options\n        pep8_ignore\n        pyflakes_ignore\n        pyflakes_ignore_import_*\n        sublimelinter_objj_check_ascii\n\n  4. Save SublimeLinter.sublime-settings. The changes may not take\n     effect until you restart Sublime Text.\n\n  When changes are made to the user SublimeLinter settings, they\n  are immediately reloaded into every open view. Note that this will\n  override any temporary changes you may have made to the settings in\n  a given view.\n- The google closure JavaScript linter (gjslint) is now supported.\n  (https://developers.google.com/closure/utilities/docs/linter_howto)\n  There is a new setting, `javascript_linter`, which determines which\n  linter to use, jshint or gjslinter. You may also customize gjslint\n  behavior with the `gjslint_options` and `gjslint_ignore` settings.\n  Please select\n  `Preferences->Package Settings->SublimeLinter->Settings - Default`\n  for more information on these settings.\n- The color theme names have been changed to avoid clashes with\n  built in names.\n\n    Old                     New\n    ---------------------   -----------------------------\n    sublimelinter.<type>    sublimelinter.outline.<type>\n    invalid.<type>          sublimelinter.underline.<type>\n\n  You will have to update your color themes accordingly. Please\n  select `Preferences->Package Settings->SublimeLinter->README` and\n  search for \"Customizing colors\" for more information.\n- When selecting an error from the popup error list, the view is\n  centered on the error line.\n\nCHANGES/FIXES\n-------------\n- The PHP error regex has been updated to work with PHP 5.3.8 on Mac\n  OS X.\n- The popup error list will no longer choke on non-ASCII text.\n- Selecting an error from the popup error list no longer attempts to\n  go directly to the point of an error as this could not be done\n  reliably. It will jump to the first non-whitespace character of\n  the error's line.\n- Go to next/previous error works correctly when an error line has\n  no underlines.\n- If an exception is thrown by jshint (e.g. too many errors), the\n  errors captured up to that point are displayed.\n- The built in jshint has been updated from the master jshint.\n- Fixed errors that would occur with the popup error list when there\n  was more than error on a line.\n\n\nSublimeLinter 1.5.2 changelog\n=============================\n\nCHANGES/FIXES\n-------------\n- Fixed a problem with messages.json that prevented correct\n  upgrading.\n\nIMPORTANT\n---------\nPlease check to see if you have multiple listings for `SublimeLinter`\nin `Preferences -> Package Settings`. If you do see 2 listings,\nplease run `Package Control: Upgrade/Overwrite All Packages` from\nthe Command Palette (`Tools -> Command Palette`).\n\n\nSublimeLinter 1.5.3 changelog\n=============================\n\nCHANGES/FIXES\n-------------\n- Annotations have been fixed.\n- Entries in \"sublimelinter_syntax_map\" take precedence over built\n  in mappings.\n- Lint errors in PHP files will hopefully not be logged to the PHP\n  log file.\n\n\nSublimeLinter 1.5.4 changelog\n=============================\n\nCHANGES/FIXES\n-------------\n- jshint.js has been updated to the latest master version.\n- [issue #128] An \"unsafe\" option has been added to jshint. If set\n  true, any UTF-8 characters are allowed in the source.\n\n\nSublimeLinter 1.5.5 changelog\n=============================\n\nCHANGES/FIXES\n-------------\n- This change log is available from the SublimeLinter preferences\n  menu.\n\n\nSublimeLinter 1.5.6 changelog\n=============================\n\nCHANGES/FIXES\n-------------\n- Fixed a problem with messages.json that prevented correct\n  upgrading.\n\nIMPORTANT\n---------\nPlease check to see if you have multiple listings for `SublimeLinter`\nin `Preferences -> Package Settings`. If you do see 2 listings,\nplease run `Package Control: Upgrade/Overwrite All Packages` from\nthe Command Palette (`Tools -> Command Palette`).\n\n\nSublimeLinter 1.5.7 changelog\n=============================\n\nCHANGES/FIXES\n-------------\n- node.js is the preferred JavaScript engine on Mac OS X and will be\n  used if it is installed. JavaScriptCore does not handle non-ASCII\n  text correctly and you should install node.js if possible.\n- If you imported `BaseLinter.JSC_PATH`, please change your linter to\n  use the `self.jsc_path()` method instead. JSC_PATH should no\n  longer be considered public.\n\n\nSublimeLinter 1.6.0 changelog\n=============================\n\nNEW FEATURES\n------------\n- Simpler abstraction of JavaScript engines for JS powered linters.\n\n  To leverage a JS linter, include a \"linter.js\" file; this file\n  should `require` the actual linter library file and export a `lint`\n  function. The `lint` function should return a list of errors back\n  to the python language handler file (via the `errors` parameter to\n  the `parse_errors` method).\n\n  Although \"linter.js\" should follow the Node.js api, the linter may\n  also be run via JavaScriptCore on OS X if Node.js is not installed.\n  In the case where JavaScriptCore is used, require + export are\n  shimmed to keep things consistent. However, it is important not to\n  assume that a full Node.js api is available. If you must know what\n  JS engine you are using, you may check for `USING_JSC` to be set\n  as `true` when JavaScriptCore is used.\n\n  For examples of using the JS engines, see \"csslint\", \"jslint\", and\n  \"jshint\" in \"SublimeLinter/sublimelinter/modules/libs\" and the\n  respective python code of \"css.py\" and \"javascript.py\" in\n  \"SublimeLinter/sublimelinter/modules\".\n- Douglas Crockford's [JSLint](http://jslint.com) JavaScript linter\n  is now supported. To use JSLint set the \"javascript_linter\" setting\n  to \"jslint\". You may also customize jslint behavior with the\n  \"jslint_options\" setting. For more information about options\n  available to JSLint, see http://jslint.com/lint.html.\n- The [CSSLint](http://csslint.net) CSS linter is now supported.\n  By default all CSSLint settings are turned on. You may customize\n  csslint behavior with the \"csslint_options\" setting. Please select\n  \"Preferences->Package Settings->SublimeLinter->Settings - Default\"\n  for more information on turning off or adjusting severity of tests.\n  For more information about options available to CSSLint, see\n  https://github.com/stubbornella/csslint/wiki/Rules.\n\n\nSublimeLinter 1.6.1 changelog\n=============================\n\nCHANGES/FIXES\n-------------\n- Fixed an issue (#141) with JSLint running in Node.js\n- Updated CSSLint, JSLint, JSHint to latest stable releases.\n- Added additional debugging output (in Sublime console) when\n  errors occur running linters written in JavaScript.\n\n\nSublimeLinter 1.6.2 changelog\n=============================\n\nCHANGES/FIXES\n-------------\n- Replaced the default perl linter with Perl::Critic. The standard\n  Perl syntax checker can still be invoked by switching the\n  \"perl_linter\" setting to \"perl\".\n- Added a LICENSE file to define appropriate usage of SublimeLinter\n  and its source.\n- Converted README back to markdown.\n\nIMPORTANT\n---------\nDue to a vulnerability (issue #77) with the Perl linter, Perl syntax\nchecking is no longer enabled by default. The default linter for\nPerl has been replaced by Perl::Critic.\n\n\nSublimeLinter 1.6.3 changelog\n=============================\n\nNEW FEATURES\n------------\n- Support for `.jshintrc` files. If using JSHint, SublimeLinter\n  will recursively search the directory tree (from the file location\n  to the file-system root directory). This functionality is\n  specified in the JSHint README.\n  https://github.com/jshint/node-jshint/#within-your-projects-directory-tree\n\nCHANGES/FIXES\n-------------\n- Fixed README reference in the menu.\n- Updated CoffeeScript module to be compatible with the updated\n  coffee command in version 1.3.\n\nIMPORTANT\n---------\nIf you are using the CoffeeScript linting, please upgrade\nthe installed coffee-script NPM module to 1.3 or greater.\n\n    npm update -g coffee-script\n\n\nSublimeLinter 1.6.4 changelog\n=============================\n\nIMPORTANT!!\n-----------\nPlease note that the SublimeLinter repository has moved to:\n\n    https://github.com/SublimeLinter/SublimeLinter\n\nIssues and pull requests should be made there.\n\nNEW FEATURES\n------------\n- The Objective-J linter now catches spaces inside parentheses\n  and dependent clauses on the same line as a control structure.\n\nCHANGES/FIXES\n-------------\n- The README has been reorganized to hopefully be clearer.\n- More explicit Node.js installation instructions have been provided.\n- The \"pep8\" setting is now recognized in SublimeLinter's settings.\n- When a minimum delay is specified with the \"sublimelinter_delay\"\n  setting, SublimeLinter will only lint the currently displayed file\n  when the queued linters run. This allows you to avoid linting of\n  files as they are selected in the choose file palette.\n\n\nSublimeLinter 1.6.5 changelog\n=============================\n\nNEW FEATURES\n------------\n- Added a (Ruby) Haml linter based on `haml -c`. For more\n  information about Haml, please see http://haml.info.\n- Added a simple Git commit message linter. This linter follows the\n  rules as defined by\n  http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html\n\nCHANGES/FIXES\n-------------\n- Updated several links to point to the SublimeLinter's new Github\n  location.\n- \"Ruby on Rails\" syntax maps to \"ruby\" as part of the default\n  settings.\n- Linter arguments are now consistently defined as arrays (instead\n  of tuples).\n- Syntax map settings are no longer (sometimes) case-sensitive.\n\n\nSublimeLinter 1.6.6 changelog\n=============================\n\nCHANGES/FIXES\n-------------\n- JSHint now shows underlines at the appropriate character positions\n  when using tabs for indentation.\n- Upgrading CSSLint to the latest version (v0.9.8). This adds\n  support for the latest \"Compatibility\" options: \"Disallow star\n  hack\" and \"Disallow underscore hack\".\n- Annotation highlighting is working again.\n- Git Commit Message linting now ignores `git --diff` output in\n  messages. These lines are automatically generated and inserted\n  when running `git commit -v`.\n\n\nSublimeLinter 1.6.7 changelog\n=============================\n\nNEW FEATURES\n------------\n- Puppet linting is now supported via `puppet parser validate`.\n- Added an option for more granular control of outline decorations.\n  Set the value of \"sublimelinter_mark_style\" to \"outline\", \"fill\",\n  or \"none\" in the user settings.\n\nCHANGES/FIXES\n-------------\n- Repaired the built-in CSS linter (CSSLint). This was broken with\n  with the last update.\n- Added missing documentation for \"save-only\" linting in the\n  settings file.\n- Adjusted ambiguous/misleading documentation for the\n  \"sublimelinter_executable_map\" setting.\n\n\nSublimeLinter 1.6.8 changelog\n=============================\n\nNEW FEATURES\n------------\n- HTML5 linting support via `tidy`. This linter will not run unless\n  you have a version of tidy with HTML5 support. To use this linter,\n  please see: https://github.com/w3c/tidy-html5\n- XML linting via `xmllint`.\n\nCHANGES/FIXES\n-------------\n- Made significant progress on issue (#181). However, SublimeLinter\n  still throws with some linter types on Windows 7 when a user has\n  non-ascii characters in the path (to the SL plugin).\n- Updated PEP8 to v1.1\n- Updated Pyflakes to v0.5.0\n- Updated JSHint to latest stable (r11).\n- Reverted a fix for accurate (JSHint) error column positions (when\n  using tab indentation) due to a regression with the `\"white\": true`\n  option. You may still manually fix error positions by setting\n  `\"indent\": 1`.\n- Changed (the default) background linting delay to a more sane 2\n  seconds. This reduces memory usage, cpu processing, and visual\n  noise while you are actively writing code.\n\n\nSublimeLinter 1.6.9 changelog\n=============================\n\nNEW FEATURES\n------------\n- C/C++ lint via `cppcheck`. Also added alternative (hidden) support\n  for `cpplint.py`. Please see README for more info.\n- Lua syntax check via `luac`.\n\nCHANGES/FIXES\n-------------\n- Adding a 'beta' channel for SublimeLinter into Package Control.\n  This branch will act as a more formal method for testing new\n  features and fixes before a release.\n\n\nSublimeLinter 1.6.10 changelog\n==============================\n\nCHANGES/FIXES\n-------------\n- Puppet validation supports error output for Puppet v3.0+.\n- JSHint options now support the (proper) \"globals\" definition.\n- Lua syntax check no longer creates luac.out file clutter.\n- Clarified documentation for styling sublimelinter.annotations.\n\n\nSublimeLinter 1.6.11 changelog\n==============================\n\nCHANGES/FIXES\n-------------\n- Github (nodeload) zip url scheme changed.\n\n\nSublimeLinter 1.6.12 changelog\n==============================\n\nCHANGES/FIXES\n-------------\n- Cpplint no longer uses a temporary file - it leverages stdin\n  instead.\n- Fixed issue #298: C linter throws \"KeyError\"\n\n\nSublimeLinter 1.6.13 changelog\n==============================\n\nCHANGES/FIXES\n-------------\n- Updated PEP8 to version v1.4\n- Updated PyFlakes to v0.6.1\n- Updated CSSLint to v0.9.10\n- Update JSHint to v1.0.0\n- Update JSLint to latest\n- Fixed issues with attempting to encode file name when using\n  scratch space.\n\n\nSublimeLinter 1.7.0 changelog\n=============================\n\nNEW FEATURES\n------------\n- Add \"Quick Start\" section to the README\n- New commands for the (Sublime Text) command palette to open the\n  SublimeLinter preferences files (Default & User)\n- Ruby linting support via [ruby-lint](https://github.com/YorickPeterse/ruby-lint)\n- Haskell linting support via [hlint](http://community.haskell.org/~ndm/hlint/)\n- Add gutter mark themes. Add 5 new built-in themes:\n  \"alpha\", \"bright\", \"dark\", \"hard\", and \"simple\".\n  Custom themes can also be used.\n\nCHANGES/FIXES\n-------------\n- Update JSHint to v1.1.0\n- Update CoffeeScript linter to support latest error message format\n- Settings are refreshed when a new file is saved; this should fix\n  several bugs: #233, #359, #149, #367\n- The `lint_args` setting now matches the documentation; it will\n  override the default arguments rather than extend them. This will\n  give users full control over linter/checker arguments.\n- Clean up markdown formatting in changelog\n\nIMPORTANT\n---------\nDue to the fix for `lint_args`, if you are currently customizing this\nsetting, you **must** adjust your settings.\n\n\nSublimeLinter 1.7.1 changelog\n=============================\n\nCHANGES/FIXES\n-------------\n- Update JSLint to latest\n- Update JSHint to v2.1.5\n- Updated link to JSHint documentation\n- Updated PEP8 to v1.4.6\n- Updated Pyflakes to v0.7.3\n- Gutter mark icons are now retina quality\n- Included Gutter mark icon PSD (for tinkering :)\n\n\nSublimeLinter 1.7.2 changelog\n=============================\n\nCHANGES/FIXES\n-------------\n- Update JSHint to v2.1.8\n- Fixing compatibility regression with latest JSHint\n- Fixing compatibility regression with latest Pyflakes\n- Apologizing for hasty v1.7.1 release ;)\n"
  },
  {
    "path": "messages/1.5.1.txt",
    "content": "SublimeLinter 1.5.1 changelog\n=============================\n\nNEW FEATURES\n------------\n- SublimeLinter keeps its settings in its own settings file now:\n  SublimeLinter.sublime-settings. You will need to copy your\n  user settings to this file. To do so, follow these steps:\n  \n  1. Select \"Preferences->Settings - User\" in one tab/window.\n     The title of this tab should be \"Preferences.sublime-settings\".\n  2. Open another tab/window and select\n     `Preferences->Package Settings->SublimeLinter->Settings - User`.\n     The title of this window should be\n     `SublimeLinter.sublime-settings`.\n  3. Copy/cut any of the following settings from\n     Preferences.sublime-settings to SublimeLinter.sublime-settings:\n\n        sublimelinter\n        sublimelinter_executable_map\n        sublimelinter_syntax_map\n        sublimelinter_disable\n        sublimelinter_delay\n        sublimelinter_fill_outlines\n        sublimelinter_gutter_marks\n        sublimelinter_wrap_find\n        sublimelinter_popup_errors_on_save\n        javascript_linter\n        jshint_options\n        pep8_ignore\n        pyflakes_ignore\n        pyflakes_ignore_import_*\n        sublimelinter_objj_check_ascii\n\n  4. Save SublimeLinter.sublime-settings. The changes may not take\n     effect until you restart Sublime Text.\n\n  When changes are made to the user SublimeLinter settings, they\n  are immediately reloaded into every open view. Note that this will\n  override any temporary changes you may have made to the settings in\n  a given view.\n- The google closure JavaScript linter (gjslint) is now supported.\n  (https://developers.google.com/closure/utilities/docs/linter_howto)\n  There is a new setting, `javascript_linter`, which determines which\n  linter to use, jshint or gjslinter. You may also customize gjslint\n  behavior with the `gjslint_options` and `gjslint_ignore` settings.\n  Please select\n  `Preferences->Package Settings->SublimeLinter->Settings - Default`\n  for more information on these settings.\n- The color theme names have been changed to avoid clashes with\n  built in names.\n\n    Old                     New\n    ---------------------   -----------------------------\n    sublimelinter.<type>    sublimelinter.outline.<type>\n    invalid.<type>          sublimelinter.underline.<type>\n\n  You will have to update your color themes accordingly. Please \n  select `Preferences->Package Settings->SublimeLinter->README` and \n  search for \"Customizing colors\" for more information.\n- When selecting an error from the popup error list, the view is \n  centered on the error line.\n\nCHANGES/FIXES\n-------------\n- The PHP error regex has been updated to work with PHP 5.3.8 on Mac\n  OS X.\n- The popup error list will no longer choke on non-ASCII text.\n- Selecting an error from the popup error list no longer attempts to\n  go directly to the point of an error as this could not be done \n  reliably. It will jump to the first non-whitespace character of \n  the error's line.\n- Go to next/previous error works correctly when an error line has\n  no underlines.\n- If an exception is thrown by jshint (e.g. too many errors), the \n  errors captured up to that point are displayed.\n- The built in jshint has been updated from the master jshint.\n- Fixed errors that would occur with the popup error list when there \n  was more than error on a line.\n\n"
  },
  {
    "path": "messages/1.5.2.txt",
    "content": "SublimeLinter 1.5.2 changelog\n=============================\n\nCHANGES/FIXES\n-------------\n- Fixed a problem with messages.json that prevented correct\n  upgrading.\n\nIMPORTANT\n---------\nPlease check to see if you have multiple listings for `SublimeLinter`\nin `Preferences -> Package Settings`. If you do see 2 listings, \nplease run `Package Control: Upgrade/Overwrite All Packages` from \nthe Command Palette (`Tools -> Command Palette`).\n"
  },
  {
    "path": "messages/1.5.3.txt",
    "content": "SublimeLinter 1.5.3 changelog\n=============================\n\nCHANGES/FIXES\n-------------\n- Annotations have been fixed.\n- Entries in \"sublimelinter_syntax_map\" take precedence over built\n  in mappings.\n- Lint errors in PHP files will hopefully not be logged to the PHP \n  log file.\n"
  },
  {
    "path": "messages/1.5.4.txt",
    "content": "SublimeLinter 1.5.4 changelog\n=============================\n\nCHANGES/FIXES\n-------------\n- jshint.js has been updated to the latest master version.\n- [issue #128] An \"unsafe\" option has been added to jshint. If set \n  true, any UTF-8 characters are allowed in the source.\n"
  },
  {
    "path": "messages/1.5.5.txt",
    "content": "SublimeLinter 1.5.5 changelog\n=============================\n\nCHANGES/FIXES\n-------------\n- This change log is available from the SublimeLinter preferences \n  menu.\n"
  },
  {
    "path": "messages/1.5.6.txt",
    "content": "SublimeLinter 1.5.6 changelog\n=============================\n\nCHANGES/FIXES\n-------------\n- Fixed a problem with messages.json that prevented correct\n  upgrading.\n\nIMPORTANT\n---------\nPlease check to see if you have multiple listings for `SublimeLinter`\nin `Preferences -> Package Settings`. If you do see 2 listings, \nplease run `Package Control: Upgrade/Overwrite All Packages` from \nthe Command Palette (`Tools -> Command Palette`).\n"
  },
  {
    "path": "messages/1.5.7.txt",
    "content": "SublimeLinter 1.5.7 changelog\n=============================\n\nCHANGES/FIXES\n-------------\n- node.js is the preferred JavaScript engine on Mac OS X and will be \n  used if it is installed. JavaScriptCore does not handle non-ASCII \n  text correctly and you should install node.js if possible.\n- If you imported `BaseLinter.JSC_PATH`, please change your linter to\n  use the `self.jsc_path()` method instead. JSC_PATH should no \n  longer be considered public.\n"
  },
  {
    "path": "messages/1.6.0.txt",
    "content": "SublimeLinter 1.6.0 changelog\n=============================\n\nNEW FEATURES\n------------\n- Simpler abstraction of JavaScript engines for JS powered linters.\n\n  To leverage a JS linter, include a \"linter.js\" file; this file \n  should `require` the actual linter library file and export a `lint`\n  function. The `lint` function should return a list of errors back \n  to the python language handler file (via the `errors` parameter to \n  the `parse_errors` method).\n\n  Although \"linter.js\" should follow the Node.js api, the linter may \n  also be run via JavaScriptCore on OS X if Node.js is not installed.\n  In the case where JavaScriptCore is used, require + export are \n  shimmed to keep things consistent. However, it is important not to \n  assume that a full Node.js api is available. If you must know what \n  JS engine you are using, you may check for `USING_JSC` to be set \n  as `true` when JavaScriptCore is used.\n  \n  For examples of using the JS engines, see \"csslint\", \"jslint\", and\n  \"jshint\" in \"SublimeLinter/sublimelinter/modules/libs\" and the \n  respective python code of \"css.py\" and \"javascript.py\" in\n  \"SublimeLinter/sublimelinter/modules\".\n- Douglas Crockford's [JSLint](http://jslint.com) JavaScript linter\n  is now supported. To use JSLint set the \"javascript_linter\" setting\n  to \"jslint\". You may also customize jslint behavior with the\n  \"jslint_options\" setting. For more information about options \n  available to JSLint, see http://jslint.com/lint.html.\n- The [CSSLint](http://csslint.net) CSS linter is now supported.\n  By default all CSSLint settings are turned on. You may customize\n  csslint behavior with the \"csslint_options\" setting. Please select\n  \"Preferences->Package Settings->SublimeLinter->Settings - Default\"\n  for more information on turning off or adjusting severity of tests.\n  For more information about options available to CSSLint, see\n  https://github.com/stubbornella/csslint/wiki/Rules.\n"
  },
  {
    "path": "messages/1.6.1.txt",
    "content": "SublimeLinter 1.6.1 changelog\n=============================\n\nCHANGES/FIXES\n-------------\n- Fixed an issue (#141) with JSLint running in Node.js\n- Updated CSSLint, JSLint, JSHint to latest stable releases.\n- Added additional debugging output (in Sublime console) when\n  errors occur running linters written in JavaScript.\n"
  },
  {
    "path": "messages/1.6.10.txt",
    "content": "SublimeLinter 1.6.10 changelog\n==============================\n\nCHANGES/FIXES\n-------------\n- Puppet validation supports error output for Puppet v3.0+.\n- JSHint options now support the (proper) \"globals\" definition.\n- Lua syntax check no longer creates luac.out file clutter.\n- Clarified documentation for styling sublimelinter.annotations.\n"
  },
  {
    "path": "messages/1.6.11.txt",
    "content": "SublimeLinter 1.6.11 changelog\n==============================\n\nCHANGES/FIXES\n-------------\n- Github (nodeload) zip url scheme changed.\n"
  },
  {
    "path": "messages/1.6.12.txt",
    "content": "SublimeLinter 1.6.12 changelog\n==============================\n\nCHANGES/FIXES\n-------------\n- Cpplint no longer uses a temporary file - it leverages stdin\n  instead.\n- Fixed issue #298: C linter throws \"KeyError\"\n"
  },
  {
    "path": "messages/1.6.13.txt",
    "content": "SublimeLinter 1.6.13 changelog\n==============================\n\nCHANGES/FIXES\n-------------\n- Updated PEP8 to version v1.4\n- Updated PyFlakes to v0.6.1\n- Updated CSSLint to v0.9.10\n- Update JSHint to v1.0.0\n- Update JSLint to latest\n- Fixed issues with attempting to encode file name when using \n  scratch space.\n"
  },
  {
    "path": "messages/1.6.2.txt",
    "content": "SublimeLinter 1.6.2 changelog\n=============================\n\nCHANGES/FIXES\n-------------\n- Replaced the default perl linter with Perl::Critic. The standard \n  Perl syntax checker can still be invoked by switching the \n  \"perl_linter\" setting to \"perl\".\n- Added a LICENSE file to define appropriate usage of SublimeLinter \n  and its source.\n- Converted README back to markdown.\n\nIMPORTANT\n---------\nDue to a vulnerability (issue #77) with the Perl linter, Perl syntax\nchecking is no longer enabled by default. The default linter for\nPerl has been replaced by Perl::Critic.\n"
  },
  {
    "path": "messages/1.6.3.txt",
    "content": "SublimeLinter 1.6.3 changelog\n=============================\n\nNEW FEATURES\n------------\n- Support for `.jshintrc` files. If using JSHint, SublimeLinter\n  will recursively search the directory tree (from the file location\n  to the file-system root directory). This functionality is\n  specified in the JSHint README.\n  https://github.com/jshint/node-jshint/#within-your-projects-directory-tree\n\nCHANGES/FIXES\n-------------\n- Fixed README reference in the menu.\n- Updated CoffeeScript module to be compatible with the updated\n  coffee command in version 1.3.\n\nIMPORTANT\n---------\nIf you are using the CoffeeScript linting, please upgrade\nthe installed coffee-script NPM module to 1.3 or greater.\n\n    npm update -g coffee-script\n"
  },
  {
    "path": "messages/1.6.4.txt",
    "content": "SublimeLinter 1.6.4 changelog\n=============================\n\nIMPORTANT!!\n-----------\nPlease note that the SublimeLinter repository has moved to:\n\n    https://github.com/SublimeLinter/SublimeLinter\n\nIssues and pull requests should be made there.\n\nNEW FEATURES\n------------\n- The Objective-J linter now catches spaces inside parentheses\n  and dependent clauses on the same line as a control structure.\n\nCHANGES/FIXES\n-------------\n- The README has been reorganized to hopefully be clearer.\n- More explicit Node.js installation instructions have been provided.\n- The \"pep8\" setting is now recognized in SublimeLinter's settings.\n- When a minimum delay is specified with the \"sublimelinter_delay\" \n  setting, SublimeLinter will only lint the currently displayed file \n  when the queued linters run. This allows you to avoid linting of \n  files as they are selected in the choose file palette.\n"
  },
  {
    "path": "messages/1.6.5.txt",
    "content": "SublimeLinter 1.6.5 changelog\n=============================\n\nNEW FEATURES\n------------\n- Added a (Ruby) Haml linter based on `haml -c`. For more \n  information about Haml, please see http://haml.info.\n- Added a simple Git commit message linter. This linter follows the\n  rules as defined by\n  http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html\n\nCHANGES/FIXES\n-------------\n- Updated several links to point to the SublimeLinter's new Github\n  location.\n- \"Ruby on Rails\" syntax maps to \"ruby\" as part of the default\n  settings.\n- Linter arguments are now consistently defined as arrays (instead\n  of tuples).\n- Syntax map settings are no longer (sometimes) case-sensitive.\n"
  },
  {
    "path": "messages/1.6.6.txt",
    "content": "SublimeLinter 1.6.6 changelog\n=============================\n\nCHANGES/FIXES\n-------------\n- JSHint now shows underlines at the appropriate character positions \n  when using tabs for indentation.\n- Upgrading CSSLint to the latest version (v0.9.8). This adds \n  support for the latest \"Compatibility\" options: \"Disallow star \n  hack\" and \"Disallow underscore hack\".\n- Annotation highlighting is working again.\n- Git Commit Message linting now ignores `git --diff` output in\n  messages. These lines are automatically generated and inserted\n  when running `git commit -v`.\n"
  },
  {
    "path": "messages/1.6.7.txt",
    "content": "SublimeLinter 1.6.7 changelog\n=============================\n\nNEW FEATURES\n------------\n- Puppet linting is now supported via `puppet parser validate`.\n- Added an option for more granular control of outline decorations. \n  Set the value of \"sublimelinter_mark_style\" to \"outline\", \"fill\", \n  or \"none\" in the user settings.\n\nCHANGES/FIXES\n-------------\n- Repaired the built-in CSS linter (CSSLint). This was broken with\n  with the last update.\n- Added missing documentation for \"save-only\" linting in the\n  settings file.\n- Adjusted ambiguous/misleading documentation for the\n  \"sublimelinter_executable_map\" setting.\n"
  },
  {
    "path": "messages/1.6.8.txt",
    "content": "SublimeLinter 1.6.8 changelog\n=============================\n\nNEW FEATURES\n------------\n- HTML5 linting support via `tidy`. This linter will not run unless\n  you have a version of tidy with HTML5 support. To use this linter, \n  please see: https://github.com/w3c/tidy-html5\n- XML linting via `xmllint`.\n\nCHANGES/FIXES\n-------------\n- Made significant progress on issue (#181). However, SublimeLinter \n  still throws with some linter types on Windows 7 when a user has \n  non-ascii characters in the path (to the SL plugin).\n- Updated PEP8 to v1.1\n- Updated Pyflakes to v0.5.0\n- Updated JSHint to latest stable (r11).\n- Reverted a fix for accurate (JSHint) error column positions (when \n  using tab indentation) due to a regression with the `\"white\": true`\n  option. You may still manually fix error positions by setting\n  `\"indent\": 1`.\n- Changed (the default) background linting delay to a more sane 2\n  seconds. This reduces memory usage, cpu processing, and visual \n  noise while you are actively writing code.\n"
  },
  {
    "path": "messages/1.6.9.txt",
    "content": "SublimeLinter 1.6.9 changelog\n=============================\n\nNEW FEATURES\n------------\n- C/C++ lint via `cppcheck`. Also added alternative (hidden) support \n  for `cpplint.py`. Please see README for more info.\n- Lua syntax check via `luac`.\n\nCHANGES/FIXES\n-------------\n- Adding a 'beta' channel for SublimeLinter into Package Control.\n  This branch will act as a more formal method for testing new\n  features and fixes before a release.\n"
  },
  {
    "path": "messages/1.7.0.txt",
    "content": "SublimeLinter 1.7.0 changelog\n=============================\n\nNEW FEATURES\n------------\n- Add \"Quick Start\" section to the README\n- New commands for the (Sublime Text) command palette to open the \n  SublimeLinter preferences files (Default & User)\n- Ruby linting support via [ruby-lint](https://github.com/YorickPeterse/ruby-lint)\n- Haskell linting support via [hlint](http://community.haskell.org/~ndm/hlint/)\n- Add gutter mark themes. Add 5 new built-in themes:\n  \"alpha\", \"bright\", \"dark\", \"hard\", and \"simple\".\n  Custom themes can also be used.\n\nCHANGES/FIXES\n-------------\n- Update JSHint to v1.1.0\n- Update CoffeeScript linter to support latest error message format\n- Settings are refreshed when a new file is saved; this should fix\n  several bugs: #233, #359, #149, #367\n- The `lint_args` setting now matches the documentation; it will\n  override the default arguments rather than extend them. This will\n  give users full control over linter/checker arguments.\n- Clean up markdown formatting in changelog\n\nIMPORTANT\n---------\nDue to the fix for `lint_args`, if you are currently customizing this\nsetting, you **must** adjust your settings.\n"
  },
  {
    "path": "messages/1.7.1.txt",
    "content": "SublimeLinter 1.7.1 changelog\n=============================\n\nCHANGES/FIXES\n-------------\n- Update JSLint to latest\n- Update JSHint to v2.1.5\n- Updated link to JSHint documentation\n- Updated PEP8 to v1.4.6\n- Updated Pyflakes to v0.7.3\n- Gutter mark icons are now retina quality\n- Included Gutter mark icon PSD (for tinkering :)\n"
  },
  {
    "path": "messages/1.7.2.txt",
    "content": "SublimeLinter 1.7.2 changelog\n=============================\n\nCHANGES/FIXES\n-------------\n- Update JSHint to v2.1.8\n- Fixing compatibility regression with latest JSHint\n- Fixing compatibility regression with latest Pyflakes\n- Apologizing for hasty v1.7.1 release ;)\n"
  },
  {
    "path": "messages/SublimeLinter3-update1.txt",
    "content": "=====================\nSublimeLinter for ST3\nFundraising update\n=====================\n\nAs of October 28, we have raised $980 (after fees) from 90 donations.\nThis is enough to get started, but I was hoping for twice that amount.\nIf you are one of the thousands of happy SublimeLinter users who has not donated,\nplease consider making a small donation to keep this plugin alive.\nOpen source software is not free! It is we the developers who usually\nend up paying for it.\n\nTo donate and find out more about what you can expect from SublimeLinter3,\ngo here:\n\nhttps://github.com/SublimeLinter/SublimeLinter3#sublimelinter3\n\nIf you are interested in helping with development, please leave a message\nhere:\n\nhttps://github.com/SublimeLinter/SublimeLinter3/issues/3\n\nThanks again for your support,\n\n- Aparajita Fishman\n  SublimeLinter maintainer\n"
  },
  {
    "path": "messages/SublimeLinter3-update2.txt",
    "content": "=====================\nSublimeLinter for ST3\nFundraising update\nOctober 31, 2013\n=====================\n\nThrough October 30, we have raised $2885 (after fees) from 226 donations. Thank you for your support!\nDevelopment has started, and I’m very excited about this new version! But there is still a lot of work\nto do, and I’m getting cool new ideas every day.\n\nSo if you are one of the thousands of happy SublimeLinter users who has not donated yet, it isn’t too late\nto contribute. Please consider making a small donation to fund ongoing development and to compensate\nRyan Hileman for the great work on which SublimeLinter3 is based.\n\nOpen source software is not free! It is we the developers who usually end up paying for it.\nTo donate and find out more about what you can expect from SublimeLinter3, go here:\n\nhttps://github.com/SublimeLinter/SublimeLinter3#sublimelinter3\n\nIf you are interested in helping with development, please leave a message here:\n\nhttps://github.com/SublimeLinter/SublimeLinter3/issues/3\n\nThanks again for your support,\n\n- Aparajita Fishman\n  SublimeLinter maintainer\n"
  },
  {
    "path": "messages/SublimeLinter3-update3.txt",
    "content": "\n  ____        _     _ _                _     _       _              _____\n / ___| _   _| |__ | (_)_ __ ___   ___| |   (_)_ __ | |_ ___ _ __  |___ /\n \\___ \\| | | | '_ \\| | | '_ ` _ \\ / _ \\ |   | | '_ \\| __/ _ \\ '__|   |_ \\\n  ___) | |_| | |_) | | | | | | | |  __/ |___| | | | | ||  __/ |     ___) |\n |____/ \\__,_|_.__/|_|_|_| |_| |_|\\___|_____|_|_| |_|\\__\\___|_|    |____/\n\n                           _\n                          | |__   __ _ ___\n                          | '_ \\ / _` / __|\n                          | | | | (_| \\__ \\\n                          |_| |_|\\__,_|___/\n\n\n                   _                 _          _ _\n                  | | __ _ _ __   __| | ___  __| | |\n                  | |/ _` | '_ \\ / _` |/ _ \\/ _` | |\n                  | | (_| | | | | (_| |  __/ (_| |_|\n                  |_|\\__,_|_| |_|\\__,_|\\___|\\__,_(_)\n\n\nSublimeLinter for Sublime Text 3 is here, and it’s soooooo much better than before!\nInstall it from Package Control and enjoy!\n\nUnless someone else comes forward, SublimeLinter for Sublime Text 2 will no longer\nbe supported. I strongly encourage everyone to upgrade to Sublime Text 3 and\nSublimeLinter 3 — you’ll be glad you did! Take a look at the extensive documentation\nto see the great new features in SublimeLinter 3.\n\nhttps://github.com/SublimeLinter/SublimeLinter3\n\n\n*****************\n Share the love!\n*****************\n\nI spent hundreds of hours writing and documenting SublimeLinter 3 to make it the best\nit can be — easy to use, easy to configure, easy to update, easy to extend. If you use\nSublimeLinter and feel it is making your coding life better and easier, please consider\nmaking a donation to help fund development and support. Thank you!\n\nTo donate: https://github.com/SublimeLinter/SublimeLinter3#share-the-love\n\nThank you for your support!\n\n- Aparajita Fishman\n  SublimeLinter maintainer\n"
  },
  {
    "path": "messages/SublimeLinter3.txt",
    "content": "=====================\nSublimeLinter for ST3\nWe need your help!\n=====================\n\nAccording to the Package Control site, SublimeLinter is the 4th most popular\nplugin for Sublime Text, with 224K installs. That's an incredible number.\nThank you to everyone!\n\nWe all want SublimeLinter to become fully compatible with Sublime Text 3,\nand we want it to be better supported. In moving to ST3 (and python 3),\nwe decided to start from scratch with a new architecture (based on sublimelint)\nthat allows us to get the most out of both ST3 and python 3. And we plan\nto join forces with Ryan Hileman and merge sublimelint and SublimeLinter,\nso we can pool our resources.\n\nTo find out more about what you can expect from SublimeLinter3,\nread about it here:\n\nhttps://github.com/SublimeLinter/SublimeLinter3#sublimelinter3\n\nTo make this happen any time soon, we need your help. I have lots of other\nprojects that currently have a higher priority than SublimeLinter3. If you\nvalue SublimeLinter and want to see it running on ST3 sooner rather than later,\nplease consider donating. If we can raise $3-5K, I'll move SublimeLinter3\nto top of my priority list and finish it off within a week or two.\n\nSee the link above for info on donating.\n\nThanks again,\n\n- Aparajita Fishman\n  SublimeLinter maintainer\n"
  },
  {
    "path": "messages/install.txt",
    "content": "SublimeLinter\n=============\n\nSublimeLinter is a plugin that supports \"lint\" programs (known as \"linters\"). SublimeLinter highlights\nlines of code the linter deems to contain (potential) errors. It also\nsupports highlighting special annotations (for example: TODO) so that they\ncan be quickly located.\n\nSublimeLinter has built in linters for the following languages:\n\n* C/C++ - lint via `cppcheck`\n* CoffeeScript - lint via `coffee -s -l`\n* CSS - lint via built-in [csslint](http://csslint.net)\n* Git Commit Messages - lint via built-in module based on [A Note About Git Commit Messages](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).\n* Haml - syntax check via `haml -c`\n* HTML - lint via `tidy` (actually [tidy for HTML5](http://w3c.github.com/tidy-html5/))\n* Java - lint via `javac -Xlint`\n* JavaScript - lint via built in [jshint](http://jshint.org), [jslint](http://jslint.com), or the [closure linter (gjslint)](https://developers.google.com/closure/utilities/docs/linter_howto) (if installed)\n* Lua - syntax check via `luac`\n* Objective-J - lint via built-in [capp_lint](https://github.com/aparajita/capp_lint)\n* Perl - lint via [Perl:Critic](http://perlcritic.com/) or syntax+deprecation check via `perl -c`\n* PHP - syntax check via `php -l`\n* Puppet - syntax check via `puppet parser validate`\n* Python - native, moderately-complete lint\n* Ruby - syntax check via `ruby -wc`\n* XML - lint via `xmllint`\n\n\nFor more information:\n---------------------\nPlease take the time to read the documentation:\n\n* Online - https://github.com/SublimeLinter/SublimeLinter\n* Sublime Text - Select Preferences->Package Settings->SublimeLinter->README\n\n\nIMPORTANT\n\nDo NOT edit the default SublimeLinter settings. Your changes will be lost\nwhen SublimeLinter is updated. ALWAYS edit the user SublimeLinter settings\nby selecting \"Preferences->Package Settings->SublimeLinter->Settings - User\".\nNote that individual settings you include in your user settings will **completely**\nreplace the corresponding default setting, so you must provide that setting in its entirety.\n"
  },
  {
    "path": "messages.json",
    "content": "{\n    \"install\": \"messages/install.txt\",\n    \"1.5.1\": \"messages/1.5.1.txt\",\n    \"1.5.2\": \"messages/1.5.2.txt\",\n    \"1.5.3\": \"messages/1.5.3.txt\",\n    \"1.5.4\": \"messages/1.5.4.txt\",\n    \"1.5.5\": \"messages/1.5.5.txt\",\n    \"1.5.6\": \"messages/1.5.6.txt\",\n    \"1.5.7\": \"messages/1.5.7.txt\",\n    \"1.6.0\": \"messages/1.6.0.txt\",\n    \"1.6.1\": \"messages/1.6.1.txt\",\n    \"1.6.2\": \"messages/1.6.2.txt\",\n    \"1.6.3\": \"messages/1.6.3.txt\",\n    \"1.6.4\": \"messages/1.6.4.txt\",\n    \"1.6.5\": \"messages/1.6.5.txt\",\n    \"1.6.6\": \"messages/1.6.6.txt\",\n    \"1.6.7\": \"messages/1.6.7.txt\",\n    \"1.6.8\": \"messages/1.6.8.txt\",\n    \"1.6.9\": \"messages/1.6.9.txt\",\n    \"1.6.10\": \"messages/1.6.10.txt\",\n    \"1.6.11\": \"messages/1.6.11.txt\",\n    \"1.6.12\": \"messages/1.6.12.txt\",\n    \"1.6.13\": \"messages/1.6.13.txt\",\n    \"1.7.0\": \"messages/1.7.0.txt\",\n    \"1.7.1\": \"messages/1.7.1.txt\",\n    \"1.7.2\": \"messages/1.7.2.txt\",\n    \"1.7.2+1\": \"messages/SublimeLinter3.txt\",\n    \"1.7.2+3\": \"messages/SublimeLinter3-update1.txt\",\n    \"1.7.2+4\": \"messages/SublimeLinter3-update2.txt\",\n    \"1.7.2+5\": \"messages/SublimeLinter3-update3.txt\"\n}\n"
  },
  {
    "path": "package_control.json",
    "content": "{\n\t\"schema_version\": \"1.1\",\n\t\"packages\": [\n\t\t{\n\t\t\t\"name\": \"SublimeLinter\",\n\t\t\t\"description\": \"Inline lint highlighting for the Sublime Text 2 editor\",\n\t\t\t\"author\": \"Kronuz, Aparajita Fishman, Jake Swartwood\",\n\t\t\t\"homepage\": \"http://github.com/SublimeLinter/SublimeLinter\",\n\t\t\t\"platforms\": {\n\t\t\t\t\"*\": [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"version\": \"1.7.2+4\",\n\t\t\t\t\t\t\"url\": \"https://nodeload.github.com/SublimeLinter/SublimeLinter/zip/v1.7.2+4\"\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"name\": \"SublimeLinter Beta\",\n\t\t\t\"description\": \"This version is considered unstable; only install this package if you plan on testing\",\n\t\t\t\"author\": \"Kronuz, Aparajita Fishman, Jake Swartwood\",\n\t\t\t\"homepage\": \"https://github.com/SublimeLinter/SublimeLinter/tree/beta\",\n\t\t\t\"platforms\": {\n\t\t\t\t\"*\": [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"version\": \"1.7.3-beta.0\",\n\t\t\t\t\t\t\"url\": \"https://nodeload.github.com/SublimeLinter/SublimeLinter/zip/beta\"\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t}\n\t\t}\n\t]\n}\n"
  },
  {
    "path": "sublimelinter/__init__.py",
    "content": ""
  },
  {
    "path": "sublimelinter/loader.py",
    "content": "# Note: Unlike linter modules, changes made to this module will NOT take effect until\n# Sublime Text is restarted.\n\nimport glob\nimport os\nimport os.path\nimport sys\n\nimport modules.base_linter as base_linter\n\n# sys.path appears to ignore individual paths with unicode characters.\n# This means that this lib_path will be ignored for Windows 7 users with\n# non-ascii characters in their username (thus as their home directory).\n#\n# libs_path = os.path.abspath(os.path.join(os.path.dirname(__file__.encode('utf-8')), u'modules', u'libs'))\n#\n# if libs_path not in sys.path:\n#     sys.path.insert(0, libs_path)\n\n# As a fix for the Windows 7 lib path issue (#181), the individual modules in\n# the `libs` folder can be explicitly imported. This obviously doesn't scale\n# well, but may be a necessary evil until ST2 upgrades its internal Python.\n#\ntmpdir = os.getcwdu()\nos.chdir(os.path.abspath(os.path.join(os.path.dirname(__file__.encode('utf-8')), u'modules', u'libs')))\n\nfor mod in [u'capp_lint', u'pep8', u'pyflakes', u'pyflakes.api', u'pyflakes.checker', u'pyflakes.messages', u'pyflakes.reporter']:\n    __import__(mod)\n    print u'imported {0}'.format(mod)\n\nos.chdir(tmpdir)\n\n\nclass Loader(object):\n    '''utility class to load (and reload if necessary) SublimeLinter modules'''\n    def __init__(self, basedir, linters):\n        '''assign relevant variables and load all existing linter modules'''\n        self.basedir = basedir\n        self.basepath = u'sublimelinter/modules'\n        self.linters = linters\n        self.modpath = self.basepath.replace('/', u'.')\n        self.ignored = ('__init__', 'base_linter')\n        self.fix_path()\n        self.load_all()\n\n    def fix_path(self):\n        if os.name != 'posix':\n            return\n\n        path = os.environ['PATH'].encode('utf-8')\n        home_path = os.path.join(os.path.expanduser(u'~'), u'bin')\n\n        if path:\n            dirs = path.encode('utf-8').split(':')\n\n            if u'/usr/local/bin' not in dirs:\n                dirs.insert(0, u'/usr/local/bin')\n\n            if home_path not in dirs:\n                dirs.append(home_path)\n\n            os.environ['PATH'] = u':'.join(dirs)\n\n    def load_all(self):\n        '''loads all existing linter modules'''\n        for modf in glob.glob(u'{0}/*.py'.format(self.basepath)):\n            base, name = os.path.split(modf)\n            name = name.split('.', 1)[0]\n\n            if name in self.ignored:\n                continue\n\n            self.load_module(name)\n\n    def load_module(self, name):\n        '''loads a single linter module'''\n        fullmod = u'{0}.{1}'.format(self.modpath, name)\n\n        # make sure the path didn't change on us (this is needed for submodule reload)\n        pushd = os.getcwdu()\n        os.chdir(self.basedir)\n\n        __import__(fullmod)\n\n        # this following line of code does two things:\n        # first, we get the actual module from sys.modules,\n        #    not the base mod returned by __import__\n        # second, we get an updated version with reload()\n        #    so module development is easier\n        # (to make sublime text reload language submodule,\n        #  just save sublimelinter_plugin.py )\n        mod = sys.modules[fullmod] = reload(sys.modules[fullmod])\n\n        # update module's __file__ to absolute path so we can reload it\n        # if saved with sublime text\n        mod.__file__ = os.path.abspath(mod.__file__.encode('utf-8')).rstrip('co')\n\n        language = ''\n\n        try:\n            config = base_linter.CONFIG.copy()\n\n            try:\n                config.update(mod.CONFIG)\n                language = config['language']\n            except (AttributeError, KeyError):\n                pass\n\n            if language:\n                if hasattr(mod, 'Linter'):\n                    linter = mod.Linter(config)\n                else:\n                    linter = base_linter.BaseLinter(config)\n\n                lc_language = language.lower()\n                self.linters[lc_language] = linter\n                print u'SublimeLinter: {0} loaded'.format(language)\n            else:\n                print u'SublimeLinter: {0} disabled (no language specified in module)'.format(name)\n\n        except KeyError:\n            print u'SublimeLinter: general error importing {0} ({1})'.format(name, language or '<unknown>')\n\n        os.chdir(pushd)\n\n    def reload_module(self, module):\n        '''reload a single linter module\n           This method is meant to be used when editing a given\n           linter module so that changes can be viewed immediately\n           upon saving without having to restart Sublime Text'''\n        fullmod = module.__name__\n\n        if not fullmod.startswith(self.modpath):\n            return\n\n        name = fullmod.replace(self.modpath + '.', '', 1)\n        self.load_module(name)\n"
  },
  {
    "path": "sublimelinter/modules/__init__.py",
    "content": ""
  },
  {
    "path": "sublimelinter/modules/base_linter.py",
    "content": "# base_linter.py - base class for linters\n\nimport os\nimport os.path\nimport json\nimport re\nimport subprocess\n\nimport sublime\n\n# If the linter uses an executable that takes stdin, use this input method.\nINPUT_METHOD_STDIN = 1\n\n# If the linter uses an executable that does not take stdin but you wish to use\n# a temp file so that the current view can be linted interactively, use this input method.\n# If the current view has been saved, the tempfile will have the same name as the\n# view's file, which is necessary for some linters.\nINPUT_METHOD_TEMP_FILE = 2\n\n# If the linter uses an executable that does not take stdin and you wish to have\n# linting occur only on file load and save, use this input method.\nINPUT_METHOD_FILE = 3\n\nCONFIG = {\n    # The display language name for this linter.\n    'language': '',\n\n    # Linters may either use built in code or use an external executable. This item may have\n    # one of the following values:\n    #\n    #   string - An external command (or path to a command) to execute\n    #   None - The linter is considered to be built in\n    #\n    # Alternately, your linter class may define the method get_executable(),\n    # which should return the three-tuple (<enabled>, <executable>, <message>):\n    #   <enabled> must be a boolean than indicates whether the executable is available and usable.\n    #   If <enabled> is True, <executable> must be one of:\n    #       - A command string (or path to a command) if an external executable will be used\n    #       - None if built in code will be used\n    #       - False if no suitable executable can be found or the linter should be disabled\n    #         for some other reason.\n    #   <message> is the message that will be shown in the console when the linter is\n    #   loaded, to aid the user in knowing what the status of the linter is. If None or an empty string,\n    #   a default message will be returned based on the value of <executable>. Otherwise it\n    #   must be a string.\n    'executable': None,\n\n    # If an external executable is being used, this item specifies the arguments\n    # used when checking the existence of the executable to determine if the linter can be enabled.\n    # If more than one argument needs to be passed, use a tuple/list.\n    # Defaults to '-v' if this item is missing.\n    'test_existence_args': '-v',\n\n    # If an external executable is being used, this item specifies the arguments to be passed\n    # when linting. If there is more than one argument, use a tuple/list.\n    # If the input method is anything other than INPUT_METHOD_STDIN, put a {filename} placeholder in\n    # the args where the filename should go.\n    #\n    # Alternately, if your linter class may define the method get_lint_args(), which should return\n    # None for no arguments or a tuple/list for one or more arguments.\n    'lint_args': None,\n\n    # If an external executable is being used, the method used to pass input to it. Defaults to STDIN.\n    'input_method': INPUT_METHOD_STDIN\n}\n\nTEMPFILES_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__.encode('utf-8')), u'..', u'.tempfiles'))\n\nJSON_MULTILINE_COMMENT_RE = re.compile(r'\\/\\*[\\s\\S]*?\\*\\/')\nJSON_SINGLELINE_COMMENT_RE = re.compile(r'\\/\\/[^\\n\\r]*')\n\nif not os.path.exists(TEMPFILES_DIR):\n    os.mkdir(TEMPFILES_DIR)\n\n\nclass BaseLinter(object):\n    '''A base class for linters. Your linter module needs to do the following:\n\n            - Set the relevant values in CONFIG\n            - Override built_in_check() if it uses a built in linter. You may return\n              whatever value you want, this value will be passed to parse_errors().\n            - Override parse_errors() and populate the relevant lists/dicts. The errors\n              argument passed to parse_errors() is the output of the executable run through strip().\n\n       If you do subclass and override __init__, be sure to call super(MyLinter, self).__init__(config).\n    '''\n\n    JSC_PATH = '/System/Library/Frameworks/JavaScriptCore.framework/Versions/A/Resources/jsc'\n\n    LIB_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__.encode('utf-8')), u'libs'))\n\n    JAVASCRIPT_ENGINES = ['node', 'jsc']\n    JAVASCRIPT_ENGINE_NAMES = {'node': 'node.js', 'jsc': 'JavaScriptCore'}\n    JAVASCRIPT_ENGINE_WRAPPERS_PATH = os.path.join(LIB_PATH, 'jsengines')\n\n    def __init__(self, config):\n        self.language = config['language']\n        self.enabled = False\n        self.executable = config.get('executable', None)\n        self.test_existence_args = config.get('test_existence_args', ['-v'])\n        self.js_engine = None\n\n        if isinstance(self.test_existence_args, basestring):\n            self.test_existence_args = (self.test_existence_args,)\n\n        self.input_method = config.get('input_method', INPUT_METHOD_STDIN)\n        self.filename = None\n        self.lint_args = config.get('lint_args', [])\n\n        if isinstance(self.lint_args, basestring):\n            self.lint_args = [self.lint_args]\n\n    def check_enabled(self, view):\n        if hasattr(self, 'get_executable'):\n            try:\n                self.enabled, self.executable, message = self.get_executable(view)\n\n                if self.enabled and not message:\n                    message = 'using \"{0}\"'.format(self.executable) if self.executable else 'built in'\n            except Exception as ex:\n                self.enabled = False\n                message = unicode(ex)\n        else:\n            self.enabled, message = self._check_enabled(view)\n\n        return (self.enabled, message or '<unknown reason>')\n\n    def _check_enabled(self, view):\n        if self.executable is None:\n            return (True, 'built in')\n        elif isinstance(self.executable, basestring):\n            self.executable = self.get_mapped_executable(view, self.executable)\n        elif isinstance(self.executable, bool) and self.executable is False:\n            return (False, 'unknown error')\n        else:\n            return (False, 'bad type for CONFIG[\"executable\"]')\n\n        # If we get this far, the executable is external. Test that it can be executed\n        # and capture stdout and stderr so they don't end up in the system log.\n        try:\n            args = [self.executable]\n            args.extend(self.test_existence_args)\n            subprocess.Popen(args, startupinfo=self.get_startupinfo(),\n                             stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate()\n        except OSError:\n            return (False, '\"{0}\" cannot be found'.format(self.executable))\n\n        return (True, 'using \"{0}\" for executable'.format(self.executable))\n\n    def _get_lint_args(self, view, code, filename):\n        if hasattr(self, 'get_lint_args'):\n            return self.get_lint_args(view, code, filename) or []\n        else:\n            lintArgs = self.lint_args or []\n            settings = view.settings().get('SublimeLinter', {}).get(self.language, {})\n\n            if settings:\n                if 'lint_args' in settings:\n                    lintArgs = settings['lint_args']\n\n                cwd = settings.get('working_directory', '').encode('utf-8')\n\n                if cwd and os.path.isabs(cwd) and os.path.isdir(cwd):\n                    os.chdir(cwd)\n\n            return [arg.format(filename=filename) for arg in lintArgs]\n\n    def built_in_check(self, view, code, filename):\n        return ''\n\n    def executable_check(self, view, code, filename):\n        args = [self.executable]\n        tempfilePath = None\n\n        if self.input_method == INPUT_METHOD_STDIN:\n            args.extend(self._get_lint_args(view, code, filename))\n\n        elif self.input_method == INPUT_METHOD_TEMP_FILE:\n            if filename:\n                filename = os.path.basename(filename)\n            else:\n                filename = u'view{0}'.format(view.id())\n\n            tempfilePath = os.path.join(TEMPFILES_DIR, filename)\n\n            with open(tempfilePath, 'w') as f:\n                f.write(code)\n\n            args.extend(self._get_lint_args(view, code, tempfilePath))\n            code = u''\n\n        elif self.input_method == INPUT_METHOD_FILE:\n            args.extend(self._get_lint_args(view, code, filename))\n            code = u''\n\n        else:\n            return u''\n\n        try:\n            process = subprocess.Popen(args,\n                                       stdin=subprocess.PIPE,\n                                       stdout=subprocess.PIPE,\n                                       stderr=subprocess.STDOUT,\n                                       startupinfo=self.get_startupinfo())\n            process.stdin.write(code)\n            result = process.communicate()[0]\n        finally:\n            if tempfilePath:\n                os.remove(tempfilePath)\n\n        return result.strip()\n\n    def parse_errors(self, view, errors, lines, errorUnderlines, violationUnderlines, warningUnderlines, errorMessages, violationMessages, warningMessages):\n        pass\n\n    def add_message(self, lineno, lines, message, messages):\n        # Assume lineno is one-based, ST2 wants zero-based line numbers\n        lineno -= 1\n        lines.add(lineno)\n        message = message[0].upper() + message[1:]\n\n        # Remove trailing period from error message\n        if message[-1] == '.':\n            message = message[:-1]\n\n        if lineno in messages:\n            messages[lineno].append(message)\n        else:\n            messages[lineno] = [message]\n\n    def underline_range(self, view, lineno, position, underlines, length=1):\n        # Assume lineno is one-based, ST2 wants zero-based line numbers\n        lineno -= 1\n        line = view.full_line(view.text_point(lineno, 0))\n        position += line.begin()\n\n        for i in xrange(length):\n            underlines.append(sublime.Region(position + i))\n\n    def underline_regex(self, view, lineno, regex, lines, underlines, wordmatch=None, linematch=None):\n        # Assume lineno is one-based, ST2 wants zero-based line numbers\n        lineno -= 1\n        lines.add(lineno)\n        offset = 0\n        line = view.full_line(view.text_point(lineno, 0))\n        lineText = view.substr(line)\n\n        if linematch:\n            match = re.match(linematch, lineText)\n\n            if match:\n                lineText = match.group('match')\n                offset = match.start('match')\n            else:\n                return\n\n        iters = re.finditer(regex, lineText)\n        results = [(result.start('underline'), result.end('underline')) for result in iters if not wordmatch or result.group('underline') == wordmatch]\n\n        # Make the lineno one-based again for underline_range\n        lineno += 1\n\n        for start, end in results:\n            self.underline_range(view, lineno, start + offset, underlines, end - start)\n\n    def underline_word(self, view, lineno, position, underlines):\n        # Assume lineno is one-based, ST2 wants zero-based line numbers\n        lineno -= 1\n        line = view.full_line(view.text_point(lineno, 0))\n        position += line.begin()\n\n        word = view.word(position)\n        underlines.append(word)\n\n    def run(self, view, code, filename=None):\n        self.filename = filename\n\n        if self.executable is None:\n            errors = self.built_in_check(view, code, filename)\n        else:\n            errors = self.executable_check(view, code, filename)\n\n        lines = set()\n        errorUnderlines = []  # leave this here for compatibility with original plugin\n        errorMessages = {}\n        violationUnderlines = []\n        violationMessages = {}\n        warningUnderlines = []\n        warningMessages = {}\n\n        self.parse_errors(view, errors, lines, errorUnderlines, violationUnderlines, warningUnderlines, errorMessages, violationMessages, warningMessages)\n        return lines, errorUnderlines, violationUnderlines, warningUnderlines, errorMessages, violationMessages, warningMessages\n\n    def get_mapped_executable(self, view, default):\n        map = view.settings().get('sublimelinter_executable_map')\n\n        if map:\n            lang = self.language.lower()\n\n            if lang in map:\n                return map[lang].encode('utf-8')\n\n        return default\n\n    def get_startupinfo(self):\n        info = None\n\n        if os.name == 'nt':\n            info = subprocess.STARTUPINFO()\n            info.dwFlags |= subprocess.STARTF_USESHOWWINDOW\n            info.wShowWindow = subprocess.SW_HIDE\n\n        return info\n\n    def execute_get_output(self, args):\n        try:\n            return subprocess.Popen(args, self.get_startupinfo()).communicate()[0]\n        except:\n            return ''\n\n    def jsc_path(self):\n        '''Return the path to JavaScriptCore. Use this method in case the path\n           has to be dynamically calculated in the future.'''\n        return self.JSC_PATH\n\n    def find_file(self, filename, view):\n        '''Find a file with the given name, starting in the view's directory,\n           then ascending the file hierarchy up to root.'''\n        path = (view.file_name() or '').encode('utf-8')\n\n        # quit if the view is temporary\n        if not path:\n            return None\n\n        dirname = os.path.dirname(path)\n\n        while True:\n            path = os.path.join(dirname, filename)\n\n            if os.path.isfile(path):\n                with open(path, 'r') as f:\n                    return f.read()\n\n            # if we hit root, quit\n            parent = os.path.dirname(dirname)\n\n            if parent == dirname:\n                return None\n            else:\n                dirname = parent\n\n    def strip_json_comments(self, json_str):\n        stripped_json = JSON_MULTILINE_COMMENT_RE.sub('', json_str)\n        stripped_json = JSON_SINGLELINE_COMMENT_RE.sub('', stripped_json)\n        return json.dumps(json.loads(stripped_json))\n\n    def get_javascript_args(self, view, linter, code):\n        path = os.path.join(self.LIB_PATH, linter)\n        options = self.get_javascript_options(view)\n\n        if options is None:\n            options = json.dumps(view.settings().get('%s_options' % linter) or {})\n\n        self.get_javascript_engine(view)\n        engine = self.js_engine\n\n        if (engine['name'] == 'jsc'):\n            args = [engine['wrapper'], '--', path + os.path.sep, str(code.count('\\n')), options]\n        else:\n            args = [engine['wrapper'], path + os.path.sep, options]\n\n        return args\n\n    def get_javascript_options(self, view):\n        '''Subclasses should override this if they want to provide options\n           for a JavaScript-based linter. If the subclass cannot provide\n           options, it should return None (or not return anything).'''\n        return None\n\n    def get_javascript_engine(self, view):\n        if self.js_engine is None:\n            for engine in self.JAVASCRIPT_ENGINES:\n                if engine == 'node':\n                    try:\n                        path = self.get_mapped_executable(view, 'node')\n                        subprocess.call([path, u'-v'], startupinfo=self.get_startupinfo())\n                        self.js_engine = {\n                            'name': engine,\n                            'path': path,\n                            'wrapper': os.path.join(self.JAVASCRIPT_ENGINE_WRAPPERS_PATH, engine + '.js'),\n                        }\n                        break\n                    except OSError:\n                        pass\n\n                elif engine == 'jsc':\n                    if os.path.exists(self.jsc_path()):\n                        self.js_engine = {\n                            'name': engine,\n                            'path': self.jsc_path(),\n                            'wrapper': os.path.join(self.JAVASCRIPT_ENGINE_WRAPPERS_PATH, engine + '.js'),\n                        }\n                        break\n\n        if self.js_engine is not None:\n            return (True, self.js_engine['path'], 'using {0}'.format(self.JAVASCRIPT_ENGINE_NAMES[self.js_engine['name']]))\n\n        # Didn't find an engine, tell the user\n        engine_list = ', '.join(self.JAVASCRIPT_ENGINE_NAMES.values())\n        return (False, '', 'One of the following JavaScript engines must be installed: ' + engine_list)\n"
  },
  {
    "path": "sublimelinter/modules/c.py",
    "content": "import re\n\nfrom base_linter import BaseLinter, INPUT_METHOD_TEMP_FILE\n\nCONFIG = {\n    'language': 'C',\n    'executable': 'cppcheck',\n    'lint_args': ['--enable=style', '--quiet', '{filename}'],\n    'input_method': INPUT_METHOD_TEMP_FILE\n}\n\n\nclass Linter(BaseLinter):\n    CPPCHECK_RE = re.compile(r'\\[.+?:(\\d+?)\\](.+)')\n\n    def __init__(self, config):\n        super(Linter, self).__init__(config)\n\n    def parse_errors(self, view, errors, lines, errorUnderlines,\n                     violationUnderlines, warningUnderlines,\n                     errorMessages, violationMessages,\n                     warningMessages):\n        # Go through each line in the output of cppcheck\n        for line in errors.splitlines():\n            match = self.CPPCHECK_RE.match(line)\n            if match:\n                # The regular expression matches the line number and\n                # the message as its two groups.\n                lineno, message = match.group(1), match.group(2)\n                # Remove the colon at the beginning of the message\n                if len(message) > 0 and message[0] == ':':\n                    message = message[1:].strip()\n                lineno = int(lineno)\n                self.add_message(lineno, lines, message, errorMessages)\n"
  },
  {
    "path": "sublimelinter/modules/c_cpplint.py",
    "content": "import re\n\nfrom base_linter import BaseLinter\n\nCONFIG = {\n    'language': 'c_cpplint',\n    'executable': 'cpplint.py',\n    'test_existence_args': ['--help'],\n    'lint_args': '-',\n}\n\n\nclass Linter(BaseLinter):\n    def parse_errors(self, view, errors, lines, errorUnderlines, violationUnderlines, warningUnderlines, errorMessages, violationMessages, warningMessages):\n        for line in errors.splitlines():\n            match = re.match(r'^.+:(?P<line>\\d+):\\s+(?P<error>.+)', line)\n\n            if match:\n                error, line = match.group('error'), match.group('line')\n                self.add_message(int(line), lines, error, errorMessages)\n"
  },
  {
    "path": "sublimelinter/modules/coffeescript.py",
    "content": "import re\nimport os\n\nfrom base_linter import BaseLinter\n\nCONFIG = {\n    'language': 'CoffeeScript',\n    'executable': 'coffee.cmd' if os.name == 'nt' else 'coffee',\n    'lint_args': ['-s', '-l']\n}\n\n\nclass Linter(BaseLinter):\n    def parse_errors(self, view, errors, lines, errorUnderlines,\n                     violationUnderlines, warningUnderlines, errorMessages,\n                     violationMessages, warningMessages):\n\n        for line in errors.splitlines():\n            match = re.match(r'.*?Error: Parse error on line '\n                             r'(?P<line>\\d+): (?P<error>.+)', line)\n            if not match:\n                match = re.match(r'.*?Error: (?P<error>.+) '\n                                 r'on line (?P<line>\\d+)', line)\n            if not match:\n                match = re.match(r'[^:]+:(?P<line>\\d+):\\d+: '\n                                 r'error: (?P<error>.+)', line)\n\n            if match:\n                line, error = match.group('line'), match.group('error')\n                self.add_message(int(line), lines, error, errorMessages)\n"
  },
  {
    "path": "sublimelinter/modules/css.py",
    "content": "import json\n\nfrom base_linter import BaseLinter\n\nCONFIG = {\n    'language': 'CSS'\n}\n\n\nclass Linter(BaseLinter):\n    def __init__(self, config):\n        super(Linter, self).__init__(config)\n\n    def get_executable(self, view):\n        return self.get_javascript_engine(view)\n\n    def get_lint_args(self, view, code, filename):\n        return self.get_javascript_args(view, 'csslint', code)\n\n    def parse_errors(self, view, errors, lines, errorUnderlines, violationUnderlines, warningUnderlines, errorMessages, violationMessages, warningMessages):\n        try:\n            errors = json.loads(errors.strip() or '[]')\n        except ValueError:\n            raise ValueError(\"Error from csslint: {0}\".format(errors))\n\n        for error in errors:\n            lineno = error['line']\n\n            if error['type'] == 'warning':\n                messages = warningMessages\n                underlines = warningUnderlines\n            else:\n                messages = errorMessages\n                underlines = errorUnderlines\n\n            self.add_message(lineno, lines, error['reason'], messages)\n            self.underline_range(view, lineno, error['character'] - 1, underlines)\n"
  },
  {
    "path": "sublimelinter/modules/git_commit_message.py",
    "content": "from base_linter import BaseLinter\n\n\nCONFIG = {\n    'language': 'Git Commit Message'\n}\n\n\nclass ErrorType:\n    WARNING = 'warning'\n    VIOLATION = 'violation'\n    ERROR = 'error'\n\n\nclass Linter(BaseLinter):\n\n    def built_in_check(self, view, code, filename):\n        lines = code.splitlines()\n        lineno = 0\n        real_lineno = 0\n        first_line_of_message = None\n        first_line_of_body = None\n        errors = []\n\n        for line in lines:\n            real_lineno += 1\n\n            if line.startswith('#'):\n                continue\n\n            if line.startswith('diff --git'):\n                break\n\n            lineno += 1\n\n            if first_line_of_message is None:\n                if line.strip():\n                    first_line_of_message = lineno\n\n                    if len(line) > 68:\n                        errors.append({\n                            'type': ErrorType.ERROR,\n                            'message': 'Subject line must be 68 characters or less (github will truncate).',\n                            'lineno': real_lineno,\n                            'col': 68,\n                        })\n                    elif len(line) > 50:\n                        errors.append({\n                            'type': ErrorType.WARNING,\n                            'message': 'Subject line should be 50 characters or less.',\n                            'lineno': real_lineno,\n                            'col': 50,\n                        })\n                    elif lineno != 1:\n                        errors.append({\n                            'type': ErrorType.ERROR,\n                            'message': 'Subject must be on first line.',\n                            'lineno': real_lineno,\n                        })\n                    elif line[0].upper() != line[0]:\n                        errors.append({\n                            'type': ErrorType.VIOLATION,\n                            'message': 'Subject line should be capitalized.',\n                            'lineno': real_lineno,\n                        })\n            elif first_line_of_body is None:\n                if len(line):\n                    first_line_of_body = lineno\n\n                    if lineno == first_line_of_message + 1:\n                        if len(line):\n                            errors.append({\n                                'message': 'Leave a blank line between the message subject and body.',\n                                'lineno': first_line_of_message + 1,\n                            })\n                    elif lineno > first_line_of_message + 2:\n                        errors.append({\n                            'message': 'Leave exactly 1 blank line between the message subject and body.',\n                            'lineno': real_lineno,\n                        })\n            if first_line_of_body is not None:\n                if len(line) > 72:\n                    errors.append({\n                        'message': 'Lines must not exceed 72 characters.',\n                        'lineno': real_lineno,\n                        'col': 72,\n                    })\n\n        return errors\n\n    def parse_errors(self, view, errors, lines, errorUnderlines, violationUnderlines, warningUnderlines, errorMessages, violationMessages, warningMessages):\n        for error in errors:\n            error_type = error.get('type', ErrorType.ERROR)\n            col = error.get('col', 0)\n\n            messages = {\n                ErrorType.WARNING: warningMessages,\n                ErrorType.VIOLATION: violationMessages,\n                ErrorType.ERROR: errorMessages,\n            }[error_type]\n            underlines = {\n                ErrorType.WARNING: warningUnderlines,\n                ErrorType.VIOLATION: violationUnderlines,\n                ErrorType.ERROR: errorUnderlines,\n            }[error_type]\n\n            self.add_message(error['lineno'], lines, error['message'], messages)\n            self.underline_range(view, error['lineno'], col, underlines, length=1)\n"
  },
  {
    "path": "sublimelinter/modules/haml.py",
    "content": "import re\n\nfrom base_linter import BaseLinter\n\nCONFIG = {\n    'language': 'Ruby Haml',\n    'executable': 'haml',\n    'lint_args': '-c'\n}\n\n\nclass Linter(BaseLinter):\n    def parse_errors(self, view, errors, lines, errorUnderlines, violationUnderlines, warningUnderlines, errorMessages, violationMessages, warningMessages):\n        for line in errors.splitlines():\n            match = re.match(r'^.+(?P<line>\\d+):\\s+(?P<error>.+)', line)\n\n            if match:\n                error, line = match.group('error'), match.group('line')\n                self.add_message(int(line), lines, error, errorMessages)\n"
  },
  {
    "path": "sublimelinter/modules/haskell.py",
    "content": "import re\nfrom base_linter import BaseLinter, INPUT_METHOD_FILE\n\n\nCONFIG = {\n    'language': 'haskell',\n    'executable': 'hlint',\n    'input_method': INPUT_METHOD_FILE,\n    'lint_args': '{filename}'\n}\n\n\nclass Linter(BaseLinter):\n    def parse_errors(self, view, errors, lines, errorUnderlines, violationUnderlines, warningUnderlines, errorMessages, violationMessages, warningMessages):\n        i = 0\n        error_lines = errors.splitlines()\n        while i < len(error_lines):\n            error = re.match(r'^.+:(?P<line>\\d+):(?P<col>\\d+): (?P<error>.+)', error_lines[i])\n\n            if error:\n                message, lineno, col = error.group('error'), int(error.group('line')), int(error.group('col'))\n\n                if error_lines[i + 1] == \"Error message:\":\n                    message = error_lines[i + 2]\n                    i += 2\n\n                lint_error = re.match(r'^(?P<type>Error|Warning): (?P<error>.+)', message)\n\n                if lint_error:\n                    error_type, message = lint_error.group('type'), lint_error.group('error')\n\n                    if error_type == 'Warning':\n                        messages = warningMessages\n                        underlines = warningUnderlines\n                    else:\n                        messages = errorMessages\n                        underlines = errorUnderlines\n\n                self.add_message(lineno, lines, message, messages)\n                self.underline_range(view, lineno, col - 1, underlines)\n\n            i += 1\n"
  },
  {
    "path": "sublimelinter/modules/html.py",
    "content": "# Example error messages\n#\n# line 1 column 1 - Warning: missing <!DOCTYPE> declaration\n# line 200 column 1 - Warning: discarding unexpected </div>\n# line 1 column 1 - Warning: inserting missing 'title' element\n\nimport re\nimport subprocess\n\nfrom base_linter import BaseLinter\n\nCONFIG = {\n    'language': 'HTML',\n    'executable': 'tidy',\n    'lint_args': '-eq'\n}\n\n\nclass Linter(BaseLinter):\n    def get_executable(self, view):\n        try:\n            path = self.get_mapped_executable(view, 'tidy')\n            version_string = subprocess.Popen([path, '-v'], startupinfo=self.get_startupinfo(), stdout=subprocess.PIPE).communicate()[0]\n\n            if u'HTML5' in version_string:\n                return (True, path, 'using tidy for executable')\n\n            return (False, '', 'tidy is not ready for HTML5')\n        except OSError:\n            return (False, '', 'tidy cannot be found')\n\n    def parse_errors(self, view, errors, lines, errorUnderlines, violationUnderlines, warningUnderlines, errorMessages, violationMessages, warningMessages):\n        for line in errors.splitlines():\n            match = re.match(r'^line\\s(?P<line>\\d+)\\scolumn\\s\\d+\\s-\\s(?P<error>.+)', line)\n\n            if match:\n                error, line = match.group('error'), match.group('line')\n                self.add_message(int(line), lines, error, errorMessages)\n"
  },
  {
    "path": "sublimelinter/modules/java.py",
    "content": "import os\nimport os.path\nimport re\n\nfrom base_linter import BaseLinter, INPUT_METHOD_FILE\n\nCONFIG = {\n    'language': 'Java',\n    'executable': 'javac',\n    'test_existence_args': '-version',\n    'input_method': INPUT_METHOD_FILE\n}\n\nERROR_RE = re.compile(r'^(?P<path>.*\\.java):(?P<line>\\d+): (?P<warning>warning: )?(?:\\[\\w+\\] )?(?P<error>.*)')\nMARK_RE = re.compile(r'^(?P<mark>\\s*)\\^$')\n\n\nclass Linter(BaseLinter):\n    def parse_errors(self, view, errors, lines, errorUnderlines,\n                     violationUnderlines, warningUnderlines, errorMessages,\n                     violationMessages, warningMessages):\n        it = iter(errors.splitlines())\n\n        for line in it:\n            match = re.match(ERROR_RE, line)\n\n            if match:\n                path = os.path.abspath(match.group('path'))\n\n                if path != self.filename:\n                    continue\n\n                lineNumber = int(match.group('line'))\n                warning = match.group('warning')\n                error = match.group('error')\n\n                if warning:\n                    messages = warningMessages\n                    underlines = warningUnderlines\n                else:\n                    messages = errorMessages\n                    underlines = errorUnderlines\n\n                # Skip forward until we find the marker\n                position = -1\n\n                while True:\n                    line = it.next()\n                    match = re.match(MARK_RE, line)\n\n                    if match:\n                        position = len(match.group('mark'))\n                        break\n\n                self.add_message(lineNumber, lines, error, messages)\n                self.underline_range(view, lineNumber, position, underlines)\n"
  },
  {
    "path": "sublimelinter/modules/javascript.py",
    "content": "import json\nimport re\nimport subprocess\n\nfrom base_linter import BaseLinter, INPUT_METHOD_TEMP_FILE\n\nCONFIG = {\n    'language': 'JavaScript'\n}\n\n\nclass Linter(BaseLinter):\n    GJSLINT_RE = re.compile(r'Line (?P<line>\\d+),\\s*E:(?P<errnum>\\d+):\\s*(?P<message>.+)')\n\n    def __init__(self, config):\n        super(Linter, self).__init__(config)\n        self.linter = None\n\n    def get_executable(self, view):\n        self.linter = view.settings().get('javascript_linter', 'jshint')\n\n        if (self.linter in ('jshint', 'jslint')):\n            return self.get_javascript_engine(view)\n        elif (self.linter == 'gjslint'):\n            try:\n                path = self.get_mapped_executable(view, 'gjslint')\n                subprocess.call([path, u'--help'], startupinfo=self.get_startupinfo())\n                self.input_method = INPUT_METHOD_TEMP_FILE\n                return (True, path, 'using gjslint')\n            except OSError:\n                return (False, '', 'gjslint cannot be found')\n        else:\n            return (False, '', '\"{0}\" is not a valid javascript linter'.format(self.linter))\n\n    def get_lint_args(self, view, code, filename):\n        if (self.linter == 'gjslint'):\n            args = []\n            gjslint_options = view.settings().get(\"gjslint_options\", [])\n            args.extend(gjslint_options)\n            args.extend([u'--nobeep', filename])\n            return args\n        elif (self.linter in ('jshint', 'jslint')):\n            return self.get_javascript_args(view, self.linter, code)\n        else:\n            return []\n\n    def get_javascript_options(self, view):\n        if self.linter == 'jshint':\n            rc_options = self.find_file('.jshintrc', view)\n\n            if rc_options is not None:\n                rc_options = self.strip_json_comments(rc_options)\n                return json.dumps(json.loads(rc_options))\n\n    def parse_errors(self, view, errors, lines, errorUnderlines, violationUnderlines, warningUnderlines, errorMessages, violationMessages, warningMessages):\n        if (self.linter == 'gjslint'):\n            ignore = view.settings().get('gjslint_ignore', [])\n\n            for line in errors.splitlines():\n                match = self.GJSLINT_RE.match(line)\n\n                if match:\n                    line, errnum, message = match.group('line'), match.group('errnum'), match.group('message')\n\n                    if (int(errnum) not in ignore):\n                        self.add_message(int(line), lines, message, errorMessages)\n\n        elif (self.linter in ('jshint', 'jslint')):\n            try:\n                errors = json.loads(errors.strip() or '[]')\n            except ValueError:\n                raise ValueError(\"Error from {0}: {1}\".format(self.linter, errors))\n\n            for error in errors:\n                lineno = error['line']\n                self.add_message(lineno, lines, error['reason'], errorMessages)\n                self.underline_range(view, lineno, error['character'] - 1, errorUnderlines)\n"
  },
  {
    "path": "sublimelinter/modules/libs/capp_lint.py",
    "content": "#!/usr/bin/env python\n#\n# capp_lint.py - Check Objective-J source code formatting,\n# according to Cappuccino standards:\n#\n# http://cappuccino.org/contribute/coding-style.php\n#\n# Copyright (C) 2011 Aparajita Fishman <aparajita@aparajita.com>\n\n# Permission is hereby granted, free of charge, to any person\n# obtaining a copy of this software and associated documentation files\n# (the \"Software\"), to deal in the Software without restriction,\n# including without limitation the rights to use, copy, modify, merge,\n# publish, distribute, sublicense, and/or sell copies of the Software,\n# and to permit persons to whom the Software is furnished to do so,\n# subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be\n# included in all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n# SOFTWARE.\n\nfrom __future__ import with_statement\nfrom optparse import OptionParser\nfrom string import Template\nimport cgi\nimport cStringIO\nimport os\nimport os.path\nimport re\nimport sys\nimport unittest\n\nEXIT_CODE_SHOW_HTML = 205\nEXIT_CODE_SHOW_TOOLTIP = 206\n\n\ndef exit_show_html(html):\n    sys.stdout.write(html.encode('utf-8'))\n    sys.exit(EXIT_CODE_SHOW_HTML)\n\n\ndef exit_show_tooltip(text):\n    sys.stdout.write(text)\n    sys.exit(EXIT_CODE_SHOW_TOOLTIP)\n\n\ndef within_textmate():\n    return os.getenv('TM_APP_PATH') is not None\n\n\ndef tabs2spaces(text, positions=None):\n    while True:\n        index = text.find(u'\\t')\n\n        if index < 0:\n            return text\n\n        spaces = u' ' * (4 - (index % 4))\n        text = text[0:index] + spaces + text[index + 1:]\n\n        if positions is not None:\n            positions.append(index)\n\n\ndef relative_path(basedir, filename):\n    if filename.find(basedir) == 0:\n        filename = filename[len(basedir) + 1:]\n\n    return filename\n\n\ndef string_replacer(line):\n    \"\"\"Take string literals like 'hello' and replace them with empty string literals, while respecting escaping.\"\"\"\n\n    r = []\n    in_quote = None\n    escapes = 0\n    for i, c in enumerate(line):\n        if in_quote:\n            if not escapes and c == in_quote:\n                in_quote = None\n                r.append(c)\n                continue\n\n            # We're inside of a string literal. Ignore everything.\n        else:\n            if not escapes and (c == '\"' or c == \"'\"):\n                in_quote = c\n                r.append(c)\n                continue\n\n            # Outside of a string literal, preserve everything.\n            r.append(c)\n\n        if c == '\\\\':\n            escapes = (escapes + 1) % 2\n        else:\n            escapes = 0\n\n    if in_quote:\n        # Unterminated string literal.\n        pass\n    return \"\".join(r)\n\n\nclass LintChecker(object):\n    \"\"\"Examine Objective-J code statically and generate warnings for possible errors and deviations from the coding-style standard.\n\n    >>> LintChecker().lint_text('var b = 5+5;')\n    [{'positions': [9], 'filename': '<stdin>', 'lineNum': 1, 'message': 'binary operator without surrounding spaces', 'type': 2, 'line': u'var b = 5+5;'}]\n\n    >>> LintChecker().lint_text('''\n    ... if( 1 ) {\n    ...   var b=7;\n    ...       c = 8;\n    ... }\n    ... ''')\n    [{'positions': [2], 'filename': '<stdin>', 'lineNum': 2, 'message': 'missing space between control statement and parentheses', 'type': 2, 'line': u'if( 1 ) {'}, {'positions': [8], 'filename': '<stdin>', 'lineNum': 2, 'message': 'braces should be on their own line', 'type': 1, 'line': u'if( 1 ) {'}, {'positions': [3, 5], 'filename': '<stdin>', 'lineNum': 2, 'message': 'space inside parentheses', 'type': 1, 'line': u'if( 1 ) {'}, {'positions': [7], 'filename': '<stdin>', 'lineNum': 3, 'message': 'assignment operator without surrounding spaces', 'type': 2, 'line': u'  var b=7;'}, {'lineNum': 4, 'message': 'accidental global variable', 'type': 1, 'line': u'      c = 8;', 'filename': '<stdin>'}]\n    \"\"\"\n\n    VAR_BLOCK_START_RE = re.compile(ur'''(?x)\n        (?P<indent>\\s*)         # indent before a var keyword\n        (?P<var>var\\s+)         # var keyword and whitespace after\n        (?P<identifier>[a-zA-Z_$]\\w*)\\s*\n        (?:\n            (?P<assignment>=)\\s*\n            (?P<expression>.*)\n            |\n            (?P<separator>[,;+\\-/*%^&|=\\\\])\n        )\n    ''')\n\n    SEPARATOR_RE = re.compile(ur'''(?x)\n        (?P<expression>.*)              # Everything up to the line separator\n        (?P<separator>[,;+\\-/*%^&|=\\\\]) # The line separator\n        \\s*                             # Optional whitespace after\n        $                               # End of expression\n    ''')\n\n    INDENTED_EXPRESSION_RE_TEMPLATE = ur'''(?x)\n        [ ]{%d}                 # Placeholder for indent of first identifier that started block\n        (?P<expression>.+)      # Expression\n    '''\n\n    VAR_BLOCK_RE_TEMPLATE = ur'''(?x)\n        [ ]{%d}                 # Placeholder for indent of first identifier that started block\n        (?P<indent>\\s*)         # Capture any further indent\n        (?:\n            (?P<bracket>[\\[\\{].*)\n            |\n            (?P<identifier>[a-zA-Z_$]\\w*)\\s*\n            (?:\n                (?P<assignment>=)\\s*\n                (?P<expression>.*)\n                |\n                (?P<separator>[,;+\\-/*%%^&|=\\\\])\n            )\n            |\n            (?P<indented_expression>.+)\n        )\n    '''\n\n    STATEMENT_RE = re.compile(ur'''(?x)\n        \\s*((continue|do|for|function|if|else|return|switch|while|with)\\b|\\[+\\s*[a-zA-Z_$]\\w*\\s+[a-zA-Z_$]\\w*\\s*[:\\]])\n    ''')\n\n    TRAILING_WHITESPACE_RE = re.compile(ur'^.*(\\s+)$')\n    STRIP_LINE_COMMENT_RE = re.compile(ur'(.*)\\s*(?://.*|/\\*.*\\*/\\s*)$')\n    LINE_COMMENT_RE = re.compile(ur'\\s*(?:/\\*.*\\*/\\s*|//.*)$')\n    COMMENT_RE = re.compile(ur'/\\*.*?\\*/')\n    BLOCK_COMMENT_START_RE = re.compile(ur'\\s*/\\*.*(?!\\*/\\s*)$')\n    BLOCK_COMMENT_END_RE = re.compile(ur'.*?\\*/')\n    METHOD_RE = ur'[-+]\\s*\\([a-zA-Z_$]\\w*\\)\\s*[a-zA-Z_$]\\w*'\n    FUNCTION_RE = re.compile(ur'\\s*function\\s*(?P<name>[a-zA-Z_$]\\w*)?\\(.*\\)\\s*\\{?')\n    RE_RE = re.compile(ur'(?<!\\\\)/.*?[^\\\\]/[gims]*')\n    EMPTY_STRING_LITERAL_FUNCTION = lambda match: match.group(1) + (len(match.group(2)) * ' ') + match.group(1)\n    EMPTY_SELF_STRING_LITERAL_FUNCTION = lambda self, match: match.group(1) + (len(match.group(2)) * ' ') + match.group(1)\n\n    def noncapturing(regex):\n        return ur'(?:%s)' % regex\n\n    def optional(regex):\n        return ur'(?:%s)?' % regex\n\n    DECIMAL_DIGIT_RE = ur'[0-9]'\n    NON_ZERO_DIGIT_RE = ur'[1-9]'\n    DECIMAL_DIGITS_RE = DECIMAL_DIGIT_RE + ur'+'\n    DECIMAL_DIGITS_OPT_RE = optional(DECIMAL_DIGIT_RE + ur'+')\n    EXPONENT_INDICATOR_RE = ur'[eE]'\n    SIGNED_INTEGER_RE = noncapturing(DECIMAL_DIGITS_RE) + ur'|' + noncapturing(ur'\\+' + DECIMAL_DIGITS_RE) + ur'|' + noncapturing('-' + DECIMAL_DIGITS_RE)\n    DECIMAL_INTEGER_LITERAL_RE = ur'0|' + noncapturing(NON_ZERO_DIGIT_RE + DECIMAL_DIGIT_RE + ur'*')\n    EXPONENT_PART_RE = EXPONENT_INDICATOR_RE + noncapturing(SIGNED_INTEGER_RE)\n    EXPONENT_PART_OPT_RE = optional(EXPONENT_PART_RE)\n\n    DECIMAL_LITERAL_RE = re.compile(noncapturing(noncapturing(DECIMAL_INTEGER_LITERAL_RE) + ur'\\.' + DECIMAL_DIGITS_OPT_RE + EXPONENT_PART_OPT_RE) + ur'|\\.' + noncapturing(DECIMAL_DIGITS_RE + EXPONENT_PART_OPT_RE) + ur'|' + noncapturing(noncapturing(DECIMAL_INTEGER_LITERAL_RE) + EXPONENT_PART_OPT_RE))\n\n    ERROR_TYPE_ILLEGAL = 1\n    ERROR_TYPE_WARNING = 2\n\n    # Replace the contents of comments, regex and string literals\n    # with spaces so we don't get false matches within them\n    STD_IGNORES = (\n        {'regex': STRIP_LINE_COMMENT_RE, 'replace': ''},\n        {'function': string_replacer},\n        {'regex': COMMENT_RE, 'replace': ''},\n        {'regex': RE_RE, 'replace': '/ /'},\n    )\n\n    # Convert exponential notation like 1.1e-6 to an arbitrary constant number so that the \"e\" notation doesn't\n    # need to be understood by the regular matchers. Obviously this is limited by the fact that we're regexing\n    # so this will probably catch some things which are not properly decimal literals (parts of strings or\n    # variable names for instance).\n    EXPONENTIAL_TO_SIMPLE = (\n        {'regex': DECIMAL_LITERAL_RE, 'replace': '42'},\n    )\n\n    LINE_CHECKLIST = (\n        {\n            'id': 'tabs',\n            'regex': re.compile(ur'[\\t]'),\n            'error': 'line contains tabs',\n            'type': ERROR_TYPE_ILLEGAL\n        },\n        {\n            'regex': re.compile(ur'([^\\t -~])'),\n            'error': 'line contains non-ASCII characters',\n            'showPositionForGroup': 1,\n            'type': ERROR_TYPE_ILLEGAL,\n            'option': 'sublimelinter_objj_check_ascii',\n            'optionDefault': False\n        },\n        {\n            'regex': re.compile(ur'^\\s*(?:(?:else )?if|for|switch|while|with)(\\()'),\n            'error': 'missing space between control statement and parentheses',\n            'showPositionForGroup': 1,\n            'type': ERROR_TYPE_WARNING\n        },\n        {\n            'regex': re.compile(ur'^\\s*(?:(?:else )?if|for|switch|while|with)\\s*\\(.+\\)\\s*(\\{)\\s*(?://.*|/\\*.*\\*/\\s*)?$'),\n            'error': 'braces should be on their own line',\n            'showPositionForGroup': 1,\n            'type': ERROR_TYPE_ILLEGAL\n        },\n        {\n            'regex': re.compile(ur'^\\s*(?:(?:else )?if|for|switch|while|with)\\s*\\((\\s+)?.+?(\\s+)?\\)\\s*(?:(?:\\{|//.*|/\\*.*\\*/)\\s*)?$'),\n            'error': 'space inside parentheses',\n            'showPositionForGroup': [1, 2],\n            'type': ERROR_TYPE_ILLEGAL\n        },\n        {\n            'regex': re.compile(ur'^\\s*(?:(?:else )?if|for|switch|while|with)\\s*\\(.+\\)\\s*(?:[\\w_]|\\[).+(;)\\s*(?://.*|/\\*.*\\*/\\s*)?$'),\n            'error': 'dependent statements must be on their own line',\n            'showPositionForGroup': 1,\n            'type': ERROR_TYPE_ILLEGAL\n        },\n        {\n            'regex': TRAILING_WHITESPACE_RE,\n            'error': 'trailing whitespace',\n            'showPositionForGroup': 1,\n            'type': ERROR_TYPE_ILLEGAL\n        },\n        {\n            # Filter out @import statements, method declarations, method parameters, unary plus/minus/increment/decrement\n            'filter': {'regex': re.compile(ur'(^@import\\b|^\\s*' + METHOD_RE + '|^\\s*[a-zA-Z_$]\\w*:\\s*\\([a-zA-Z_$][\\w<>]*\\)\\s*\\w+|[a-zA-Z_$]\\w*(\\+\\+|--)|([ -+*/%^&|<>!]=?|&&|\\|\\||<<|>>>|={1,3}|!==?)\\s*[-+][\\w(\\[])'), 'pass': False},\n\n            # Also convert literals like 1.5e+7 to 42 so that the - or + in there is ignored for purposes of this warning.\n            'preprocess': STD_IGNORES + EXPONENTIAL_TO_SIMPLE,\n            'regex': re.compile(ur'(?<=[\\w)\\]\"\\']|([ ]))([-+*/%^]|&&?|\\|\\|?|<<|>>>?)(?=[\\w({\\[\"\\']|(?(1)\\b\\b|[ ]))'),\n            'error': 'binary operator without surrounding spaces',\n            'showPositionForGroup': 2,\n            'type': ERROR_TYPE_WARNING\n        },\n        {\n            # Filter out possible = within @accessors\n            'filter': {'regex': re.compile(ur'^\\s*(?:@outlet\\s+)?[a-zA-Z_$]\\w*\\s+[a-zA-Z_$]\\w*\\s+@accessors\\b'), 'pass': False},\n\n            'preprocess': STD_IGNORES,\n            'regex': re.compile(ur'(?<=[\\w)\\]\"\\']|([ ]))(=|[-+*/%^&|]=|<<=|>>>?=)(?=[\\w({\\[\"\\']|(?(1)\\b\\b|[ ]))'),\n            'error': 'assignment operator without surrounding spaces',\n            'showPositionForGroup': 2,\n            'type': ERROR_TYPE_WARNING\n        },\n        {\n            # Filter out @import statements and @implementation/method declarations\n            'filter': {'regex': re.compile(ur'^(@import\\b|@implementation\\b|\\s*' + METHOD_RE + ')'), 'pass': False},\n\n            'preprocess': STD_IGNORES,\n            'regex': re.compile(ur'(?<=[\\w)\\]\"\\']|([ ]))(===?|!==?|[<>]=?)(?=[\\w({\\[\"\\']|(?(1)\\b\\b|[ ]))'),\n            'error': 'comparison operator without surrounding spaces',\n            'showPositionForGroup': 2,\n            'type': ERROR_TYPE_WARNING\n        },\n        {\n            'regex': re.compile(ur'^(\\s+)' + METHOD_RE + '|^\\s*[-+](\\()[a-zA-Z_$][\\w]*\\)\\s*[a-zA-Z_$]\\w*|^\\s*[-+]\\s*\\([a-zA-Z_$][\\w]*\\)(\\s+)[a-zA-Z_$]\\w*'),\n            'error': 'extra or missing space in a method declaration',\n            'showPositionForGroup': 0,\n            'type': ERROR_TYPE_WARNING\n        },\n        {\n            # Check for brace following a class or method declaration\n            'regex': re.compile(ur'^(?:\\s*[-+]\\s*\\([a-zA-Z_$]\\w*\\)|@implementation)\\s*[a-zA-Z_$][\\w]*.*?\\s*(\\{)\\s*(?:$|//.*$)'),\n            'error': 'braces should be on their own line',\n            'showPositionForGroup': 0,\n            'type': ERROR_TYPE_ILLEGAL\n        },\n        {\n            'regex': re.compile(ur'^\\s*var\\s+[a-zA-Z_$]\\w*\\s*=\\s*function\\s+([a-zA-Z_$]\\w*)\\s*\\('),\n            'error': 'function name is ignored',\n            'showPositionForGroup': 1,\n            'skip': True,\n            'type': ERROR_TYPE_WARNING\n        },\n    )\n\n    VAR_DECLARATIONS = ['none', 'single', 'strict']\n    VAR_DECLARATIONS_NONE = 0\n    VAR_DECLARATIONS_SINGLE = 1\n    VAR_DECLARATIONS_STRICT = 2\n\n    DIRS_TO_SKIP = ('.git', 'Frameworks', 'Build', 'Resources', 'CommonJS', 'Objective-J')\n\n    ERROR_FORMATS = ('text', 'html')\n    TEXT_ERROR_SINGLE_FILE_TEMPLATE = Template(u'$lineNum: $message.\\n+$line\\n')\n    TEXT_ERROR_MULTI_FILE_TEMPLATE = Template(u'$filename:$lineNum: $message.\\n+$line\\n')\n\n    def __init__(self, view=None, basedir='', var_declarations=VAR_DECLARATIONS_SINGLE, verbose=False):\n        self.view = view\n        self.basedir = unicode(basedir, 'utf-8')\n        self.errors = []\n        self.errorFiles = []\n        self.filesToCheck = []\n        self.varDeclarations = var_declarations\n        self.verbose = verbose\n        self.sourcefile = None\n        self.filename = u''\n        self.line = u''\n        self.lineNum = 0\n        self.varIndent = u''\n        self.identifierIndent = u''\n\n        self.fileChecklist = (\n            {'title': 'Check variable blocks', 'action': self.check_var_blocks},\n        )\n\n    def run_line_checks(self):\n        for check in self.LINE_CHECKLIST:\n            option = check.get('option')\n\n            if option:\n                default = check.get('optionDefault', False)\n\n                if self.view and not self.view.settings().get(option, default):\n                    continue\n\n            line = self.line\n            originalLine = line\n            lineFilter = check.get('filter')\n\n            if lineFilter:\n                match = lineFilter['regex'].search(line)\n\n                if (match and not lineFilter['pass']) or (not match and lineFilter['pass']):\n                    continue\n\n            preprocess = check.get('preprocess')\n\n            if preprocess:\n                if not isinstance(preprocess, (list, tuple)):\n                    preprocess = (preprocess,)\n\n                for processor in preprocess:\n                    regex = processor.get('regex')\n\n                    if regex:\n                        line = regex.sub(processor.get('replace', ''), line)\n\n                    fnct = processor.get('function')\n\n                    if fnct:\n                        line = fnct(line)\n\n            regex = check.get('regex')\n\n            if not regex:\n                continue\n\n            match = regex.search(line)\n\n            if not match:\n                continue\n\n            positions = []\n            groups = check.get('showPositionForGroup')\n\n            if (check.get('id') == 'tabs'):\n                line = tabs2spaces(line, positions=positions)\n            elif groups is not None:\n                line = tabs2spaces(line)\n\n                if not isinstance(groups, (list, tuple)):\n                    groups = (groups,)\n\n                for match in regex.finditer(line):\n                    for group in groups:\n                        if group > 0:\n                            start = match.start(group)\n\n                            if start >= 0:\n                                positions.append(start)\n                        else:\n                            # group 0 means show the first non-empty match\n                            for i in range(1, len(match.groups()) + 1):\n                                if match.start(i) >= 0:\n                                    positions.append(match.start(i))\n                                    break\n\n            if positions:\n                self.error(check['error'], line=originalLine, positions=positions, type=check['type'])\n\n    def next_statement(self, expect_line=False, check_line=True):\n        try:\n            while True:\n                raw_line = self.sourcefile.next()\n                # strip EOL\n                if raw_line[-1] == '\\n':  # ... unless this is the last line which might not have a \\n.\n                    raw_line = raw_line[:-1]\n\n                try:\n                    self.line = unicode(raw_line, 'utf-8', 'strict')  # convert to Unicode\n                    self.lineNum += 1\n                except UnicodeDecodeError:\n                    self.line = unicode(raw_line, 'utf-8', 'replace')\n                    self.lineNum += 1\n                    self.error('line contains invalid unicode character(s)', type=self.ERROR_TYPE_ILLEGAL)\n\n                if self.verbose:\n                    print u'%d: %s' % (self.lineNum, tabs2spaces(self.line))\n\n                if check_line:\n                    self.run_line_checks()\n\n                if not self.is_statement():\n                    continue\n\n                return True\n        except StopIteration:\n            if expect_line:\n                self.error('unexpected EOF', type=self.ERROR_TYPE_ILLEGAL)\n            raise\n\n    def is_statement(self):\n        # Skip empty lines\n        if len(self.line.strip()) == 0:\n            return False\n\n        # See if we have a line comment, skip that\n        match = self.LINE_COMMENT_RE.match(self.line)\n\n        if match:\n            return False\n\n        # Match a block comment start next so we can find its end,\n        # otherwise we might get false matches on the contents of the block comment.\n        match = self.BLOCK_COMMENT_START_RE.match(self.line)\n\n        if match:\n            self.block_comment()\n            return False\n\n        return True\n\n    def is_expression(self):\n        match = self.STATEMENT_RE.match(self.line)\n        return match is None\n\n    def strip_comment(self):\n        match = self.STRIP_LINE_COMMENT_RE.match(self.expression)\n\n        if match:\n            self.expression = match.group(1)\n\n    def get_expression(self, lineMatch):\n        groupdict = lineMatch.groupdict()\n\n        self.expression = groupdict.get('expression')\n\n        if self.expression is None:\n            self.expression = groupdict.get('bracket')\n\n        if self.expression is None:\n            self.expression = groupdict.get('indented_expression')\n\n        if self.expression is None:\n            self.expression = ''\n            return\n\n        # Remove all quoted strings from the expression so that we don't\n        # count unmatched pairs inside the strings.\n        self.expression = string_replacer(self.expression)\n\n        self.strip_comment()\n        self.expression = self.expression.strip()\n\n    def block_comment(self):\n        'Find the end of a block comment'\n\n        commentOpenCount = self.line.count('/*')\n        commentOpenCount -= self.line.count('*/')\n\n        # If there is an open comment block, eat it\n        if commentOpenCount:\n            if self.verbose:\n                print u'%d: BLOCK COMMENT START' % self.lineNum\n        else:\n            return\n\n        match = None\n\n        while not match and self.next_statement(expect_line=True, check_line=False):\n            match = self.BLOCK_COMMENT_END_RE.match(self.line)\n\n        if self.verbose:\n            print u'%d: BLOCK COMMENT END' % self.lineNum\n\n    def balance_pairs(self, squareOpenCount, curlyOpenCount, parenOpenCount):\n        # The following lines have to be indented at least as much as the first identifier\n        # after the var keyword at the start of the block.\n        if self.verbose:\n            print \"%d: BALANCE BRACKETS: '['=%d, '{'=%d, '('=%d\" % (self.lineNum, squareOpenCount, curlyOpenCount, parenOpenCount)\n\n        lineRE = re.compile(self.INDENTED_EXPRESSION_RE_TEMPLATE % len(self.identifierIndent))\n\n        while True:\n            # If the expression has open brackets and is terminated, it's an error\n            match = self.SEPARATOR_RE.match(self.expression)\n\n            if match and match.group('separator') == ';':\n                unterminated = []\n\n                if squareOpenCount:\n                    unterminated.append('[')\n\n                if curlyOpenCount:\n                    unterminated.append('{')\n\n                if parenOpenCount:\n                    unterminated.append('(')\n\n                self.error('unbalanced %s' % ' and '.join(unterminated), type=self.ERROR_TYPE_ILLEGAL)\n                return False\n\n            self.next_statement(expect_line=True)\n            match = lineRE.match(self.line)\n\n            if not match:\n                # If it doesn't match, the indent is wrong check the whole line\n                self.error('incorrect indentation')\n                self.expression = self.line\n                self.strip_comment()\n            else:\n                # It matches, extract the expression\n                self.get_expression(match)\n\n            # Update the bracket counts\n            squareOpenCount += self.expression.count('[')\n            squareOpenCount -= self.expression.count(']')\n            curlyOpenCount += self.expression.count('{')\n            curlyOpenCount -= self.expression.count('}')\n            parenOpenCount += self.expression.count('(')\n            parenOpenCount -= self.expression.count(')')\n\n            if squareOpenCount == 0 and curlyOpenCount == 0 and parenOpenCount == 0:\n                if self.verbose:\n                    print u'%d: BRACKETS BALANCED' % self.lineNum\n\n                # The brackets are closed, this line must be separated\n                match = self.SEPARATOR_RE.match(self.expression)\n\n                if not match:\n                    self.error('missing statement separator', type=self.ERROR_TYPE_ILLEGAL)\n                    return False\n\n                return True\n\n    def pairs_balanced(self, lineMatchOrBlockMatch):\n\n        groups = lineMatchOrBlockMatch.groupdict()\n\n        if 'assignment' in groups or 'bracket' in groups:\n            squareOpenCount = self.expression.count('[')\n            squareOpenCount -= self.expression.count(']')\n\n            curlyOpenCount = self.expression.count('{')\n            curlyOpenCount -= self.expression.count('}')\n\n            parenOpenCount = self.expression.count('(')\n            parenOpenCount -= self.expression.count(')')\n\n            if squareOpenCount or curlyOpenCount or parenOpenCount:\n                # If the brackets were not properly closed or the statement was\n                # missing a separator, skip the rest of the var block.\n                if not self.balance_pairs(squareOpenCount, curlyOpenCount, parenOpenCount):\n                    return False\n\n        return True\n\n    def var_block(self, blockMatch):\n        \"\"\"\n        Parse a var block, return a tuple (haveLine, isSingleVar), where haveLine\n        indicates whether self.line is the next line to be parsed.\n        \"\"\"\n\n        # Keep track of whether this var block has multiple declarations\n        isSingleVar = True\n\n        # Keep track of the indent of the var keyword to compare with following lines\n        self.varIndent = blockMatch.group('indent')\n\n        # Keep track of how far the first variable name is indented to make sure\n        # following lines line up with that\n        self.identifierIndent = self.varIndent + blockMatch.group('var')\n\n        # Check the expression to see if we have any open [ or { or /*\n        self.get_expression(blockMatch)\n\n        if not self.pairs_balanced(blockMatch):\n            return (False, False)\n\n        separator = ''\n\n        if self.expression:\n            match = self.SEPARATOR_RE.match(self.expression)\n\n            if not match:\n                self.error('missing statement separator', type=self.ERROR_TYPE_ILLEGAL)\n            else:\n                separator = match.group('separator')\n        elif blockMatch.group('separator'):\n            separator = blockMatch.group('separator')\n\n        # If the block has a semicolon, there should be no more lines in the block\n        blockHasSemicolon = separator == ';'\n\n        # We may not catch an error till after the line that is wrong, so keep\n        # the most recent declaration and its line number.\n        lastBlockLine = self.line\n        lastBlockLineNum = self.lineNum\n\n        # Now construct an RE that will match any lines indented at least as much\n        # as the var keyword that started the block.\n        blockRE = re.compile(self.VAR_BLOCK_RE_TEMPLATE % len(self.identifierIndent))\n\n        while self.next_statement(expect_line=not blockHasSemicolon):\n\n            if not self.is_statement():\n                continue\n\n            # Is the line indented at least as much as the var keyword that started the block?\n            match = blockRE.match(self.line)\n\n            if match:\n                if self.is_expression():\n                    lastBlockLine = self.line\n                    lastBlockLineNum = self.lineNum\n\n                    # If the line is indented farther than the first identifier in the block,\n                    # it is considered a formatting error.\n                    if match.group('indent') and not match.group('indented_expression'):\n                        self.error('incorrect indentation')\n\n                    self.get_expression(match)\n\n                    if not self.pairs_balanced(match):\n                        return (False, isSingleVar)\n\n                    if self.expression:\n                        separatorMatch = self.SEPARATOR_RE.match(self.expression)\n\n                        if separatorMatch is None:\n                            # If the assignment does not have a separator, it's an error\n                            self.error('missing statement separator', type=self.ERROR_TYPE_ILLEGAL)\n                        else:\n                            separator = separatorMatch.group('separator')\n\n                            if blockHasSemicolon:\n                                # If the block already has a semicolon, we have an accidental global declaration\n                                self.error('accidental global variable', type=self.ERROR_TYPE_ILLEGAL)\n                            elif (separator == ';'):\n                                blockHasSemicolon = True\n                    elif match.group('separator'):\n                        separator = match.group('separator')\n\n                    isSingleVar = False\n                else:\n                    # If the line is a control statement of some kind, then it should not be indented this far.\n                    self.error('statement should be outdented from preceding var block')\n                    return (True, False)\n\n            else:\n                # If the line does not match, it is not an assignment or is outdented from the block.\n                # In either case, the block is considered closed. If the most recent separator was not ';',\n                # the block was not properly terminated.\n                if separator != ';':\n                    self.error('unterminated var block', lineNum=lastBlockLineNum, line=lastBlockLine, type=self.ERROR_TYPE_ILLEGAL)\n\n                return (True, isSingleVar)\n\n    def check_var_blocks(self):\n        lastStatementWasVar = False\n        lastVarWasSingle = False\n        haveLine = True\n\n        while True:\n            if not haveLine:\n                haveLine = self.next_statement()\n\n            if not self.is_statement():\n                haveLine = False\n                continue\n\n            match = self.VAR_BLOCK_START_RE.match(self.line)\n\n            if match is None:\n                lastStatementWasVar = False\n                haveLine = False\n                continue\n\n            # It might be a function definition, in which case we continue\n            expression = match.group('expression')\n\n            if expression:\n                functionMatch = self.FUNCTION_RE.match(expression)\n\n                if functionMatch:\n                    lastStatementWasVar = False\n                    haveLine = False\n                    continue\n\n            # Now we have the start of a variable block\n            if self.verbose:\n                print u'%d: VAR BLOCK' % self.lineNum\n\n            varLineNum = self.lineNum\n            varLine = self.line\n\n            haveLine, isSingleVar = self.var_block(match)\n\n            if self.verbose:\n                print u'%d: END VAR BLOCK:' % self.lineNum,\n\n                if isSingleVar:\n                    print u'SINGLE'\n                else:\n                    print u'MULTIPLE'\n\n            if lastStatementWasVar and self.varDeclarations != self.VAR_DECLARATIONS_NONE:\n                if (self.varDeclarations == self.VAR_DECLARATIONS_SINGLE and lastVarWasSingle and isSingleVar) or \\\n                   (self.varDeclarations == self.VAR_DECLARATIONS_STRICT and (lastVarWasSingle or isSingleVar)):\n                    self.error('consecutive var declarations', lineNum=varLineNum, line=varLine)\n\n            lastStatementWasVar = True\n            lastVarWasSingle = isSingleVar\n\n    def run_file_checks(self):\n        for check in self.fileChecklist:\n            self.sourcefile.seek(0)\n            self.lineNum = 0\n\n            if self.verbose:\n                print u'%s: %s' % (check['title'], self.sourcefile.name)\n\n            check['action']()\n\n    def lint(self, filesToCheck):\n        # Recursively walk any directories and eliminate duplicates\n        self.filesToCheck = []\n\n        for filename in filesToCheck:\n            filename = unicode(filename, 'utf-8')\n            fullpath = os.path.join(self.basedir, filename)\n\n            if fullpath not in self.filesToCheck:\n                if os.path.isdir(fullpath):\n                    for root, dirs, files in os.walk(fullpath):\n                        for skipDir in self.DIRS_TO_SKIP:\n                            if skipDir in dirs:\n                                dirs.remove(skipDir)\n\n                        for filename in files:\n                            if not filename.endswith('.j'):\n                                continue\n\n                            fullpath = os.path.join(root, filename)\n\n                            if fullpath not in self.filesToCheck:\n                                self.filesToCheck.append(fullpath)\n                else:\n                    self.filesToCheck.append(fullpath)\n\n        for filename in self.filesToCheck:\n            try:\n                with open(filename) as self.sourcefile:\n                    self.filename = relative_path(self.basedir, filename)\n                    self.run_file_checks()\n\n            except IOError:\n                self.lineNum = 0\n                self.line = None\n                self.error('file not found', type=self.ERROR_TYPE_ILLEGAL)\n\n            except StopIteration:\n                if self.verbose:\n                    print u'EOF\\n'\n                pass\n\n    def lint_text(self, text, filename=\"<stdin>\"):\n        self.filename = filename\n        self.filesToCheck = []\n\n        try:\n            self.sourcefile = cStringIO.StringIO(text)\n            self.run_file_checks()\n        except StopIteration:\n            if self.verbose:\n                print u'EOF\\n'\n            pass\n\n        return self.errors\n\n    def count_files_checked(self):\n        return len(self.filesToCheck)\n\n    def error(self, message, **kwargs):\n        info = {\n            'filename':  self.filename,\n            'message':   message,\n            'type':      kwargs.get('type', self.ERROR_TYPE_WARNING)\n        }\n\n        line = kwargs.get('line', self.line)\n        lineNum = kwargs.get('lineNum', self.lineNum)\n\n        if line and lineNum:\n            info['line'] = tabs2spaces(line)\n            info['lineNum'] = lineNum\n\n        positions = kwargs.get('positions')\n\n        if positions:\n            info['positions'] = positions\n\n        self.errors.append(info)\n\n        if self.filename not in self.errorFiles:\n            self.errorFiles.append(self.filename)\n\n    def has_errors(self):\n        return len(self.errors) != 0\n\n    def print_errors(self, format='text'):\n        if not self.errors:\n            return\n\n        if format == 'text':\n            self.print_text_errors()\n        elif format == 'html':\n            self.print_textmate_html_errors()\n        elif format == 'tooltip':\n            self.print_tooltip_errors()\n\n    def print_text_errors(self):\n        sys.stdout.write('%d error' % len(self.errors))\n\n        if len(self.errors) > 1:\n            sys.stdout.write('s')\n\n        if len(self.filesToCheck) == 1:\n            template = self.TEXT_ERROR_SINGLE_FILE_TEMPLATE\n        else:\n            sys.stdout.write(' in %d files' % len(self.errorFiles))\n            template = self.TEXT_ERROR_MULTI_FILE_TEMPLATE\n\n        sys.stdout.write(':\\n\\n')\n\n        for error in self.errors:\n            if 'lineNum' in error and 'line' in error:\n                sys.stdout.write(template.substitute(error).encode('utf-8'))\n\n                if error.get('positions'):\n                    markers = ' ' * len(error['line'])\n\n                    for position in error['positions']:\n                        markers = markers[:position] + '^' + markers[position + 1:]\n\n                    # Add a space at the beginning of the markers to account for the '+' at the beginning\n                    # of the source line.\n                    sys.stdout.write(' %s\\n' % markers)\n            else:\n                sys.stdout.write('%s: %s.\\n' % (error['filename'], error['message']))\n\n            sys.stdout.write('\\n')\n\n    def print_textmate_html_errors(self):\n        html = \"\"\"\n<html>\n    <head>\n        <title>Cappuccino Lint Report</title>\n        <style type=\"text/css\">\n            body {\n                margin: 0px;\n                padding: 1px;\n            }\n\n            h1 {\n                font: bold 12pt \"Lucida Grande\";\n                color: #333;\n                background-color: #FF7880;\n                margin: 0 0 .5em 0;\n                padding: .25em .5em;\n            }\n\n            p, a {\n                margin: 0px;\n                padding: 0px;\n            }\n\n            p {\n                font: normal 10pt \"Lucida Grande\";\n                color: #000;\n            }\n\n            p.error {\n                background-color: #E2EAFF;\n            }\n\n            p.source {\n                font-family: Consolas, 'Bitstream Vera Sans Mono', Monoco, Courier, sans-serif;\n                white-space: pre;\n                background-color: #fff;\n                padding-bottom: 1em;\n            }\n\n            a {\n                display: block;\n                padding: .25em .5em;\n                text-decoration: none;\n                color: inherit;\n                background-color: inherit;\n            }\n\n            a:hover {\n                background-color: #ddd;\n            }\n\n            em {\n                font-weight: normal;\n                font-style: normal;\n                font-variant: normal;\n                background-color: #FF7880;\n            }\n        </style>\n    </head>\n    <body>\n    \"\"\"\n\n        html += '<h1>Results: %d error' % len(self.errors)\n\n        if len(self.errors) > 1:\n            html += 's'\n\n        if len(self.filesToCheck) > 1:\n            html += ' in %d files' % len(self.errorFiles)\n\n        html += '</h1>'\n\n        for error in self.errors:\n            message = cgi.escape(error['message'])\n\n            if len(self.filesToCheck) > 1:\n                filename = cgi.escape(error['filename']) + ':'\n            else:\n                filename = ''\n\n            html += '<p class=\"error\">'\n\n            if 'line' in error and 'lineNum' in error:\n                filepath = cgi.escape(os.path.join(self.basedir, error['filename']))\n                lineNum = error['lineNum']\n                line = error['line']\n                positions = error.get('positions')\n                firstPos = -1\n                source = ''\n\n                if positions:\n                    firstPos = positions[0] + 1\n                    lastPos = 0\n\n                    for pos in error.get('positions'):\n                        if pos < len(line):\n                            charToHighlight = line[pos]\n                        else:\n                            charToHighlight = ''\n\n                        source += '%s<em>%s</em>' % (cgi.escape(line[lastPos:pos]), cgi.escape(charToHighlight))\n                        lastPos = pos + 1\n\n                    if lastPos <= len(line):\n                        source += cgi.escape(line[lastPos:])\n                else:\n                    source = line\n\n                link = '<a href=\"txmt://open/?url=file://%s&line=%d&column=%d\">' % (filepath, lineNum, firstPos)\n\n                if len(self.filesToCheck) > 1:\n                    errorMsg = '%s%d: %s' % (filename, lineNum, message)\n                else:\n                    errorMsg = '%d: %s' % (lineNum, message)\n\n                html += '%(link)s%(errorMsg)s</a></p>\\n<p class=\"source\">%(link)s%(source)s</a></p>\\n' % {'link': link, 'errorMsg': errorMsg, 'source': source}\n            else:\n                html += '%s%s</p>\\n' % (filename, message)\n\n        html += \"\"\"\n    </body>\n</html>\n\"\"\"\n        exit_show_html(html)\n\n\nclass MiscTest(unittest.TestCase):\n    def test_string_replacer(self):\n        self.assertEquals(string_replacer(\"x = 'hello';\"), \"x = '';\")\n        self.assertEquals(string_replacer(\"x = '\\\\' hello';\"), \"x = '';\")\n        self.assertEquals(string_replacer(\"x = '\\\\\\\\';\"), \"x = '';\")\n        self.assertEquals(string_replacer(\"\"\"x = '\"string in string\"';\"\"\"), \"x = '';\")\n\n        self.assertEquals(string_replacer('x = \"hello\";'), 'x = \"\";')\n        self.assertEquals(string_replacer('x = \"\\\\\" hello\";'), 'x = \"\";')\n        self.assertEquals(string_replacer('x = \"\\\\\\\\\";'), 'x = \"\";')\n        self.assertEquals(string_replacer('''x = \"'\";'''), 'x = \"\";')\n\n\nclass LintCheckerTest(unittest.TestCase):\n    def test_exponential_notation(self):\n        \"\"\"Test that exponential notation such as 1.1e-6 doesn't cause a warning about missing whitespace.\"\"\"\n\n        # This should not report \"binary operator without surrounding spaces\".\n        self.assertEquals(LintChecker().lint_text(\"a = 2.1e-6;\"), [])\n        self.assertEquals(LintChecker().lint_text(\"a = 2.1e+6;\"), [])\n        self.assertEquals(LintChecker().lint_text(\"a = 2e-0;\"), [])\n        self.assertEquals(LintChecker().lint_text(\"a = 2e+0;\"), [])\n\n        # But this should.\n        self.assertEquals(LintChecker().lint_text(\"a = 1.1e-6+2e2;\"), [{'positions': [6], 'filename': '<stdin>', 'lineNum': 1, 'message': 'binary operator without surrounding spaces', 'type': 2, 'line': u'a = 1.1e-6+2e2;'}])\n\n    def test_function_types(self):\n        \"\"\"Test that function definitions like function(/*CPString*/key) don't cause warnings about surrounding spaces.\"\"\"\n\n        # This should not report \"binary operator without surrounding spaces\".\n        self.assertEquals(LintChecker().lint_text(\"var resolveMultipleValues = function(/*CPString*/key, /*CPDictionary*/bindings, /*GSBindingOperationKind*/operation)\"), [])\n\n    def test_unary_plus(self):\n        \"\"\"Test that = +<variable>, like in `x = +y;`, doesn't cause a warning.\"\"\"\n\n        # +<variable> converts number in a string to a number.\n        self.assertEquals(LintChecker().lint_text(\"var y = +x;\"), [])\n\n    def test_string_escaping(self):\n        \"\"\"Test that string literals are not parsed as syntax, even when they end with a double backslash.\"\"\"\n\n        self.assertEquals(LintChecker().lint_text('var x = \"(\\\\\\\\\";'), [])\n\n\nif __name__ == '__main__':\n    usage = 'usage: %prog [options] [file ... | -]'\n    parser = OptionParser(usage=usage, version='1.02')\n    parser.add_option('-f', '--format', action='store', type='string', dest='format', default='text', help='the format to use for the report: text (default) or html (HTML in which errors can be clicked on to view in TextMate)')\n    parser.add_option('-b', '--basedir', action='store', type='string', dest='basedir', help='the base directory relative to which filenames are resolved, defaults to the current working directory')\n    parser.add_option('-d', '--var-declarations', action='store', type='string', dest='var_declarations', default='single', help='set the policy for flagging consecutive var declarations (%s)' % ', '.join(LintChecker.VAR_DECLARATIONS))\n    parser.add_option('-v', '--verbose', action='store_true', dest='verbose', default=False, help='show what lint is doing')\n    parser.add_option('-q', '--quiet', action='store_true', dest='quiet', default=False, help='do not display errors, only return an exit code')\n\n    (options, args) = parser.parse_args()\n\n    if options.var_declarations not in LintChecker.VAR_DECLARATIONS:\n        parser.error('--var-declarations must be one of [' + ', '.join(LintChecker.VAR_DECLARATIONS) + ']')\n\n    if options.verbose and options.quiet:\n        parser.error('options -v/--verbose and -q/--quiet are mutually exclusive')\n\n    options.format = options.format.lower()\n\n    if not options.format in LintChecker.ERROR_FORMATS:\n        parser.error('format must be one of ' + '/'.join(LintChecker.ERROR_FORMATS))\n\n    if options.format == 'html' and not within_textmate():\n        parser.error('html format can only be used within TextMate.')\n\n    if options.basedir:\n        basedir = options.basedir\n\n        if basedir[-1] == '/':\n            basedir = basedir[:-1]\n    else:\n        basedir = os.getcwd()\n\n    # We accept a list of filenames (relative to the cwd) either from the command line or from stdin\n    filenames = args\n\n    if args and args[0] == '-':\n        filenames = [name.rstrip() for name in sys.stdin.readlines()]\n\n    if not filenames:\n        print usage.replace('%prog', os.path.basename(sys.argv[0]))\n        sys.exit(0)\n\n    checker = LintChecker(basedir=basedir, view=None, var_declarations=LintChecker.VAR_DECLARATIONS.index(options.var_declarations), verbose=options.verbose)\n    pathsToCheck = []\n\n    for filename in filenames:\n        filename = filename.strip('\"\\'')\n        path = os.path.join(basedir, filename)\n\n        if (os.path.isdir(path) and not path.endswith('Frameworks')) or filename.endswith('.j'):\n            pathsToCheck.append(relative_path(basedir, filename))\n\n    if len(pathsToCheck) == 0:\n        if within_textmate():\n            exit_show_tooltip('No Objective-J files found.')\n\n        sys.exit(0)\n\n    checker.lint(pathsToCheck)\n\n    if checker.has_errors():\n        if not options.quiet:\n            checker.print_errors(options.format)\n\n        sys.exit(1)\n    else:\n        if within_textmate():\n            exit_show_tooltip('Everything looks clean.')\n\n        sys.exit(0)\n"
  },
  {
    "path": "sublimelinter/modules/libs/csslint/csslint-node.js",
    "content": "/*!\nCSSLint\nCopyright (c) 2011 Nicole Sullivan and Nicholas C. Zakas. All rights reserved.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n/* Build time: 17-January-2013 10:55:01 */\n/*!\nParser-Lib\nCopyright (c) 2009-2011 Nicholas C. Zakas. All rights reserved.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n/* Version v0.2.2, Build time: 17-January-2013 10:26:34 */\nvar parserlib = {};\n(function(){\n\n\n/**\n * A generic base to inherit from for any object\n * that needs event handling.\n * @class EventTarget\n * @constructor\n */\nfunction EventTarget(){\n\n    /**\n     * The array of listeners for various events.\n     * @type Object\n     * @property _listeners\n     * @private\n     */\n    this._listeners = {};\n}\n\nEventTarget.prototype = {\n\n    //restore constructor\n    constructor: EventTarget,\n\n    /**\n     * Adds a listener for a given event type.\n     * @param {String} type The type of event to add a listener for.\n     * @param {Function} listener The function to call when the event occurs.\n     * @return {void}\n     * @method addListener\n     */\n    addListener: function(type, listener){\n        if (!this._listeners[type]){\n            this._listeners[type] = [];\n        }\n\n        this._listeners[type].push(listener);\n    },\n\n    /**\n     * Fires an event based on the passed-in object.\n     * @param {Object|String} event An object with at least a 'type' attribute\n     *      or a string indicating the event name.\n     * @return {void}\n     * @method fire\n     */\n    fire: function(event){\n        if (typeof event == \"string\"){\n            event = { type: event };\n        }\n        if (typeof event.target != \"undefined\"){\n            event.target = this;\n        }\n\n        if (typeof event.type == \"undefined\"){\n            throw new Error(\"Event object missing 'type' property.\");\n        }\n\n        if (this._listeners[event.type]){\n\n            //create a copy of the array and use that so listeners can't chane\n            var listeners = this._listeners[event.type].concat();\n            for (var i=0, len=listeners.length; i < len; i++){\n                listeners[i].call(this, event);\n            }\n        }\n    },\n\n    /**\n     * Removes a listener for a given event type.\n     * @param {String} type The type of event to remove a listener from.\n     * @param {Function} listener The function to remove from the event.\n     * @return {void}\n     * @method removeListener\n     */\n    removeListener: function(type, listener){\n        if (this._listeners[type]){\n            var listeners = this._listeners[type];\n            for (var i=0, len=listeners.length; i < len; i++){\n                if (listeners[i] === listener){\n                    listeners.splice(i, 1);\n                    break;\n                }\n            }\n\n\n        }\n    }\n};\n/**\n * Convenient way to read through strings.\n * @namespace parserlib.util\n * @class StringReader\n * @constructor\n * @param {String} text The text to read.\n */\nfunction StringReader(text){\n\n    /**\n     * The input text with line endings normalized.\n     * @property _input\n     * @type String\n     * @private\n     */\n    this._input = text.replace(/\\n\\r?/g, \"\\n\");\n\n\n    /**\n     * The row for the character to be read next.\n     * @property _line\n     * @type int\n     * @private\n     */\n    this._line = 1;\n\n\n    /**\n     * The column for the character to be read next.\n     * @property _col\n     * @type int\n     * @private\n     */\n    this._col = 1;\n\n    /**\n     * The index of the character in the input to be read next.\n     * @property _cursor\n     * @type int\n     * @private\n     */\n    this._cursor = 0;\n}\n\nStringReader.prototype = {\n\n    //restore constructor\n    constructor: StringReader,\n\n    //-------------------------------------------------------------------------\n    // Position info\n    //-------------------------------------------------------------------------\n\n    /**\n     * Returns the column of the character to be read next.\n     * @return {int} The column of the character to be read next.\n     * @method getCol\n     */\n    getCol: function(){\n        return this._col;\n    },\n\n    /**\n     * Returns the row of the character to be read next.\n     * @return {int} The row of the character to be read next.\n     * @method getLine\n     */\n    getLine: function(){\n        return this._line ;\n    },\n\n    /**\n     * Determines if you're at the end of the input.\n     * @return {Boolean} True if there's no more input, false otherwise.\n     * @method eof\n     */\n    eof: function(){\n        return (this._cursor == this._input.length);\n    },\n\n    //-------------------------------------------------------------------------\n    // Basic reading\n    //-------------------------------------------------------------------------\n\n    /**\n     * Reads the next character without advancing the cursor.\n     * @param {int} count How many characters to look ahead (default is 1).\n     * @return {String} The next character or null if there is no next character.\n     * @method peek\n     */\n    peek: function(count){\n        var c = null;\n        count = (typeof count == \"undefined\" ? 1 : count);\n\n        //if we're not at the end of the input...\n        if (this._cursor < this._input.length){\n\n            //get character and increment cursor and column\n            c = this._input.charAt(this._cursor + count - 1);\n        }\n\n        return c;\n    },\n\n    /**\n     * Reads the next character from the input and adjusts the row and column\n     * accordingly.\n     * @return {String} The next character or null if there is no next character.\n     * @method read\n     */\n    read: function(){\n        var c = null;\n\n        //if we're not at the end of the input...\n        if (this._cursor < this._input.length){\n\n            //if the last character was a newline, increment row count\n            //and reset column count\n            if (this._input.charAt(this._cursor) == \"\\n\"){\n                this._line++;\n                this._col=1;\n            } else {\n                this._col++;\n            }\n\n            //get character and increment cursor and column\n            c = this._input.charAt(this._cursor++);\n        }\n\n        return c;\n    },\n\n    //-------------------------------------------------------------------------\n    // Misc\n    //-------------------------------------------------------------------------\n\n    /**\n     * Saves the current location so it can be returned to later.\n     * @method mark\n     * @return {void}\n     */\n    mark: function(){\n        this._bookmark = {\n            cursor: this._cursor,\n            line:   this._line,\n            col:    this._col\n        };\n    },\n\n    reset: function(){\n        if (this._bookmark){\n            this._cursor = this._bookmark.cursor;\n            this._line = this._bookmark.line;\n            this._col = this._bookmark.col;\n            delete this._bookmark;\n        }\n    },\n\n    //-------------------------------------------------------------------------\n    // Advanced reading\n    //-------------------------------------------------------------------------\n\n    /**\n     * Reads up to and including the given string. Throws an error if that\n     * string is not found.\n     * @param {String} pattern The string to read.\n     * @return {String} The string when it is found.\n     * @throws Error when the string pattern is not found.\n     * @method readTo\n     */\n    readTo: function(pattern){\n\n        var buffer = \"\",\n            c;\n\n        /*\n         * First, buffer must be the same length as the pattern.\n         * Then, buffer must end with the pattern or else reach the\n         * end of the input.\n         */\n        while (buffer.length < pattern.length || buffer.lastIndexOf(pattern) != buffer.length - pattern.length){\n            c = this.read();\n            if (c){\n                buffer += c;\n            } else {\n                throw new Error(\"Expected \\\"\" + pattern + \"\\\" at line \" + this._line  + \", col \" + this._col + \".\");\n            }\n        }\n\n        return buffer;\n\n    },\n\n    /**\n     * Reads characters while each character causes the given\n     * filter function to return true. The function is passed\n     * in each character and either returns true to continue\n     * reading or false to stop.\n     * @param {Function} filter The function to read on each character.\n     * @return {String} The string made up of all characters that passed the\n     *      filter check.\n     * @method readWhile\n     */\n    readWhile: function(filter){\n\n        var buffer = \"\",\n            c = this.read();\n\n        while(c !== null && filter(c)){\n            buffer += c;\n            c = this.read();\n        }\n\n        return buffer;\n\n    },\n\n    /**\n     * Reads characters that match either text or a regular expression and\n     * returns those characters. If a match is found, the row and column\n     * are adjusted; if no match is found, the reader's state is unchanged.\n     * reading or false to stop.\n     * @param {String|RegExp} matchter If a string, then the literal string\n     *      value is searched for. If a regular expression, then any string\n     *      matching the pattern is search for.\n     * @return {String} The string made up of all characters that matched or\n     *      null if there was no match.\n     * @method readMatch\n     */\n    readMatch: function(matcher){\n\n        var source = this._input.substring(this._cursor),\n            value = null;\n\n        //if it's a string, just do a straight match\n        if (typeof matcher == \"string\"){\n            if (source.indexOf(matcher) === 0){\n                value = this.readCount(matcher.length);\n            }\n        } else if (matcher instanceof RegExp){\n            if (matcher.test(source)){\n                value = this.readCount(RegExp.lastMatch.length);\n            }\n        }\n\n        return value;\n    },\n\n\n    /**\n     * Reads a given number of characters. If the end of the input is reached,\n     * it reads only the remaining characters and does not throw an error.\n     * @param {int} count The number of characters to read.\n     * @return {String} The string made up the read characters.\n     * @method readCount\n     */\n    readCount: function(count){\n        var buffer = \"\";\n\n        while(count--){\n            buffer += this.read();\n        }\n\n        return buffer;\n    }\n\n};\n/**\n * Type to use when a syntax error occurs.\n * @class SyntaxError\n * @namespace parserlib.util\n * @constructor\n * @param {String} message The error message.\n * @param {int} line The line at which the error occurred.\n * @param {int} col The column at which the error occurred.\n */\nfunction SyntaxError(message, line, col){\n\n    /**\n     * The column at which the error occurred.\n     * @type int\n     * @property col\n     */\n    this.col = col;\n\n    /**\n     * The line at which the error occurred.\n     * @type int\n     * @property line\n     */\n    this.line = line;\n\n    /**\n     * The text representation of the unit.\n     * @type String\n     * @property text\n     */\n    this.message = message;\n\n}\n\n//inherit from Error\nSyntaxError.prototype = new Error();\n/**\n * Base type to represent a single syntactic unit.\n * @class SyntaxUnit\n * @namespace parserlib.util\n * @constructor\n * @param {String} text The text of the unit.\n * @param {int} line The line of text on which the unit resides.\n * @param {int} col The column of text on which the unit resides.\n */\nfunction SyntaxUnit(text, line, col, type){\n\n\n    /**\n     * The column of text on which the unit resides.\n     * @type int\n     * @property col\n     */\n    this.col = col;\n\n    /**\n     * The line of text on which the unit resides.\n     * @type int\n     * @property line\n     */\n    this.line = line;\n\n    /**\n     * The text representation of the unit.\n     * @type String\n     * @property text\n     */\n    this.text = text;\n\n    /**\n     * The type of syntax unit.\n     * @type int\n     * @property type\n     */\n    this.type = type;\n}\n\n/**\n * Create a new syntax unit based solely on the given token.\n * Convenience method for creating a new syntax unit when\n * it represents a single token instead of multiple.\n * @param {Object} token The token object to represent.\n * @return {parserlib.util.SyntaxUnit} The object representing the token.\n * @static\n * @method fromToken\n */\nSyntaxUnit.fromToken = function(token){\n    return new SyntaxUnit(token.value, token.startLine, token.startCol);\n};\n\nSyntaxUnit.prototype = {\n\n    //restore constructor\n    constructor: SyntaxUnit,\n\n    /**\n     * Returns the text representation of the unit.\n     * @return {String} The text representation of the unit.\n     * @method valueOf\n     */\n    valueOf: function(){\n        return this.toString();\n    },\n\n    /**\n     * Returns the text representation of the unit.\n     * @return {String} The text representation of the unit.\n     * @method toString\n     */\n    toString: function(){\n        return this.text;\n    }\n\n};\n/*global StringReader, SyntaxError*/\n\n/**\n * Generic TokenStream providing base functionality.\n * @class TokenStreamBase\n * @namespace parserlib.util\n * @constructor\n * @param {String|StringReader} input The text to tokenize or a reader from\n *      which to read the input.\n */\nfunction TokenStreamBase(input, tokenData){\n\n    /**\n     * The string reader for easy access to the text.\n     * @type StringReader\n     * @property _reader\n     * @private\n     */\n    this._reader = input ? new StringReader(input.toString()) : null;\n\n    /**\n     * Token object for the last consumed token.\n     * @type Token\n     * @property _token\n     * @private\n     */\n    this._token = null;\n\n    /**\n     * The array of token information.\n     * @type Array\n     * @property _tokenData\n     * @private\n     */\n    this._tokenData = tokenData;\n\n    /**\n     * Lookahead token buffer.\n     * @type Array\n     * @property _lt\n     * @private\n     */\n    this._lt = [];\n\n    /**\n     * Lookahead token buffer index.\n     * @type int\n     * @property _ltIndex\n     * @private\n     */\n    this._ltIndex = 0;\n\n    this._ltIndexCache = [];\n}\n\n/**\n * Accepts an array of token information and outputs\n * an array of token data containing key-value mappings\n * and matching functions that the TokenStream needs.\n * @param {Array} tokens An array of token descriptors.\n * @return {Array} An array of processed token data.\n * @method createTokenData\n * @static\n */\nTokenStreamBase.createTokenData = function(tokens){\n\n    var nameMap     = [],\n        typeMap     = {},\n        tokenData     = tokens.concat([]),\n        i            = 0,\n        len            = tokenData.length+1;\n\n    tokenData.UNKNOWN = -1;\n    tokenData.unshift({name:\"EOF\"});\n\n    for (; i < len; i++){\n        nameMap.push(tokenData[i].name);\n        tokenData[tokenData[i].name] = i;\n        if (tokenData[i].text){\n            typeMap[tokenData[i].text] = i;\n        }\n    }\n\n    tokenData.name = function(tt){\n        return nameMap[tt];\n    };\n\n    tokenData.type = function(c){\n        return typeMap[c];\n    };\n\n    return tokenData;\n};\n\nTokenStreamBase.prototype = {\n\n    //restore constructor\n    constructor: TokenStreamBase,\n\n    //-------------------------------------------------------------------------\n    // Matching methods\n    //-------------------------------------------------------------------------\n\n    /**\n     * Determines if the next token matches the given token type.\n     * If so, that token is consumed; if not, the token is placed\n     * back onto the token stream. You can pass in any number of\n     * token types and this will return true if any of the token\n     * types is found.\n     * @param {int|int[]} tokenTypes Either a single token type or an array of\n     *      token types that the next token might be. If an array is passed,\n     *      it's assumed that the token can be any of these.\n     * @param {variant} channel (Optional) The channel to read from. If not\n     *      provided, reads from the default (unnamed) channel.\n     * @return {Boolean} True if the token type matches, false if not.\n     * @method match\n     */\n    match: function(tokenTypes, channel){\n\n        //always convert to an array, makes things easier\n        if (!(tokenTypes instanceof Array)){\n            tokenTypes = [tokenTypes];\n        }\n\n        var tt  = this.get(channel),\n            i   = 0,\n            len = tokenTypes.length;\n\n        while(i < len){\n            if (tt == tokenTypes[i++]){\n                return true;\n            }\n        }\n\n        //no match found, put the token back\n        this.unget();\n        return false;\n    },\n\n    /**\n     * Determines if the next token matches the given token type.\n     * If so, that token is consumed; if not, an error is thrown.\n     * @param {int|int[]} tokenTypes Either a single token type or an array of\n     *      token types that the next token should be. If an array is passed,\n     *      it's assumed that the token must be one of these.\n     * @param {variant} channel (Optional) The channel to read from. If not\n     *      provided, reads from the default (unnamed) channel.\n     * @return {void}\n     * @method mustMatch\n     */\n    mustMatch: function(tokenTypes, channel){\n\n        var token;\n\n        //always convert to an array, makes things easier\n        if (!(tokenTypes instanceof Array)){\n            tokenTypes = [tokenTypes];\n        }\n\n        if (!this.match.apply(this, arguments)){\n            token = this.LT(1);\n            throw new SyntaxError(\"Expected \" + this._tokenData[tokenTypes[0]].name +\n                \" at line \" + token.startLine + \", col \" + token.startCol + \".\", token.startLine, token.startCol);\n        }\n    },\n\n    //-------------------------------------------------------------------------\n    // Consuming methods\n    //-------------------------------------------------------------------------\n\n    /**\n     * Keeps reading from the token stream until either one of the specified\n     * token types is found or until the end of the input is reached.\n     * @param {int|int[]} tokenTypes Either a single token type or an array of\n     *      token types that the next token should be. If an array is passed,\n     *      it's assumed that the token must be one of these.\n     * @param {variant} channel (Optional) The channel to read from. If not\n     *      provided, reads from the default (unnamed) channel.\n     * @return {void}\n     * @method advance\n     */\n    advance: function(tokenTypes, channel){\n\n        while(this.LA(0) !== 0 && !this.match(tokenTypes, channel)){\n            this.get();\n        }\n\n        return this.LA(0);\n    },\n\n    /**\n     * Consumes the next token from the token stream.\n     * @return {int} The token type of the token that was just consumed.\n     * @method get\n     */\n    get: function(channel){\n\n        var tokenInfo   = this._tokenData,\n            reader      = this._reader,\n            value,\n            i           =0,\n            len         = tokenInfo.length,\n            found       = false,\n            token,\n            info;\n\n        //check the lookahead buffer first\n        if (this._lt.length && this._ltIndex >= 0 && this._ltIndex < this._lt.length){\n\n            i++;\n            this._token = this._lt[this._ltIndex++];\n            info = tokenInfo[this._token.type];\n\n            //obey channels logic\n            while((info.channel !== undefined && channel !== info.channel) &&\n                    this._ltIndex < this._lt.length){\n                this._token = this._lt[this._ltIndex++];\n                info = tokenInfo[this._token.type];\n                i++;\n            }\n\n            //here be dragons\n            if ((info.channel === undefined || channel === info.channel) &&\n                    this._ltIndex <= this._lt.length){\n                this._ltIndexCache.push(i);\n                return this._token.type;\n            }\n        }\n\n        //call token retriever method\n        token = this._getToken();\n\n        //if it should be hidden, don't save a token\n        if (token.type > -1 && !tokenInfo[token.type].hide){\n\n            //apply token channel\n            token.channel = tokenInfo[token.type].channel;\n\n            //save for later\n            this._token = token;\n            this._lt.push(token);\n\n            //save space that will be moved (must be done before array is truncated)\n            this._ltIndexCache.push(this._lt.length - this._ltIndex + i);\n\n            //keep the buffer under 5 items\n            if (this._lt.length > 5){\n                this._lt.shift();\n            }\n\n            //also keep the shift buffer under 5 items\n            if (this._ltIndexCache.length > 5){\n                this._ltIndexCache.shift();\n            }\n\n            //update lookahead index\n            this._ltIndex = this._lt.length;\n        }\n\n        /*\n         * Skip to the next token if:\n         * 1. The token type is marked as hidden.\n         * 2. The token type has a channel specified and it isn't the current channel.\n         */\n        info = tokenInfo[token.type];\n        if (info &&\n                (info.hide ||\n                (info.channel !== undefined && channel !== info.channel))){\n            return this.get(channel);\n        } else {\n            //return just the type\n            return token.type;\n        }\n    },\n\n    /**\n     * Looks ahead a certain number of tokens and returns the token type at\n     * that position. This will throw an error if you lookahead past the\n     * end of input, past the size of the lookahead buffer, or back past\n     * the first token in the lookahead buffer.\n     * @param {int} The index of the token type to retrieve. 0 for the\n     *      current token, 1 for the next, -1 for the previous, etc.\n     * @return {int} The token type of the token in the given position.\n     * @method LA\n     */\n    LA: function(index){\n        var total = index,\n            tt;\n        if (index > 0){\n            //TODO: Store 5 somewhere\n            if (index > 5){\n                throw new Error(\"Too much lookahead.\");\n            }\n\n            //get all those tokens\n            while(total){\n                tt = this.get();\n                total--;\n            }\n\n            //unget all those tokens\n            while(total < index){\n                this.unget();\n                total++;\n            }\n        } else if (index < 0){\n\n            if(this._lt[this._ltIndex+index]){\n                tt = this._lt[this._ltIndex+index].type;\n            } else {\n                throw new Error(\"Too much lookbehind.\");\n            }\n\n        } else {\n            tt = this._token.type;\n        }\n\n        return tt;\n\n    },\n\n    /**\n     * Looks ahead a certain number of tokens and returns the token at\n     * that position. This will throw an error if you lookahead past the\n     * end of input, past the size of the lookahead buffer, or back past\n     * the first token in the lookahead buffer.\n     * @param {int} The index of the token type to retrieve. 0 for the\n     *      current token, 1 for the next, -1 for the previous, etc.\n     * @return {Object} The token of the token in the given position.\n     * @method LA\n     */\n    LT: function(index){\n\n        //lookahead first to prime the token buffer\n        this.LA(index);\n\n        //now find the token, subtract one because _ltIndex is already at the next index\n        return this._lt[this._ltIndex+index-1];\n    },\n\n    /**\n     * Returns the token type for the next token in the stream without\n     * consuming it.\n     * @return {int} The token type of the next token in the stream.\n     * @method peek\n     */\n    peek: function(){\n        return this.LA(1);\n    },\n\n    /**\n     * Returns the actual token object for the last consumed token.\n     * @return {Token} The token object for the last consumed token.\n     * @method token\n     */\n    token: function(){\n        return this._token;\n    },\n\n    /**\n     * Returns the name of the token for the given token type.\n     * @param {int} tokenType The type of token to get the name of.\n     * @return {String} The name of the token or \"UNKNOWN_TOKEN\" for any\n     *      invalid token type.\n     * @method tokenName\n     */\n    tokenName: function(tokenType){\n        if (tokenType < 0 || tokenType > this._tokenData.length){\n            return \"UNKNOWN_TOKEN\";\n        } else {\n            return this._tokenData[tokenType].name;\n        }\n    },\n\n    /**\n     * Returns the token type value for the given token name.\n     * @param {String} tokenName The name of the token whose value should be returned.\n     * @return {int} The token type value for the given token name or -1\n     *      for an unknown token.\n     * @method tokenName\n     */\n    tokenType: function(tokenName){\n        return this._tokenData[tokenName] || -1;\n    },\n\n    /**\n     * Returns the last consumed token to the token stream.\n     * @method unget\n     */\n    unget: function(){\n        //if (this._ltIndex > -1){\n        if (this._ltIndexCache.length){\n            this._ltIndex -= this._ltIndexCache.pop();//--;\n            this._token = this._lt[this._ltIndex - 1];\n        } else {\n            throw new Error(\"Too much lookahead.\");\n        }\n    }\n\n};\n\n\n\n\nparserlib.util = {\nStringReader: StringReader,\nSyntaxError : SyntaxError,\nSyntaxUnit  : SyntaxUnit,\nEventTarget : EventTarget,\nTokenStreamBase : TokenStreamBase\n};\n})();\n\n\n/*\nParser-Lib\nCopyright (c) 2009-2011 Nicholas C. Zakas. All rights reserved.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n/* Version v0.2.2, Build time: 17-January-2013 10:26:34 */\n(function(){\nvar EventTarget = parserlib.util.EventTarget,\nTokenStreamBase = parserlib.util.TokenStreamBase,\nStringReader = parserlib.util.StringReader,\nSyntaxError = parserlib.util.SyntaxError,\nSyntaxUnit  = parserlib.util.SyntaxUnit;\n\n\nvar Colors = {\n    aliceblue       :\"#f0f8ff\",\n    antiquewhite    :\"#faebd7\",\n    aqua            :\"#00ffff\",\n    aquamarine      :\"#7fffd4\",\n    azure           :\"#f0ffff\",\n    beige           :\"#f5f5dc\",\n    bisque          :\"#ffe4c4\",\n    black           :\"#000000\",\n    blanchedalmond  :\"#ffebcd\",\n    blue            :\"#0000ff\",\n    blueviolet      :\"#8a2be2\",\n    brown           :\"#a52a2a\",\n    burlywood       :\"#deb887\",\n    cadetblue       :\"#5f9ea0\",\n    chartreuse      :\"#7fff00\",\n    chocolate       :\"#d2691e\",\n    coral           :\"#ff7f50\",\n    cornflowerblue  :\"#6495ed\",\n    cornsilk        :\"#fff8dc\",\n    crimson         :\"#dc143c\",\n    cyan            :\"#00ffff\",\n    darkblue        :\"#00008b\",\n    darkcyan        :\"#008b8b\",\n    darkgoldenrod   :\"#b8860b\",\n    darkgray        :\"#a9a9a9\",\n    darkgreen       :\"#006400\",\n    darkkhaki       :\"#bdb76b\",\n    darkmagenta     :\"#8b008b\",\n    darkolivegreen  :\"#556b2f\",\n    darkorange      :\"#ff8c00\",\n    darkorchid      :\"#9932cc\",\n    darkred         :\"#8b0000\",\n    darksalmon      :\"#e9967a\",\n    darkseagreen    :\"#8fbc8f\",\n    darkslateblue   :\"#483d8b\",\n    darkslategray   :\"#2f4f4f\",\n    darkturquoise   :\"#00ced1\",\n    darkviolet      :\"#9400d3\",\n    deeppink        :\"#ff1493\",\n    deepskyblue     :\"#00bfff\",\n    dimgray         :\"#696969\",\n    dodgerblue      :\"#1e90ff\",\n    firebrick       :\"#b22222\",\n    floralwhite     :\"#fffaf0\",\n    forestgreen     :\"#228b22\",\n    fuchsia         :\"#ff00ff\",\n    gainsboro       :\"#dcdcdc\",\n    ghostwhite      :\"#f8f8ff\",\n    gold            :\"#ffd700\",\n    goldenrod       :\"#daa520\",\n    gray            :\"#808080\",\n    green           :\"#008000\",\n    greenyellow     :\"#adff2f\",\n    honeydew        :\"#f0fff0\",\n    hotpink         :\"#ff69b4\",\n    indianred       :\"#cd5c5c\",\n    indigo          :\"#4b0082\",\n    ivory           :\"#fffff0\",\n    khaki           :\"#f0e68c\",\n    lavender        :\"#e6e6fa\",\n    lavenderblush   :\"#fff0f5\",\n    lawngreen       :\"#7cfc00\",\n    lemonchiffon    :\"#fffacd\",\n    lightblue       :\"#add8e6\",\n    lightcoral      :\"#f08080\",\n    lightcyan       :\"#e0ffff\",\n    lightgoldenrodyellow  :\"#fafad2\",\n    lightgray       :\"#d3d3d3\",\n    lightgreen      :\"#90ee90\",\n    lightpink       :\"#ffb6c1\",\n    lightsalmon     :\"#ffa07a\",\n    lightseagreen   :\"#20b2aa\",\n    lightskyblue    :\"#87cefa\",\n    lightslategray  :\"#778899\",\n    lightsteelblue  :\"#b0c4de\",\n    lightyellow     :\"#ffffe0\",\n    lime            :\"#00ff00\",\n    limegreen       :\"#32cd32\",\n    linen           :\"#faf0e6\",\n    magenta         :\"#ff00ff\",\n    maroon          :\"#800000\",\n    mediumaquamarine:\"#66cdaa\",\n    mediumblue      :\"#0000cd\",\n    mediumorchid    :\"#ba55d3\",\n    mediumpurple    :\"#9370d8\",\n    mediumseagreen  :\"#3cb371\",\n    mediumslateblue :\"#7b68ee\",\n    mediumspringgreen   :\"#00fa9a\",\n    mediumturquoise :\"#48d1cc\",\n    mediumvioletred :\"#c71585\",\n    midnightblue    :\"#191970\",\n    mintcream       :\"#f5fffa\",\n    mistyrose       :\"#ffe4e1\",\n    moccasin        :\"#ffe4b5\",\n    navajowhite     :\"#ffdead\",\n    navy            :\"#000080\",\n    oldlace         :\"#fdf5e6\",\n    olive           :\"#808000\",\n    olivedrab       :\"#6b8e23\",\n    orange          :\"#ffa500\",\n    orangered       :\"#ff4500\",\n    orchid          :\"#da70d6\",\n    palegoldenrod   :\"#eee8aa\",\n    palegreen       :\"#98fb98\",\n    paleturquoise   :\"#afeeee\",\n    palevioletred   :\"#d87093\",\n    papayawhip      :\"#ffefd5\",\n    peachpuff       :\"#ffdab9\",\n    peru            :\"#cd853f\",\n    pink            :\"#ffc0cb\",\n    plum            :\"#dda0dd\",\n    powderblue      :\"#b0e0e6\",\n    purple          :\"#800080\",\n    red             :\"#ff0000\",\n    rosybrown       :\"#bc8f8f\",\n    royalblue       :\"#4169e1\",\n    saddlebrown     :\"#8b4513\",\n    salmon          :\"#fa8072\",\n    sandybrown      :\"#f4a460\",\n    seagreen        :\"#2e8b57\",\n    seashell        :\"#fff5ee\",\n    sienna          :\"#a0522d\",\n    silver          :\"#c0c0c0\",\n    skyblue         :\"#87ceeb\",\n    slateblue       :\"#6a5acd\",\n    slategray       :\"#708090\",\n    snow            :\"#fffafa\",\n    springgreen     :\"#00ff7f\",\n    steelblue       :\"#4682b4\",\n    tan             :\"#d2b48c\",\n    teal            :\"#008080\",\n    thistle         :\"#d8bfd8\",\n    tomato          :\"#ff6347\",\n    turquoise       :\"#40e0d0\",\n    violet          :\"#ee82ee\",\n    wheat           :\"#f5deb3\",\n    white           :\"#ffffff\",\n    whitesmoke      :\"#f5f5f5\",\n    yellow          :\"#ffff00\",\n    yellowgreen     :\"#9acd32\",\n    //CSS2 system colors http://www.w3.org/TR/css3-color/#css2-system\n    activeBorder        :\"Active window border.\",\n    activecaption       :\"Active window caption.\",\n    appworkspace        :\"Background color of multiple document interface.\",\n    background          :\"Desktop background.\",\n    buttonface          :\"The face background color for 3-D elements that appear 3-D due to one layer of surrounding border.\",\n    buttonhighlight     :\"The color of the border facing the light source for 3-D elements that appear 3-D due to one layer of surrounding border.\",\n    buttonshadow        :\"The color of the border away from the light source for 3-D elements that appear 3-D due to one layer of surrounding border.\",\n    buttontext          :\"Text on push buttons.\",\n    captiontext         :\"Text in caption, size box, and scrollbar arrow box.\",\n    graytext            :\"Grayed (disabled) text. This color is set to #000 if the current display driver does not support a solid gray color.\",\n    highlight           :\"Item(s) selected in a control.\",\n    highlighttext       :\"Text of item(s) selected in a control.\",\n    inactiveborder      :\"Inactive window border.\",\n    inactivecaption     :\"Inactive window caption.\",\n    inactivecaptiontext :\"Color of text in an inactive caption.\",\n    infobackground      :\"Background color for tooltip controls.\",\n    infotext            :\"Text color for tooltip controls.\",\n    menu                :\"Menu background.\",\n    menutext            :\"Text in menus.\",\n    scrollbar           :\"Scroll bar gray area.\",\n    threeddarkshadow    :\"The color of the darker (generally outer) of the two borders away from the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.\",\n    threedface          :\"The face background color for 3-D elements that appear 3-D due to two concentric layers of surrounding border.\",\n    threedhighlight     :\"The color of the lighter (generally outer) of the two borders facing the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.\",\n    threedlightshadow   :\"The color of the darker (generally inner) of the two borders facing the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.\",\n    threedshadow        :\"The color of the lighter (generally inner) of the two borders away from the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.\",\n    window              :\"Window background.\",\n    windowframe         :\"Window frame.\",\n    windowtext          :\"Text in windows.\"\n};\n/*global SyntaxUnit, Parser*/\n/**\n * Represents a selector combinator (whitespace, +, >).\n * @namespace parserlib.css\n * @class Combinator\n * @extends parserlib.util.SyntaxUnit\n * @constructor\n * @param {String} text The text representation of the unit.\n * @param {int} line The line of text on which the unit resides.\n * @param {int} col The column of text on which the unit resides.\n */\nfunction Combinator(text, line, col){\n\n    SyntaxUnit.call(this, text, line, col, Parser.COMBINATOR_TYPE);\n\n    /**\n     * The type of modifier.\n     * @type String\n     * @property type\n     */\n    this.type = \"unknown\";\n\n    //pretty simple\n    if (/^\\s+$/.test(text)){\n        this.type = \"descendant\";\n    } else if (text == \">\"){\n        this.type = \"child\";\n    } else if (text == \"+\"){\n        this.type = \"adjacent-sibling\";\n    } else if (text == \"~\"){\n        this.type = \"sibling\";\n    }\n\n}\n\nCombinator.prototype = new SyntaxUnit();\nCombinator.prototype.constructor = Combinator;\n\n\n/*global SyntaxUnit, Parser*/\n/**\n * Represents a media feature, such as max-width:500.\n * @namespace parserlib.css\n * @class MediaFeature\n * @extends parserlib.util.SyntaxUnit\n * @constructor\n * @param {SyntaxUnit} name The name of the feature.\n * @param {SyntaxUnit} value The value of the feature or null if none.\n */\nfunction MediaFeature(name, value){\n\n    SyntaxUnit.call(this, \"(\" + name + (value !== null ? \":\" + value : \"\") + \")\", name.startLine, name.startCol, Parser.MEDIA_FEATURE_TYPE);\n\n    /**\n     * The name of the media feature\n     * @type String\n     * @property name\n     */\n    this.name = name;\n\n    /**\n     * The value for the feature or null if there is none.\n     * @type SyntaxUnit\n     * @property value\n     */\n    this.value = value;\n}\n\nMediaFeature.prototype = new SyntaxUnit();\nMediaFeature.prototype.constructor = MediaFeature;\n\n\n/*global SyntaxUnit, Parser*/\n/**\n * Represents an individual media query.\n * @namespace parserlib.css\n * @class MediaQuery\n * @extends parserlib.util.SyntaxUnit\n * @constructor\n * @param {String} modifier The modifier \"not\" or \"only\" (or null).\n * @param {String} mediaType The type of media (i.e., \"print\").\n * @param {Array} parts Array of selectors parts making up this selector.\n * @param {int} line The line of text on which the unit resides.\n * @param {int} col The column of text on which the unit resides.\n */\nfunction MediaQuery(modifier, mediaType, features, line, col){\n\n    SyntaxUnit.call(this, (modifier ? modifier + \" \": \"\") + (mediaType ? mediaType : \"\") + (mediaType && features.length > 0 ? \" and \" : \"\") + features.join(\" and \"), line, col, Parser.MEDIA_QUERY_TYPE);\n\n    /**\n     * The media modifier (\"not\" or \"only\")\n     * @type String\n     * @property modifier\n     */\n    this.modifier = modifier;\n\n    /**\n     * The mediaType (i.e., \"print\")\n     * @type String\n     * @property mediaType\n     */\n    this.mediaType = mediaType;\n\n    /**\n     * The parts that make up the selector.\n     * @type Array\n     * @property features\n     */\n    this.features = features;\n\n}\n\nMediaQuery.prototype = new SyntaxUnit();\nMediaQuery.prototype.constructor = MediaQuery;\n\n\n/*global Tokens, TokenStream, SyntaxError, Properties, Validation, ValidationError, SyntaxUnit,\n    PropertyValue, PropertyValuePart, SelectorPart, SelectorSubPart, Selector,\n    PropertyName, Combinator, MediaFeature, MediaQuery, EventTarget */\n\n/**\n * A CSS3 parser.\n * @namespace parserlib.css\n * @class Parser\n * @constructor\n * @param {Object} options (Optional) Various options for the parser:\n *      starHack (true|false) to allow IE6 star hack as valid,\n *      underscoreHack (true|false) to interpret leading underscores\n *      as IE6-7 targeting for known properties, ieFilters (true|false)\n *      to indicate that IE < 8 filters should be accepted and not throw\n *      syntax errors.\n */\nfunction Parser(options){\n\n    //inherit event functionality\n    EventTarget.call(this);\n\n\n    this.options = options || {};\n\n    this._tokenStream = null;\n}\n\n//Static constants\nParser.DEFAULT_TYPE = 0;\nParser.COMBINATOR_TYPE = 1;\nParser.MEDIA_FEATURE_TYPE = 2;\nParser.MEDIA_QUERY_TYPE = 3;\nParser.PROPERTY_NAME_TYPE = 4;\nParser.PROPERTY_VALUE_TYPE = 5;\nParser.PROPERTY_VALUE_PART_TYPE = 6;\nParser.SELECTOR_TYPE = 7;\nParser.SELECTOR_PART_TYPE = 8;\nParser.SELECTOR_SUB_PART_TYPE = 9;\n\nParser.prototype = function(){\n\n    var proto = new EventTarget(),  //new prototype\n        prop,\n        additions =  {\n\n            //restore constructor\n            constructor: Parser,\n\n            //instance constants - yuck\n            DEFAULT_TYPE : 0,\n            COMBINATOR_TYPE : 1,\n            MEDIA_FEATURE_TYPE : 2,\n            MEDIA_QUERY_TYPE : 3,\n            PROPERTY_NAME_TYPE : 4,\n            PROPERTY_VALUE_TYPE : 5,\n            PROPERTY_VALUE_PART_TYPE : 6,\n            SELECTOR_TYPE : 7,\n            SELECTOR_PART_TYPE : 8,\n            SELECTOR_SUB_PART_TYPE : 9,\n\n            //-----------------------------------------------------------------\n            // Grammar\n            //-----------------------------------------------------------------\n\n            _stylesheet: function(){\n\n                /*\n                 * stylesheet\n                 *  : [ CHARSET_SYM S* STRING S* ';' ]?\n                 *    [S|CDO|CDC]* [ import [S|CDO|CDC]* ]*\n                 *    [ namespace [S|CDO|CDC]* ]*\n                 *    [ [ ruleset | media | page | font_face | keyframes ] [S|CDO|CDC]* ]*\n                 *  ;\n                 */\n\n                var tokenStream = this._tokenStream,\n                    charset     = null,\n                    count,\n                    token,\n                    tt;\n\n                this.fire(\"startstylesheet\");\n\n                //try to read character set\n                this._charset();\n\n                this._skipCruft();\n\n                //try to read imports - may be more than one\n                while (tokenStream.peek() == Tokens.IMPORT_SYM){\n                    this._import();\n                    this._skipCruft();\n                }\n\n                //try to read namespaces - may be more than one\n                while (tokenStream.peek() == Tokens.NAMESPACE_SYM){\n                    this._namespace();\n                    this._skipCruft();\n                }\n\n                //get the next token\n                tt = tokenStream.peek();\n\n                //try to read the rest\n                while(tt > Tokens.EOF){\n\n                    try {\n\n                        switch(tt){\n                            case Tokens.MEDIA_SYM:\n                                this._media();\n                                this._skipCruft();\n                                break;\n                            case Tokens.PAGE_SYM:\n                                this._page();\n                                this._skipCruft();\n                                break;\n                            case Tokens.FONT_FACE_SYM:\n                                this._font_face();\n                                this._skipCruft();\n                                break;\n                            case Tokens.KEYFRAMES_SYM:\n                                this._keyframes();\n                                this._skipCruft();\n                                break;\n                            case Tokens.UNKNOWN_SYM:  //unknown @ rule\n                                tokenStream.get();\n                                if (!this.options.strict){\n\n                                    //fire error event\n                                    this.fire({\n                                        type:       \"error\",\n                                        error:      null,\n                                        message:    \"Unknown @ rule: \" + tokenStream.LT(0).value + \".\",\n                                        line:       tokenStream.LT(0).startLine,\n                                        col:        tokenStream.LT(0).startCol\n                                    });\n\n                                    //skip braces\n                                    count=0;\n                                    while (tokenStream.advance([Tokens.LBRACE, Tokens.RBRACE]) == Tokens.LBRACE){\n                                        count++;    //keep track of nesting depth\n                                    }\n\n                                    while(count){\n                                        tokenStream.advance([Tokens.RBRACE]);\n                                        count--;\n                                    }\n\n                                } else {\n                                    //not a syntax error, rethrow it\n                                    throw new SyntaxError(\"Unknown @ rule.\", tokenStream.LT(0).startLine, tokenStream.LT(0).startCol);\n                                }\n                                break;\n                            case Tokens.S:\n                                this._readWhitespace();\n                                break;\n                            default:\n                                if(!this._ruleset()){\n\n                                    //error handling for known issues\n                                    switch(tt){\n                                        case Tokens.CHARSET_SYM:\n                                            token = tokenStream.LT(1);\n                                            this._charset(false);\n                                            throw new SyntaxError(\"@charset not allowed here.\", token.startLine, token.startCol);\n                                        case Tokens.IMPORT_SYM:\n                                            token = tokenStream.LT(1);\n                                            this._import(false);\n                                            throw new SyntaxError(\"@import not allowed here.\", token.startLine, token.startCol);\n                                        case Tokens.NAMESPACE_SYM:\n                                            token = tokenStream.LT(1);\n                                            this._namespace(false);\n                                            throw new SyntaxError(\"@namespace not allowed here.\", token.startLine, token.startCol);\n                                        default:\n                                            tokenStream.get();  //get the last token\n                                            this._unexpectedToken(tokenStream.token());\n                                    }\n\n                                }\n                        }\n                    } catch(ex) {\n                        if (ex instanceof SyntaxError && !this.options.strict){\n                            this.fire({\n                                type:       \"error\",\n                                error:      ex,\n                                message:    ex.message,\n                                line:       ex.line,\n                                col:        ex.col\n                            });\n                        } else {\n                            throw ex;\n                        }\n                    }\n\n                    tt = tokenStream.peek();\n                }\n\n                if (tt != Tokens.EOF){\n                    this._unexpectedToken(tokenStream.token());\n                }\n\n                this.fire(\"endstylesheet\");\n            },\n\n            _charset: function(emit){\n                var tokenStream = this._tokenStream,\n                    charset,\n                    token,\n                    line,\n                    col;\n\n                if (tokenStream.match(Tokens.CHARSET_SYM)){\n                    line = tokenStream.token().startLine;\n                    col = tokenStream.token().startCol;\n\n                    this._readWhitespace();\n                    tokenStream.mustMatch(Tokens.STRING);\n\n                    token = tokenStream.token();\n                    charset = token.value;\n\n                    this._readWhitespace();\n                    tokenStream.mustMatch(Tokens.SEMICOLON);\n\n                    if (emit !== false){\n                        this.fire({\n                            type:   \"charset\",\n                            charset:charset,\n                            line:   line,\n                            col:    col\n                        });\n                    }\n                }\n            },\n\n            _import: function(emit){\n                /*\n                 * import\n                 *   : IMPORT_SYM S*\n                 *    [STRING|URI] S* media_query_list? ';' S*\n                 */\n\n                var tokenStream = this._tokenStream,\n                    tt,\n                    uri,\n                    importToken,\n                    mediaList   = [];\n\n                //read import symbol\n                tokenStream.mustMatch(Tokens.IMPORT_SYM);\n                importToken = tokenStream.token();\n                this._readWhitespace();\n\n                tokenStream.mustMatch([Tokens.STRING, Tokens.URI]);\n\n                //grab the URI value\n                uri = tokenStream.token().value.replace(/(?:url\\()?[\"']([^\"']+)[\"']\\)?/, \"$1\");\n\n                this._readWhitespace();\n\n                mediaList = this._media_query_list();\n\n                //must end with a semicolon\n                tokenStream.mustMatch(Tokens.SEMICOLON);\n                this._readWhitespace();\n\n                if (emit !== false){\n                    this.fire({\n                        type:   \"import\",\n                        uri:    uri,\n                        media:  mediaList,\n                        line:   importToken.startLine,\n                        col:    importToken.startCol\n                    });\n                }\n\n            },\n\n            _namespace: function(emit){\n                /*\n                 * namespace\n                 *   : NAMESPACE_SYM S* [namespace_prefix S*]? [STRING|URI] S* ';' S*\n                 */\n\n                var tokenStream = this._tokenStream,\n                    line,\n                    col,\n                    prefix,\n                    uri;\n\n                //read import symbol\n                tokenStream.mustMatch(Tokens.NAMESPACE_SYM);\n                line = tokenStream.token().startLine;\n                col = tokenStream.token().startCol;\n                this._readWhitespace();\n\n                //it's a namespace prefix - no _namespace_prefix() method because it's just an IDENT\n                if (tokenStream.match(Tokens.IDENT)){\n                    prefix = tokenStream.token().value;\n                    this._readWhitespace();\n                }\n\n                tokenStream.mustMatch([Tokens.STRING, Tokens.URI]);\n                /*if (!tokenStream.match(Tokens.STRING)){\n                    tokenStream.mustMatch(Tokens.URI);\n                }*/\n\n                //grab the URI value\n                uri = tokenStream.token().value.replace(/(?:url\\()?[\"']([^\"']+)[\"']\\)?/, \"$1\");\n\n                this._readWhitespace();\n\n                //must end with a semicolon\n                tokenStream.mustMatch(Tokens.SEMICOLON);\n                this._readWhitespace();\n\n                if (emit !== false){\n                    this.fire({\n                        type:   \"namespace\",\n                        prefix: prefix,\n                        uri:    uri,\n                        line:   line,\n                        col:    col\n                    });\n                }\n\n            },\n\n            _media: function(){\n                /*\n                 * media\n                 *   : MEDIA_SYM S* media_query_list S* '{' S* ruleset* '}' S*\n                 *   ;\n                 */\n                var tokenStream     = this._tokenStream,\n                    line,\n                    col,\n                    mediaList;//       = [];\n\n                //look for @media\n                tokenStream.mustMatch(Tokens.MEDIA_SYM);\n                line = tokenStream.token().startLine;\n                col = tokenStream.token().startCol;\n\n                this._readWhitespace();\n\n                mediaList = this._media_query_list();\n\n                tokenStream.mustMatch(Tokens.LBRACE);\n                this._readWhitespace();\n\n                this.fire({\n                    type:   \"startmedia\",\n                    media:  mediaList,\n                    line:   line,\n                    col:    col\n                });\n\n                while(true) {\n                    if (tokenStream.peek() == Tokens.PAGE_SYM){\n                        this._page();\n                    } else if (!this._ruleset()){\n                        break;\n                    }\n                }\n\n                tokenStream.mustMatch(Tokens.RBRACE);\n                this._readWhitespace();\n\n                this.fire({\n                    type:   \"endmedia\",\n                    media:  mediaList,\n                    line:   line,\n                    col:    col\n                });\n            },\n\n\n            //CSS3 Media Queries\n            _media_query_list: function(){\n                /*\n                 * media_query_list\n                 *   : S* [media_query [ ',' S* media_query ]* ]?\n                 *   ;\n                 */\n                var tokenStream = this._tokenStream,\n                    mediaList   = [];\n\n\n                this._readWhitespace();\n\n                if (tokenStream.peek() == Tokens.IDENT || tokenStream.peek() == Tokens.LPAREN){\n                    mediaList.push(this._media_query());\n                }\n\n                while(tokenStream.match(Tokens.COMMA)){\n                    this._readWhitespace();\n                    mediaList.push(this._media_query());\n                }\n\n                return mediaList;\n            },\n\n            /*\n             * Note: \"expression\" in the grammar maps to the _media_expression\n             * method.\n\n             */\n            _media_query: function(){\n                /*\n                 * media_query\n                 *   : [ONLY | NOT]? S* media_type S* [ AND S* expression ]*\n                 *   | expression [ AND S* expression ]*\n                 *   ;\n                 */\n                var tokenStream = this._tokenStream,\n                    type        = null,\n                    ident       = null,\n                    token       = null,\n                    expressions = [];\n\n                if (tokenStream.match(Tokens.IDENT)){\n                    ident = tokenStream.token().value.toLowerCase();\n\n                    //since there's no custom tokens for these, need to manually check\n                    if (ident != \"only\" && ident != \"not\"){\n                        tokenStream.unget();\n                        ident = null;\n                    } else {\n                        token = tokenStream.token();\n                    }\n                }\n\n                this._readWhitespace();\n\n                if (tokenStream.peek() == Tokens.IDENT){\n                    type = this._media_type();\n                    if (token === null){\n                        token = tokenStream.token();\n                    }\n                } else if (tokenStream.peek() == Tokens.LPAREN){\n                    if (token === null){\n                        token = tokenStream.LT(1);\n                    }\n                    expressions.push(this._media_expression());\n                }\n\n                if (type === null && expressions.length === 0){\n                    return null;\n                } else {\n                    this._readWhitespace();\n                    while (tokenStream.match(Tokens.IDENT)){\n                        if (tokenStream.token().value.toLowerCase() != \"and\"){\n                            this._unexpectedToken(tokenStream.token());\n                        }\n\n                        this._readWhitespace();\n                        expressions.push(this._media_expression());\n                    }\n                }\n\n                return new MediaQuery(ident, type, expressions, token.startLine, token.startCol);\n            },\n\n            //CSS3 Media Queries\n            _media_type: function(){\n                /*\n                 * media_type\n                 *   : IDENT\n                 *   ;\n                 */\n                return this._media_feature();\n            },\n\n            /**\n             * Note: in CSS3 Media Queries, this is called \"expression\".\n             * Renamed here to avoid conflict with CSS3 Selectors\n             * definition of \"expression\". Also note that \"expr\" in the\n             * grammar now maps to \"expression\" from CSS3 selectors.\n             * @method _media_expression\n             * @private\n             */\n            _media_expression: function(){\n                /*\n                 * expression\n                 *  : '(' S* media_feature S* [ ':' S* expr ]? ')' S*\n                 *  ;\n                 */\n                var tokenStream = this._tokenStream,\n                    feature     = null,\n                    token,\n                    expression  = null;\n\n                tokenStream.mustMatch(Tokens.LPAREN);\n\n                feature = this._media_feature();\n                this._readWhitespace();\n\n                if (tokenStream.match(Tokens.COLON)){\n                    this._readWhitespace();\n                    token = tokenStream.LT(1);\n                    expression = this._expression();\n                }\n\n                tokenStream.mustMatch(Tokens.RPAREN);\n                this._readWhitespace();\n\n                return new MediaFeature(feature, (expression ? new SyntaxUnit(expression, token.startLine, token.startCol) : null));\n            },\n\n            //CSS3 Media Queries\n            _media_feature: function(){\n                /*\n                 * media_feature\n                 *   : IDENT\n                 *   ;\n                 */\n                var tokenStream = this._tokenStream;\n\n                tokenStream.mustMatch(Tokens.IDENT);\n\n                return SyntaxUnit.fromToken(tokenStream.token());\n            },\n\n            //CSS3 Paged Media\n            _page: function(){\n                /*\n                 * page:\n                 *    PAGE_SYM S* IDENT? pseudo_page? S*\n                 *    '{' S* [ declaration | margin ]? [ ';' S* [ declaration | margin ]? ]* '}' S*\n                 *    ;\n                 */\n                var tokenStream = this._tokenStream,\n                    line,\n                    col,\n                    identifier  = null,\n                    pseudoPage  = null;\n\n                //look for @page\n                tokenStream.mustMatch(Tokens.PAGE_SYM);\n                line = tokenStream.token().startLine;\n                col = tokenStream.token().startCol;\n\n                this._readWhitespace();\n\n                if (tokenStream.match(Tokens.IDENT)){\n                    identifier = tokenStream.token().value;\n\n                    //The value 'auto' may not be used as a page name and MUST be treated as a syntax error.\n                    if (identifier.toLowerCase() === \"auto\"){\n                        this._unexpectedToken(tokenStream.token());\n                    }\n                }\n\n                //see if there's a colon upcoming\n                if (tokenStream.peek() == Tokens.COLON){\n                    pseudoPage = this._pseudo_page();\n                }\n\n                this._readWhitespace();\n\n                this.fire({\n                    type:   \"startpage\",\n                    id:     identifier,\n                    pseudo: pseudoPage,\n                    line:   line,\n                    col:    col\n                });\n\n                this._readDeclarations(true, true);\n\n                this.fire({\n                    type:   \"endpage\",\n                    id:     identifier,\n                    pseudo: pseudoPage,\n                    line:   line,\n                    col:    col\n                });\n\n            },\n\n            //CSS3 Paged Media\n            _margin: function(){\n                /*\n                 * margin :\n                 *    margin_sym S* '{' declaration [ ';' S* declaration? ]* '}' S*\n                 *    ;\n                 */\n                var tokenStream = this._tokenStream,\n                    line,\n                    col,\n                    marginSym   = this._margin_sym();\n\n                if (marginSym){\n                    line = tokenStream.token().startLine;\n                    col = tokenStream.token().startCol;\n\n                    this.fire({\n                        type: \"startpagemargin\",\n                        margin: marginSym,\n                        line:   line,\n                        col:    col\n                    });\n\n                    this._readDeclarations(true);\n\n                    this.fire({\n                        type: \"endpagemargin\",\n                        margin: marginSym,\n                        line:   line,\n                        col:    col\n                    });\n                    return true;\n                } else {\n                    return false;\n                }\n            },\n\n            //CSS3 Paged Media\n            _margin_sym: function(){\n\n                /*\n                 * margin_sym :\n                 *    TOPLEFTCORNER_SYM |\n                 *    TOPLEFT_SYM |\n                 *    TOPCENTER_SYM |\n                 *    TOPRIGHT_SYM |\n                 *    TOPRIGHTCORNER_SYM |\n                 *    BOTTOMLEFTCORNER_SYM |\n                 *    BOTTOMLEFT_SYM |\n                 *    BOTTOMCENTER_SYM |\n                 *    BOTTOMRIGHT_SYM |\n                 *    BOTTOMRIGHTCORNER_SYM |\n                 *    LEFTTOP_SYM |\n                 *    LEFTMIDDLE_SYM |\n                 *    LEFTBOTTOM_SYM |\n                 *    RIGHTTOP_SYM |\n                 *    RIGHTMIDDLE_SYM |\n                 *    RIGHTBOTTOM_SYM\n                 *    ;\n                 */\n\n                var tokenStream = this._tokenStream;\n\n                if(tokenStream.match([Tokens.TOPLEFTCORNER_SYM, Tokens.TOPLEFT_SYM,\n                        Tokens.TOPCENTER_SYM, Tokens.TOPRIGHT_SYM, Tokens.TOPRIGHTCORNER_SYM,\n                        Tokens.BOTTOMLEFTCORNER_SYM, Tokens.BOTTOMLEFT_SYM,\n                        Tokens.BOTTOMCENTER_SYM, Tokens.BOTTOMRIGHT_SYM,\n                        Tokens.BOTTOMRIGHTCORNER_SYM, Tokens.LEFTTOP_SYM,\n                        Tokens.LEFTMIDDLE_SYM, Tokens.LEFTBOTTOM_SYM, Tokens.RIGHTTOP_SYM,\n                        Tokens.RIGHTMIDDLE_SYM, Tokens.RIGHTBOTTOM_SYM]))\n                {\n                    return SyntaxUnit.fromToken(tokenStream.token());\n                } else {\n                    return null;\n                }\n\n            },\n\n            _pseudo_page: function(){\n                /*\n                 * pseudo_page\n                 *   : ':' IDENT\n                 *   ;\n                 */\n\n                var tokenStream = this._tokenStream;\n\n                tokenStream.mustMatch(Tokens.COLON);\n                tokenStream.mustMatch(Tokens.IDENT);\n\n                //TODO: CSS3 Paged Media says only \"left\", \"center\", and \"right\" are allowed\n\n                return tokenStream.token().value;\n            },\n\n            _font_face: function(){\n                /*\n                 * font_face\n                 *   : FONT_FACE_SYM S*\n                 *     '{' S* declaration [ ';' S* declaration ]* '}' S*\n                 *   ;\n                 */\n                var tokenStream = this._tokenStream,\n                    line,\n                    col;\n\n                //look for @page\n                tokenStream.mustMatch(Tokens.FONT_FACE_SYM);\n                line = tokenStream.token().startLine;\n                col = tokenStream.token().startCol;\n\n                this._readWhitespace();\n\n                this.fire({\n                    type:   \"startfontface\",\n                    line:   line,\n                    col:    col\n                });\n\n                this._readDeclarations(true);\n\n                this.fire({\n                    type:   \"endfontface\",\n                    line:   line,\n                    col:    col\n                });\n            },\n\n            _operator: function(inFunction){\n\n                /*\n                 * operator (outside function)\n                 *  : '/' S* | ',' S* | /( empty )/\n                 * operator (inside function)\n                 *  : '/' S* | '+' S* | '*' S* | '-' S* /( empty )/\n                 *  ;\n                 */\n\n                var tokenStream = this._tokenStream,\n                    token       = null;\n\n                if (tokenStream.match([Tokens.SLASH, Tokens.COMMA]) ||\n                    (inFunction && tokenStream.match([Tokens.PLUS, Tokens.STAR, Tokens.MINUS]))){\n                    token =  tokenStream.token();\n                    this._readWhitespace();\n                }\n                return token ? PropertyValuePart.fromToken(token) : null;\n\n            },\n\n            _combinator: function(){\n\n                /*\n                 * combinator\n                 *  : PLUS S* | GREATER S* | TILDE S* | S+\n                 *  ;\n                 */\n\n                var tokenStream = this._tokenStream,\n                    value       = null,\n                    token;\n\n                if(tokenStream.match([Tokens.PLUS, Tokens.GREATER, Tokens.TILDE])){\n                    token = tokenStream.token();\n                    value = new Combinator(token.value, token.startLine, token.startCol);\n                    this._readWhitespace();\n                }\n\n                return value;\n            },\n\n            _unary_operator: function(){\n\n                /*\n                 * unary_operator\n                 *  : '-' | '+'\n                 *  ;\n                 */\n\n                var tokenStream = this._tokenStream;\n\n                if (tokenStream.match([Tokens.MINUS, Tokens.PLUS])){\n                    return tokenStream.token().value;\n                } else {\n                    return null;\n                }\n            },\n\n            _property: function(){\n\n                /*\n                 * property\n                 *   : IDENT S*\n                 *   ;\n                 */\n\n                var tokenStream = this._tokenStream,\n                    value       = null,\n                    hack        = null,\n                    tokenValue,\n                    token,\n                    line,\n                    col;\n\n                //check for star hack - throws error if not allowed\n                if (tokenStream.peek() == Tokens.STAR && this.options.starHack){\n                    tokenStream.get();\n                    token = tokenStream.token();\n                    hack = token.value;\n                    line = token.startLine;\n                    col = token.startCol;\n                }\n\n                if(tokenStream.match(Tokens.IDENT)){\n                    token = tokenStream.token();\n                    tokenValue = token.value;\n\n                    //check for underscore hack - no error if not allowed because it's valid CSS syntax\n                    if (tokenValue.charAt(0) == \"_\" && this.options.underscoreHack){\n                        hack = \"_\";\n                        tokenValue = tokenValue.substring(1);\n                    }\n\n                    value = new PropertyName(tokenValue, hack, (line||token.startLine), (col||token.startCol));\n                    this._readWhitespace();\n                }\n\n                return value;\n            },\n\n            //Augmented with CSS3 Selectors\n            _ruleset: function(){\n                /*\n                 * ruleset\n                 *   : selectors_group\n                 *     '{' S* declaration? [ ';' S* declaration? ]* '}' S*\n                 *   ;\n                 */\n\n                var tokenStream = this._tokenStream,\n                    tt,\n                    selectors;\n\n\n                /*\n                 * Error Recovery: If even a single selector fails to parse,\n                 * then the entire ruleset should be thrown away.\n                 */\n                try {\n                    selectors = this._selectors_group();\n                } catch (ex){\n                    if (ex instanceof SyntaxError && !this.options.strict){\n\n                        //fire error event\n                        this.fire({\n                            type:       \"error\",\n                            error:      ex,\n                            message:    ex.message,\n                            line:       ex.line,\n                            col:        ex.col\n                        });\n\n                        //skip over everything until closing brace\n                        tt = tokenStream.advance([Tokens.RBRACE]);\n                        if (tt == Tokens.RBRACE){\n                            //if there's a right brace, the rule is finished so don't do anything\n                        } else {\n                            //otherwise, rethrow the error because it wasn't handled properly\n                            throw ex;\n                        }\n\n                    } else {\n                        //not a syntax error, rethrow it\n                        throw ex;\n                    }\n\n                    //trigger parser to continue\n                    return true;\n                }\n\n                //if it got here, all selectors parsed\n                if (selectors){\n\n                    this.fire({\n                        type:       \"startrule\",\n                        selectors:  selectors,\n                        line:       selectors[0].line,\n                        col:        selectors[0].col\n                    });\n\n                    this._readDeclarations(true);\n\n                    this.fire({\n                        type:       \"endrule\",\n                        selectors:  selectors,\n                        line:       selectors[0].line,\n                        col:        selectors[0].col\n                    });\n\n                }\n\n                return selectors;\n\n            },\n\n            //CSS3 Selectors\n            _selectors_group: function(){\n\n                /*\n                 * selectors_group\n                 *   : selector [ COMMA S* selector ]*\n                 *   ;\n                 */\n                var tokenStream = this._tokenStream,\n                    selectors   = [],\n                    selector;\n\n                selector = this._selector();\n                if (selector !== null){\n\n                    selectors.push(selector);\n                    while(tokenStream.match(Tokens.COMMA)){\n                        this._readWhitespace();\n                        selector = this._selector();\n                        if (selector !== null){\n                            selectors.push(selector);\n                        } else {\n                            this._unexpectedToken(tokenStream.LT(1));\n                        }\n                    }\n                }\n\n                return selectors.length ? selectors : null;\n            },\n\n            //CSS3 Selectors\n            _selector: function(){\n                /*\n                 * selector\n                 *   : simple_selector_sequence [ combinator simple_selector_sequence ]*\n                 *   ;\n                 */\n\n                var tokenStream = this._tokenStream,\n                    selector    = [],\n                    nextSelector = null,\n                    combinator  = null,\n                    ws          = null;\n\n                //if there's no simple selector, then there's no selector\n                nextSelector = this._simple_selector_sequence();\n                if (nextSelector === null){\n                    return null;\n                }\n\n                selector.push(nextSelector);\n\n                do {\n\n                    //look for a combinator\n                    combinator = this._combinator();\n\n                    if (combinator !== null){\n                        selector.push(combinator);\n                        nextSelector = this._simple_selector_sequence();\n\n                        //there must be a next selector\n                        if (nextSelector === null){\n                            this._unexpectedToken(tokenStream.LT(1));\n                        } else {\n\n                            //nextSelector is an instance of SelectorPart\n                            selector.push(nextSelector);\n                        }\n                    } else {\n\n                        //if there's not whitespace, we're done\n                        if (this._readWhitespace()){\n\n                            //add whitespace separator\n                            ws = new Combinator(tokenStream.token().value, tokenStream.token().startLine, tokenStream.token().startCol);\n\n                            //combinator is not required\n                            combinator = this._combinator();\n\n                            //selector is required if there's a combinator\n                            nextSelector = this._simple_selector_sequence();\n                            if (nextSelector === null){\n                                if (combinator !== null){\n                                    this._unexpectedToken(tokenStream.LT(1));\n                                }\n                            } else {\n\n                                if (combinator !== null){\n                                    selector.push(combinator);\n                                } else {\n                                    selector.push(ws);\n                                }\n\n                                selector.push(nextSelector);\n                            }\n                        } else {\n                            break;\n                        }\n\n                    }\n                } while(true);\n\n                return new Selector(selector, selector[0].line, selector[0].col);\n            },\n\n            //CSS3 Selectors\n            _simple_selector_sequence: function(){\n                /*\n                 * simple_selector_sequence\n                 *   : [ type_selector | universal ]\n                 *     [ HASH | class | attrib | pseudo | negation ]*\n                 *   | [ HASH | class | attrib | pseudo | negation ]+\n                 *   ;\n                 */\n\n                var tokenStream = this._tokenStream,\n\n                    //parts of a simple selector\n                    elementName = null,\n                    modifiers   = [],\n\n                    //complete selector text\n                    selectorText= \"\",\n\n                    //the different parts after the element name to search for\n                    components  = [\n                        //HASH\n                        function(){\n                            return tokenStream.match(Tokens.HASH) ?\n                                    new SelectorSubPart(tokenStream.token().value, \"id\", tokenStream.token().startLine, tokenStream.token().startCol) :\n                                    null;\n                        },\n                        this._class,\n                        this._attrib,\n                        this._pseudo,\n                        this._negation\n                    ],\n                    i           = 0,\n                    len         = components.length,\n                    component   = null,\n                    found       = false,\n                    line,\n                    col;\n\n\n                //get starting line and column for the selector\n                line = tokenStream.LT(1).startLine;\n                col = tokenStream.LT(1).startCol;\n\n                elementName = this._type_selector();\n                if (!elementName){\n                    elementName = this._universal();\n                }\n\n                if (elementName !== null){\n                    selectorText += elementName;\n                }\n\n                while(true){\n\n                    //whitespace means we're done\n                    if (tokenStream.peek() === Tokens.S){\n                        break;\n                    }\n\n                    //check for each component\n                    while(i < len && component === null){\n                        component = components[i++].call(this);\n                    }\n\n                    if (component === null){\n\n                        //we don't have a selector\n                        if (selectorText === \"\"){\n                            return null;\n                        } else {\n                            break;\n                        }\n                    } else {\n                        i = 0;\n                        modifiers.push(component);\n                        selectorText += component.toString();\n                        component = null;\n                    }\n                }\n\n\n                return selectorText !== \"\" ?\n                        new SelectorPart(elementName, modifiers, selectorText, line, col) :\n                        null;\n            },\n\n            //CSS3 Selectors\n            _type_selector: function(){\n                /*\n                 * type_selector\n                 *   : [ namespace_prefix ]? element_name\n                 *   ;\n                 */\n\n                var tokenStream = this._tokenStream,\n                    ns          = this._namespace_prefix(),\n                    elementName = this._element_name();\n\n                if (!elementName){\n                    /*\n                     * Need to back out the namespace that was read due to both\n                     * type_selector and universal reading namespace_prefix\n                     * first. Kind of hacky, but only way I can figure out\n                     * right now how to not change the grammar.\n                     */\n                    if (ns){\n                        tokenStream.unget();\n                        if (ns.length > 1){\n                            tokenStream.unget();\n                        }\n                    }\n\n                    return null;\n                } else {\n                    if (ns){\n                        elementName.text = ns + elementName.text;\n                        elementName.col -= ns.length;\n                    }\n                    return elementName;\n                }\n            },\n\n            //CSS3 Selectors\n            _class: function(){\n                /*\n                 * class\n                 *   : '.' IDENT\n                 *   ;\n                 */\n\n                var tokenStream = this._tokenStream,\n                    token;\n\n                if (tokenStream.match(Tokens.DOT)){\n                    tokenStream.mustMatch(Tokens.IDENT);\n                    token = tokenStream.token();\n                    return new SelectorSubPart(\".\" + token.value, \"class\", token.startLine, token.startCol - 1);\n                } else {\n                    return null;\n                }\n\n            },\n\n            //CSS3 Selectors\n            _element_name: function(){\n                /*\n                 * element_name\n                 *   : IDENT\n                 *   ;\n                 */\n\n                var tokenStream = this._tokenStream,\n                    token;\n\n                if (tokenStream.match(Tokens.IDENT)){\n                    token = tokenStream.token();\n                    return new SelectorSubPart(token.value, \"elementName\", token.startLine, token.startCol);\n\n                } else {\n                    return null;\n                }\n            },\n\n            //CSS3 Selectors\n            _namespace_prefix: function(){\n                /*\n                 * namespace_prefix\n                 *   : [ IDENT | '*' ]? '|'\n                 *   ;\n                 */\n                var tokenStream = this._tokenStream,\n                    value       = \"\";\n\n                //verify that this is a namespace prefix\n                if (tokenStream.LA(1) === Tokens.PIPE || tokenStream.LA(2) === Tokens.PIPE){\n\n                    if(tokenStream.match([Tokens.IDENT, Tokens.STAR])){\n                        value += tokenStream.token().value;\n                    }\n\n                    tokenStream.mustMatch(Tokens.PIPE);\n                    value += \"|\";\n\n                }\n\n                return value.length ? value : null;\n            },\n\n            //CSS3 Selectors\n            _universal: function(){\n                /*\n                 * universal\n                 *   : [ namespace_prefix ]? '*'\n                 *   ;\n                 */\n                var tokenStream = this._tokenStream,\n                    value       = \"\",\n                    ns;\n\n                ns = this._namespace_prefix();\n                if(ns){\n                    value += ns;\n                }\n\n                if(tokenStream.match(Tokens.STAR)){\n                    value += \"*\";\n                }\n\n                return value.length ? value : null;\n\n           },\n\n            //CSS3 Selectors\n            _attrib: function(){\n                /*\n                 * attrib\n                 *   : '[' S* [ namespace_prefix ]? IDENT S*\n                 *         [ [ PREFIXMATCH |\n                 *             SUFFIXMATCH |\n                 *             SUBSTRINGMATCH |\n                 *             '=' |\n                 *             INCLUDES |\n                 *             DASHMATCH ] S* [ IDENT | STRING ] S*\n                 *         ]? ']'\n                 *   ;\n                 */\n\n                var tokenStream = this._tokenStream,\n                    value       = null,\n                    ns,\n                    token;\n\n                if (tokenStream.match(Tokens.LBRACKET)){\n                    token = tokenStream.token();\n                    value = token.value;\n                    value += this._readWhitespace();\n\n                    ns = this._namespace_prefix();\n\n                    if (ns){\n                        value += ns;\n                    }\n\n                    tokenStream.mustMatch(Tokens.IDENT);\n                    value += tokenStream.token().value;\n                    value += this._readWhitespace();\n\n                    if(tokenStream.match([Tokens.PREFIXMATCH, Tokens.SUFFIXMATCH, Tokens.SUBSTRINGMATCH,\n                            Tokens.EQUALS, Tokens.INCLUDES, Tokens.DASHMATCH])){\n\n                        value += tokenStream.token().value;\n                        value += this._readWhitespace();\n\n                        tokenStream.mustMatch([Tokens.IDENT, Tokens.STRING]);\n                        value += tokenStream.token().value;\n                        value += this._readWhitespace();\n                    }\n\n                    tokenStream.mustMatch(Tokens.RBRACKET);\n\n                    return new SelectorSubPart(value + \"]\", \"attribute\", token.startLine, token.startCol);\n                } else {\n                    return null;\n                }\n            },\n\n            //CSS3 Selectors\n            _pseudo: function(){\n\n                /*\n                 * pseudo\n                 *   : ':' ':'? [ IDENT | functional_pseudo ]\n                 *   ;\n                 */\n\n                var tokenStream = this._tokenStream,\n                    pseudo      = null,\n                    colons      = \":\",\n                    line,\n                    col;\n\n                if (tokenStream.match(Tokens.COLON)){\n\n                    if (tokenStream.match(Tokens.COLON)){\n                        colons += \":\";\n                    }\n\n                    if (tokenStream.match(Tokens.IDENT)){\n                        pseudo = tokenStream.token().value;\n                        line = tokenStream.token().startLine;\n                        col = tokenStream.token().startCol - colons.length;\n                    } else if (tokenStream.peek() == Tokens.FUNCTION){\n                        line = tokenStream.LT(1).startLine;\n                        col = tokenStream.LT(1).startCol - colons.length;\n                        pseudo = this._functional_pseudo();\n                    }\n\n                    if (pseudo){\n                        pseudo = new SelectorSubPart(colons + pseudo, \"pseudo\", line, col);\n                    }\n                }\n\n                return pseudo;\n            },\n\n            //CSS3 Selectors\n            _functional_pseudo: function(){\n                /*\n                 * functional_pseudo\n                 *   : FUNCTION S* expression ')'\n                 *   ;\n                */\n\n                var tokenStream = this._tokenStream,\n                    value = null;\n\n                if(tokenStream.match(Tokens.FUNCTION)){\n                    value = tokenStream.token().value;\n                    value += this._readWhitespace();\n                    value += this._expression();\n                    tokenStream.mustMatch(Tokens.RPAREN);\n                    value += \")\";\n                }\n\n                return value;\n            },\n\n            //CSS3 Selectors\n            _expression: function(){\n                /*\n                 * expression\n                 *   : [ [ PLUS | '-' | DIMENSION | NUMBER | STRING | IDENT ] S* ]+\n                 *   ;\n                 */\n\n                var tokenStream = this._tokenStream,\n                    value       = \"\";\n\n                while(tokenStream.match([Tokens.PLUS, Tokens.MINUS, Tokens.DIMENSION,\n                        Tokens.NUMBER, Tokens.STRING, Tokens.IDENT, Tokens.LENGTH,\n                        Tokens.FREQ, Tokens.ANGLE, Tokens.TIME,\n                        Tokens.RESOLUTION, Tokens.SLASH])){\n\n                    value += tokenStream.token().value;\n                    value += this._readWhitespace();\n                }\n\n                return value.length ? value : null;\n\n            },\n\n            //CSS3 Selectors\n            _negation: function(){\n                /*\n                 * negation\n                 *   : NOT S* negation_arg S* ')'\n                 *   ;\n                 */\n\n                var tokenStream = this._tokenStream,\n                    line,\n                    col,\n                    value       = \"\",\n                    arg,\n                    subpart     = null;\n\n                if (tokenStream.match(Tokens.NOT)){\n                    value = tokenStream.token().value;\n                    line = tokenStream.token().startLine;\n                    col = tokenStream.token().startCol;\n                    value += this._readWhitespace();\n                    arg = this._negation_arg();\n                    value += arg;\n                    value += this._readWhitespace();\n                    tokenStream.match(Tokens.RPAREN);\n                    value += tokenStream.token().value;\n\n                    subpart = new SelectorSubPart(value, \"not\", line, col);\n                    subpart.args.push(arg);\n                }\n\n                return subpart;\n            },\n\n            //CSS3 Selectors\n            _negation_arg: function(){\n                /*\n                 * negation_arg\n                 *   : type_selector | universal | HASH | class | attrib | pseudo\n                 *   ;\n                 */\n\n                var tokenStream = this._tokenStream,\n                    args        = [\n                        this._type_selector,\n                        this._universal,\n                        function(){\n                            return tokenStream.match(Tokens.HASH) ?\n                                    new SelectorSubPart(tokenStream.token().value, \"id\", tokenStream.token().startLine, tokenStream.token().startCol) :\n                                    null;\n                        },\n                        this._class,\n                        this._attrib,\n                        this._pseudo\n                    ],\n                    arg         = null,\n                    i           = 0,\n                    len         = args.length,\n                    elementName,\n                    line,\n                    col,\n                    part;\n\n                line = tokenStream.LT(1).startLine;\n                col = tokenStream.LT(1).startCol;\n\n                while(i < len && arg === null){\n\n                    arg = args[i].call(this);\n                    i++;\n                }\n\n                //must be a negation arg\n                if (arg === null){\n                    this._unexpectedToken(tokenStream.LT(1));\n                }\n\n                //it's an element name\n                if (arg.type == \"elementName\"){\n                    part = new SelectorPart(arg, [], arg.toString(), line, col);\n                } else {\n                    part = new SelectorPart(null, [arg], arg.toString(), line, col);\n                }\n\n                return part;\n            },\n\n            _declaration: function(){\n\n                /*\n                 * declaration\n                 *   : property ':' S* expr prio?\n                 *   | /( empty )/\n                 *   ;\n                 */\n\n                var tokenStream = this._tokenStream,\n                    property    = null,\n                    expr        = null,\n                    prio        = null,\n                    error       = null,\n                    invalid     = null,\n                    propertyName= \"\";\n\n                property = this._property();\n                if (property !== null){\n\n                    tokenStream.mustMatch(Tokens.COLON);\n                    this._readWhitespace();\n\n                    expr = this._expr();\n\n                    //if there's no parts for the value, it's an error\n                    if (!expr || expr.length === 0){\n                        this._unexpectedToken(tokenStream.LT(1));\n                    }\n\n                    prio = this._prio();\n\n                    /*\n                     * If hacks should be allowed, then only check the root\n                     * property. If hacks should not be allowed, treat\n                     * _property or *property as invalid properties.\n                     */\n                    propertyName = property.toString();\n                    if (this.options.starHack && property.hack == \"*\" ||\n                            this.options.underscoreHack && property.hack == \"_\") {\n\n                        propertyName = property.text;\n                    }\n\n                    try {\n                        this._validateProperty(propertyName, expr);\n                    } catch (ex) {\n                        invalid = ex;\n                    }\n\n                    this.fire({\n                        type:       \"property\",\n                        property:   property,\n                        value:      expr,\n                        important:  prio,\n                        line:       property.line,\n                        col:        property.col,\n                        invalid:    invalid\n                    });\n\n                    return true;\n                } else {\n                    return false;\n                }\n            },\n\n            _prio: function(){\n                /*\n                 * prio\n                 *   : IMPORTANT_SYM S*\n                 *   ;\n                 */\n\n                var tokenStream = this._tokenStream,\n                    result      = tokenStream.match(Tokens.IMPORTANT_SYM);\n\n                this._readWhitespace();\n                return result;\n            },\n\n            _expr: function(inFunction){\n                /*\n                 * expr\n                 *   : term [ operator term ]*\n                 *   ;\n                 */\n\n                var tokenStream = this._tokenStream,\n                    values      = [],\n                    //valueParts    = [],\n                    value       = null,\n                    operator    = null;\n\n                value = this._term();\n                if (value !== null){\n\n                    values.push(value);\n\n                    do {\n                        operator = this._operator(inFunction);\n\n                        //if there's an operator, keep building up the value parts\n                        if (operator){\n                            values.push(operator);\n                        } /*else {\n                            //if there's not an operator, you have a full value\n                            values.push(new PropertyValue(valueParts, valueParts[0].line, valueParts[0].col));\n                            valueParts = [];\n                        }*/\n\n                        value = this._term();\n\n                        if (value === null){\n                            break;\n                        } else {\n                            values.push(value);\n                        }\n                    } while(true);\n                }\n\n                //cleanup\n                /*if (valueParts.length){\n                    values.push(new PropertyValue(valueParts, valueParts[0].line, valueParts[0].col));\n                }*/\n\n                return values.length > 0 ? new PropertyValue(values, values[0].line, values[0].col) : null;\n            },\n\n            _term: function(){\n\n                /*\n                 * term\n                 *   : unary_operator?\n                 *     [ NUMBER S* | PERCENTAGE S* | LENGTH S* | ANGLE S* |\n                 *       TIME S* | FREQ S* | function | ie_function ]\n                 *   | STRING S* | IDENT S* | URI S* | UNICODERANGE S* | hexcolor\n                 *   ;\n                 */\n\n                var tokenStream = this._tokenStream,\n                    unary       = null,\n                    value       = null,\n                    token,\n                    line,\n                    col;\n\n                //returns the operator or null\n                unary = this._unary_operator();\n                if (unary !== null){\n                    line = tokenStream.token().startLine;\n                    col = tokenStream.token().startCol;\n                }\n\n                //exception for IE filters\n                if (tokenStream.peek() == Tokens.IE_FUNCTION && this.options.ieFilters){\n\n                    value = this._ie_function();\n                    if (unary === null){\n                        line = tokenStream.token().startLine;\n                        col = tokenStream.token().startCol;\n                    }\n\n                //see if there's a simple match\n                } else if (tokenStream.match([Tokens.NUMBER, Tokens.PERCENTAGE, Tokens.LENGTH,\n                        Tokens.ANGLE, Tokens.TIME,\n                        Tokens.FREQ, Tokens.STRING, Tokens.IDENT, Tokens.URI, Tokens.UNICODE_RANGE])){\n\n                    value = tokenStream.token().value;\n                    if (unary === null){\n                        line = tokenStream.token().startLine;\n                        col = tokenStream.token().startCol;\n                    }\n                    this._readWhitespace();\n                } else {\n\n                    //see if it's a color\n                    token = this._hexcolor();\n                    if (token === null){\n\n                        //if there's no unary, get the start of the next token for line/col info\n                        if (unary === null){\n                            line = tokenStream.LT(1).startLine;\n                            col = tokenStream.LT(1).startCol;\n                        }\n\n                        //has to be a function\n                        if (value === null){\n\n                            /*\n                             * This checks for alpha(opacity=0) style of IE\n                             * functions. IE_FUNCTION only presents progid: style.\n                             */\n                            if (tokenStream.LA(3) == Tokens.EQUALS && this.options.ieFilters){\n                                value = this._ie_function();\n                            } else {\n                                value = this._function();\n                            }\n                        }\n\n                        /*if (value === null){\n                            return null;\n                            //throw new Error(\"Expected identifier at line \" + tokenStream.token().startLine + \", character \" +  tokenStream.token().startCol + \".\");\n                        }*/\n\n                    } else {\n                        value = token.value;\n                        if (unary === null){\n                            line = token.startLine;\n                            col = token.startCol;\n                        }\n                    }\n\n                }\n\n                return value !== null ?\n                        new PropertyValuePart(unary !== null ? unary + value : value, line, col) :\n                        null;\n\n            },\n\n            _function: function(){\n\n                /*\n                 * function\n                 *   : FUNCTION S* expr ')' S*\n                 *   ;\n                 */\n\n                var tokenStream = this._tokenStream,\n                    functionText = null,\n                    expr        = null,\n                    lt;\n\n                if (tokenStream.match(Tokens.FUNCTION)){\n                    functionText = tokenStream.token().value;\n                    this._readWhitespace();\n                    expr = this._expr(true);\n                    functionText += expr;\n\n                    //START: Horrible hack in case it's an IE filter\n                    if (this.options.ieFilters && tokenStream.peek() == Tokens.EQUALS){\n                        do {\n\n                            if (this._readWhitespace()){\n                                functionText += tokenStream.token().value;\n                            }\n\n                            //might be second time in the loop\n                            if (tokenStream.LA(0) == Tokens.COMMA){\n                                functionText += tokenStream.token().value;\n                            }\n\n                            tokenStream.match(Tokens.IDENT);\n                            functionText += tokenStream.token().value;\n\n                            tokenStream.match(Tokens.EQUALS);\n                            functionText += tokenStream.token().value;\n\n                            //functionText += this._term();\n                            lt = tokenStream.peek();\n                            while(lt != Tokens.COMMA && lt != Tokens.S && lt != Tokens.RPAREN){\n                                tokenStream.get();\n                                functionText += tokenStream.token().value;\n                                lt = tokenStream.peek();\n                            }\n                        } while(tokenStream.match([Tokens.COMMA, Tokens.S]));\n                    }\n\n                    //END: Horrible Hack\n\n                    tokenStream.match(Tokens.RPAREN);\n                    functionText += \")\";\n                    this._readWhitespace();\n                }\n\n                return functionText;\n            },\n\n            _ie_function: function(){\n\n                /* (My own extension)\n                 * ie_function\n                 *   : IE_FUNCTION S* IDENT '=' term [S* ','? IDENT '=' term]+ ')' S*\n                 *   ;\n                 */\n\n                var tokenStream = this._tokenStream,\n                    functionText = null,\n                    expr        = null,\n                    lt;\n\n                //IE function can begin like a regular function, too\n                if (tokenStream.match([Tokens.IE_FUNCTION, Tokens.FUNCTION])){\n                    functionText = tokenStream.token().value;\n\n                    do {\n\n                        if (this._readWhitespace()){\n                            functionText += tokenStream.token().value;\n                        }\n\n                        //might be second time in the loop\n                        if (tokenStream.LA(0) == Tokens.COMMA){\n                            functionText += tokenStream.token().value;\n                        }\n\n                        tokenStream.match(Tokens.IDENT);\n                        functionText += tokenStream.token().value;\n\n                        tokenStream.match(Tokens.EQUALS);\n                        functionText += tokenStream.token().value;\n\n                        //functionText += this._term();\n                        lt = tokenStream.peek();\n                        while(lt != Tokens.COMMA && lt != Tokens.S && lt != Tokens.RPAREN){\n                            tokenStream.get();\n                            functionText += tokenStream.token().value;\n                            lt = tokenStream.peek();\n                        }\n                    } while(tokenStream.match([Tokens.COMMA, Tokens.S]));\n\n                    tokenStream.match(Tokens.RPAREN);\n                    functionText += \")\";\n                    this._readWhitespace();\n                }\n\n                return functionText;\n            },\n\n            _hexcolor: function(){\n                /*\n                 * There is a constraint on the color that it must\n                 * have either 3 or 6 hex-digits (i.e., [0-9a-fA-F])\n                 * after the \"#\"; e.g., \"#000\" is OK, but \"#abcd\" is not.\n                 *\n                 * hexcolor\n                 *   : HASH S*\n                 *   ;\n                 */\n\n                var tokenStream = this._tokenStream,\n                    token = null,\n                    color;\n\n                if(tokenStream.match(Tokens.HASH)){\n\n                    //need to do some validation here\n\n                    token = tokenStream.token();\n                    color = token.value;\n                    if (!/#[a-f0-9]{3,6}/i.test(color)){\n                        throw new SyntaxError(\"Expected a hex color but found '\" + color + \"' at line \" + token.startLine + \", col \" + token.startCol + \".\", token.startLine, token.startCol);\n                    }\n                    this._readWhitespace();\n                }\n\n                return token;\n            },\n\n            //-----------------------------------------------------------------\n            // Animations methods\n            //-----------------------------------------------------------------\n\n            _keyframes: function(){\n\n                /*\n                 * keyframes:\n                 *   : KEYFRAMES_SYM S* keyframe_name S* '{' S* keyframe_rule* '}' {\n                 *   ;\n                 */\n                var tokenStream = this._tokenStream,\n                    token,\n                    tt,\n                    name,\n                    prefix = \"\";\n\n                tokenStream.mustMatch(Tokens.KEYFRAMES_SYM);\n                token = tokenStream.token();\n                if (/^@\\-([^\\-]+)\\-/.test(token.value)) {\n                    prefix = RegExp.$1;\n                }\n\n                this._readWhitespace();\n                name = this._keyframe_name();\n\n                this._readWhitespace();\n                tokenStream.mustMatch(Tokens.LBRACE);\n\n                this.fire({\n                    type:   \"startkeyframes\",\n                    name:   name,\n                    prefix: prefix,\n                    line:   token.startLine,\n                    col:    token.startCol\n                });\n\n                this._readWhitespace();\n                tt = tokenStream.peek();\n\n                //check for key\n                while(tt == Tokens.IDENT || tt == Tokens.PERCENTAGE) {\n                    this._keyframe_rule();\n                    this._readWhitespace();\n                    tt = tokenStream.peek();\n                }\n\n                this.fire({\n                    type:   \"endkeyframes\",\n                    name:   name,\n                    prefix: prefix,\n                    line:   token.startLine,\n                    col:    token.startCol\n                });\n\n                this._readWhitespace();\n                tokenStream.mustMatch(Tokens.RBRACE);\n\n            },\n\n            _keyframe_name: function(){\n\n                /*\n                 * keyframe_name:\n                 *   : IDENT\n                 *   | STRING\n                 *   ;\n                 */\n                var tokenStream = this._tokenStream,\n                    token;\n\n                tokenStream.mustMatch([Tokens.IDENT, Tokens.STRING]);\n                return SyntaxUnit.fromToken(tokenStream.token());\n            },\n\n            _keyframe_rule: function(){\n\n                /*\n                 * keyframe_rule:\n                 *   : key_list S*\n                 *     '{' S* declaration [ ';' S* declaration ]* '}' S*\n                 *   ;\n                 */\n                var tokenStream = this._tokenStream,\n                    token,\n                    keyList = this._key_list();\n\n                this.fire({\n                    type:   \"startkeyframerule\",\n                    keys:   keyList,\n                    line:   keyList[0].line,\n                    col:    keyList[0].col\n                });\n\n                this._readDeclarations(true);\n\n                this.fire({\n                    type:   \"endkeyframerule\",\n                    keys:   keyList,\n                    line:   keyList[0].line,\n                    col:    keyList[0].col\n                });\n\n            },\n\n            _key_list: function(){\n\n                /*\n                 * key_list:\n                 *   : key [ S* ',' S* key]*\n                 *   ;\n                 */\n                var tokenStream = this._tokenStream,\n                    token,\n                    key,\n                    keyList = [];\n\n                //must be least one key\n                keyList.push(this._key());\n\n                this._readWhitespace();\n\n                while(tokenStream.match(Tokens.COMMA)){\n                    this._readWhitespace();\n                    keyList.push(this._key());\n                    this._readWhitespace();\n                }\n\n                return keyList;\n            },\n\n            _key: function(){\n                /*\n                 * There is a restriction that IDENT can be only \"from\" or \"to\".\n                 *\n                 * key\n                 *   : PERCENTAGE\n                 *   | IDENT\n                 *   ;\n                 */\n\n                var tokenStream = this._tokenStream,\n                    token;\n\n                if (tokenStream.match(Tokens.PERCENTAGE)){\n                    return SyntaxUnit.fromToken(tokenStream.token());\n                } else if (tokenStream.match(Tokens.IDENT)){\n                    token = tokenStream.token();\n\n                    if (/from|to/i.test(token.value)){\n                        return SyntaxUnit.fromToken(token);\n                    }\n\n                    tokenStream.unget();\n                }\n\n                //if it gets here, there wasn't a valid token, so time to explode\n                this._unexpectedToken(tokenStream.LT(1));\n            },\n\n            //-----------------------------------------------------------------\n            // Helper methods\n            //-----------------------------------------------------------------\n\n            /**\n             * Not part of CSS grammar, but useful for skipping over\n             * combination of white space and HTML-style comments.\n             * @return {void}\n             * @method _skipCruft\n             * @private\n             */\n            _skipCruft: function(){\n                while(this._tokenStream.match([Tokens.S, Tokens.CDO, Tokens.CDC])){\n                    //noop\n                }\n            },\n\n            /**\n             * Not part of CSS grammar, but this pattern occurs frequently\n             * in the official CSS grammar. Split out here to eliminate\n             * duplicate code.\n             * @param {Boolean} checkStart Indicates if the rule should check\n             *      for the left brace at the beginning.\n             * @param {Boolean} readMargins Indicates if the rule should check\n             *      for margin patterns.\n             * @return {void}\n             * @method _readDeclarations\n             * @private\n             */\n            _readDeclarations: function(checkStart, readMargins){\n                /*\n                 * Reads the pattern\n                 * S* '{' S* declaration [ ';' S* declaration ]* '}' S*\n                 * or\n                 * S* '{' S* [ declaration | margin ]? [ ';' S* [ declaration | margin ]? ]* '}' S*\n                 * Note that this is how it is described in CSS3 Paged Media, but is actually incorrect.\n                 * A semicolon is only necessary following a delcaration is there's another declaration\n                 * or margin afterwards.\n                 */\n                var tokenStream = this._tokenStream,\n                    tt;\n\n\n                this._readWhitespace();\n\n                if (checkStart){\n                    tokenStream.mustMatch(Tokens.LBRACE);\n                }\n\n                this._readWhitespace();\n\n                try {\n\n                    while(true){\n\n                        if (tokenStream.match(Tokens.SEMICOLON) || (readMargins && this._margin())){\n                            //noop\n                        } else if (this._declaration()){\n                            if (!tokenStream.match(Tokens.SEMICOLON)){\n                                break;\n                            }\n                        } else {\n                            break;\n                        }\n\n                        //if ((!this._margin() && !this._declaration()) || !tokenStream.match(Tokens.SEMICOLON)){\n                        //    break;\n                        //}\n                        this._readWhitespace();\n                    }\n\n                    tokenStream.mustMatch(Tokens.RBRACE);\n                    this._readWhitespace();\n\n                } catch (ex) {\n                    if (ex instanceof SyntaxError && !this.options.strict){\n\n                        //fire error event\n                        this.fire({\n                            type:       \"error\",\n                            error:      ex,\n                            message:    ex.message,\n                            line:       ex.line,\n                            col:        ex.col\n                        });\n\n                        //see if there's another declaration\n                        tt = tokenStream.advance([Tokens.SEMICOLON, Tokens.RBRACE]);\n                        if (tt == Tokens.SEMICOLON){\n                            //if there's a semicolon, then there might be another declaration\n                            this._readDeclarations(false, readMargins);\n                        } else if (tt != Tokens.RBRACE){\n                            //if there's a right brace, the rule is finished so don't do anything\n                            //otherwise, rethrow the error because it wasn't handled properly\n                            throw ex;\n                        }\n\n                    } else {\n                        //not a syntax error, rethrow it\n                        throw ex;\n                    }\n                }\n\n            },\n\n            /**\n             * In some cases, you can end up with two white space tokens in a\n             * row. Instead of making a change in every function that looks for\n             * white space, this function is used to match as much white space\n             * as necessary.\n             * @method _readWhitespace\n             * @return {String} The white space if found, empty string if not.\n             * @private\n             */\n            _readWhitespace: function(){\n\n                var tokenStream = this._tokenStream,\n                    ws = \"\";\n\n                while(tokenStream.match(Tokens.S)){\n                    ws += tokenStream.token().value;\n                }\n\n                return ws;\n            },\n\n\n            /**\n             * Throws an error when an unexpected token is found.\n             * @param {Object} token The token that was found.\n             * @method _unexpectedToken\n             * @return {void}\n             * @private\n             */\n            _unexpectedToken: function(token){\n                throw new SyntaxError(\"Unexpected token '\" + token.value + \"' at line \" + token.startLine + \", col \" + token.startCol + \".\", token.startLine, token.startCol);\n            },\n\n            /**\n             * Helper method used for parsing subparts of a style sheet.\n             * @return {void}\n             * @method _verifyEnd\n             * @private\n             */\n            _verifyEnd: function(){\n                if (this._tokenStream.LA(1) != Tokens.EOF){\n                    this._unexpectedToken(this._tokenStream.LT(1));\n                }\n            },\n\n            //-----------------------------------------------------------------\n            // Validation methods\n            //-----------------------------------------------------------------\n            _validateProperty: function(property, value){\n                Validation.validate(property, value);\n            },\n\n            //-----------------------------------------------------------------\n            // Parsing methods\n            //-----------------------------------------------------------------\n\n            parse: function(input){\n                this._tokenStream = new TokenStream(input, Tokens);\n                this._stylesheet();\n            },\n\n            parseStyleSheet: function(input){\n                //just passthrough\n                return this.parse(input);\n            },\n\n            parseMediaQuery: function(input){\n                this._tokenStream = new TokenStream(input, Tokens);\n                var result = this._media_query();\n\n                //if there's anything more, then it's an invalid selector\n                this._verifyEnd();\n\n                //otherwise return result\n                return result;\n            },\n\n            /**\n             * Parses a property value (everything after the semicolon).\n             * @return {parserlib.css.PropertyValue} The property value.\n             * @throws parserlib.util.SyntaxError If an unexpected token is found.\n             * @method parserPropertyValue\n             */\n            parsePropertyValue: function(input){\n\n                this._tokenStream = new TokenStream(input, Tokens);\n                this._readWhitespace();\n\n                var result = this._expr();\n\n                //okay to have a trailing white space\n                this._readWhitespace();\n\n                //if there's anything more, then it's an invalid selector\n                this._verifyEnd();\n\n                //otherwise return result\n                return result;\n            },\n\n            /**\n             * Parses a complete CSS rule, including selectors and\n             * properties.\n             * @param {String} input The text to parser.\n             * @return {Boolean} True if the parse completed successfully, false if not.\n             * @method parseRule\n             */\n            parseRule: function(input){\n                this._tokenStream = new TokenStream(input, Tokens);\n\n                //skip any leading white space\n                this._readWhitespace();\n\n                var result = this._ruleset();\n\n                //skip any trailing white space\n                this._readWhitespace();\n\n                //if there's anything more, then it's an invalid selector\n                this._verifyEnd();\n\n                //otherwise return result\n                return result;\n            },\n\n            /**\n             * Parses a single CSS selector (no comma)\n             * @param {String} input The text to parse as a CSS selector.\n             * @return {Selector} An object representing the selector.\n             * @throws parserlib.util.SyntaxError If an unexpected token is found.\n             * @method parseSelector\n             */\n            parseSelector: function(input){\n\n                this._tokenStream = new TokenStream(input, Tokens);\n\n                //skip any leading white space\n                this._readWhitespace();\n\n                var result = this._selector();\n\n                //skip any trailing white space\n                this._readWhitespace();\n\n                //if there's anything more, then it's an invalid selector\n                this._verifyEnd();\n\n                //otherwise return result\n                return result;\n            },\n\n            /**\n             * Parses an HTML style attribute: a set of CSS declarations\n             * separated by semicolons.\n             * @param {String} input The text to parse as a style attribute\n             * @return {void}\n             * @method parseStyleAttribute\n             */\n            parseStyleAttribute: function(input){\n                input += \"}\"; // for error recovery in _readDeclarations()\n                this._tokenStream = new TokenStream(input, Tokens);\n                this._readDeclarations();\n            }\n        };\n\n    //copy over onto prototype\n    for (prop in additions){\n        if (additions.hasOwnProperty(prop)){\n            proto[prop] = additions[prop];\n        }\n    }\n\n    return proto;\n}();\n\n\n/*\nnth\n  : S* [ ['-'|'+']? INTEGER? {N} [ S* ['-'|'+'] S* INTEGER ]? |\n         ['-'|'+']? INTEGER | {O}{D}{D} | {E}{V}{E}{N} ] S*\n  ;\n*/\n/*global Validation, ValidationTypes, ValidationError*/\nvar Properties = {\n\n    //A\n    \"alignment-adjust\"              : \"auto | baseline | before-edge | text-before-edge | middle | central | after-edge | text-after-edge | ideographic | alphabetic | hanging | mathematical | <percentage> | <length>\",\n    \"alignment-baseline\"            : \"baseline | use-script | before-edge | text-before-edge | after-edge | text-after-edge | central | middle | ideographic | alphabetic | hanging | mathematical\",\n    \"animation\"                     : 1,\n    \"animation-delay\"               : { multi: \"<time>\", comma: true },\n    \"animation-direction\"           : { multi: \"normal | alternate\", comma: true },\n    \"animation-duration\"            : { multi: \"<time>\", comma: true },\n    \"animation-iteration-count\"     : { multi: \"<number> | infinite\", comma: true },\n    \"animation-name\"                : { multi: \"none | <ident>\", comma: true },\n    \"animation-play-state\"          : { multi: \"running | paused\", comma: true },\n    \"animation-timing-function\"     : 1,\n\n    //vendor prefixed\n    \"-moz-animation-delay\"               : { multi: \"<time>\", comma: true },\n    \"-moz-animation-direction\"           : { multi: \"normal | alternate\", comma: true },\n    \"-moz-animation-duration\"            : { multi: \"<time>\", comma: true },\n    \"-moz-animation-iteration-count\"     : { multi: \"<number> | infinite\", comma: true },\n    \"-moz-animation-name\"                : { multi: \"none | <ident>\", comma: true },\n    \"-moz-animation-play-state\"          : { multi: \"running | paused\", comma: true },\n\n    \"-ms-animation-delay\"               : { multi: \"<time>\", comma: true },\n    \"-ms-animation-direction\"           : { multi: \"normal | alternate\", comma: true },\n    \"-ms-animation-duration\"            : { multi: \"<time>\", comma: true },\n    \"-ms-animation-iteration-count\"     : { multi: \"<number> | infinite\", comma: true },\n    \"-ms-animation-name\"                : { multi: \"none | <ident>\", comma: true },\n    \"-ms-animation-play-state\"          : { multi: \"running | paused\", comma: true },\n\n    \"-webkit-animation-delay\"               : { multi: \"<time>\", comma: true },\n    \"-webkit-animation-direction\"           : { multi: \"normal | alternate\", comma: true },\n    \"-webkit-animation-duration\"            : { multi: \"<time>\", comma: true },\n    \"-webkit-animation-iteration-count\"     : { multi: \"<number> | infinite\", comma: true },\n    \"-webkit-animation-name\"                : { multi: \"none | <ident>\", comma: true },\n    \"-webkit-animation-play-state\"          : { multi: \"running | paused\", comma: true },\n\n    \"-o-animation-delay\"               : { multi: \"<time>\", comma: true },\n    \"-o-animation-direction\"           : { multi: \"normal | alternate\", comma: true },\n    \"-o-animation-duration\"            : { multi: \"<time>\", comma: true },\n    \"-o-animation-iteration-count\"     : { multi: \"<number> | infinite\", comma: true },\n    \"-o-animation-name\"                : { multi: \"none | <ident>\", comma: true },\n    \"-o-animation-play-state\"          : { multi: \"running | paused\", comma: true },\n\n    \"appearance\"                    : \"icon | window | desktop | workspace | document | tooltip | dialog | button | push-button | hyperlink | radio-button | checkbox | menu-item | tab | menu | menubar | pull-down-menu | pop-up-menu | list-menu | radio-group | checkbox-group | outline-tree | range | field | combo-box | signature | password | normal | none | inherit\",\n    \"azimuth\"                       : function (expression) {\n        var simple      = \"<angle> | leftwards | rightwards | inherit\",\n            direction   = \"left-side | far-left | left | center-left | center | center-right | right | far-right | right-side\",\n            behind      = false,\n            valid       = false,\n            part;\n\n        if (!ValidationTypes.isAny(expression, simple)) {\n            if (ValidationTypes.isAny(expression, \"behind\")) {\n                behind = true;\n                valid = true;\n            }\n\n            if (ValidationTypes.isAny(expression, direction)) {\n                valid = true;\n                if (!behind) {\n                    ValidationTypes.isAny(expression, \"behind\");\n                }\n            }\n        }\n\n        if (expression.hasNext()) {\n            part = expression.next();\n            if (valid) {\n                throw new ValidationError(\"Expected end of value but found '\" + part + \"'.\", part.line, part.col);\n            } else {\n                throw new ValidationError(\"Expected (<'azimuth'>) but found '\" + part + \"'.\", part.line, part.col);\n            }\n        }\n    },\n\n    //B\n    \"backface-visibility\"           : \"visible | hidden\",\n    \"background\"                    : 1,\n    \"background-attachment\"         : { multi: \"<attachment>\", comma: true },\n    \"background-clip\"               : { multi: \"<box>\", comma: true },\n    \"background-color\"              : \"<color> | inherit\",\n    \"background-image\"              : { multi: \"<bg-image>\", comma: true },\n    \"background-origin\"             : { multi: \"<box>\", comma: true },\n    \"background-position\"           : { multi: \"<bg-position>\", comma: true },\n    \"background-repeat\"             : { multi: \"<repeat-style>\" },\n    \"background-size\"               : { multi: \"<bg-size>\", comma: true },\n    \"baseline-shift\"                : \"baseline | sub | super | <percentage> | <length>\",\n    \"behavior\"                      : 1,\n    \"binding\"                       : 1,\n    \"bleed\"                         : \"<length>\",\n    \"bookmark-label\"                : \"<content> | <attr> | <string>\",\n    \"bookmark-level\"                : \"none | <integer>\",\n    \"bookmark-state\"                : \"open | closed\",\n    \"bookmark-target\"               : \"none | <uri> | <attr>\",\n    \"border\"                        : \"<border-width> || <border-style> || <color>\",\n    \"border-bottom\"                 : \"<border-width> || <border-style> || <color>\",\n    \"border-bottom-color\"           : \"<color>\",\n    \"border-bottom-left-radius\"     :  \"<x-one-radius>\",\n    \"border-bottom-right-radius\"    :  \"<x-one-radius>\",\n    \"border-bottom-style\"           : \"<border-style>\",\n    \"border-bottom-width\"           : \"<border-width>\",\n    \"border-collapse\"               : \"collapse | separate | inherit\",\n    \"border-color\"                  : { multi: \"<color> | inherit\", max: 4 },\n    \"border-image\"                  : 1,\n    \"border-image-outset\"           : { multi: \"<length> | <number>\", max: 4 },\n    \"border-image-repeat\"           : { multi: \"stretch | repeat | round\", max: 2 },\n    \"border-image-slice\"            : function(expression) {\n\n        var valid   = false,\n            numeric = \"<number> | <percentage>\",\n            fill    = false,\n            count   = 0,\n            max     = 4,\n            part;\n\n        if (ValidationTypes.isAny(expression, \"fill\")) {\n            fill = true;\n            valid = true;\n        }\n\n        while (expression.hasNext() && count < max) {\n            valid = ValidationTypes.isAny(expression, numeric);\n            if (!valid) {\n                break;\n            }\n            count++;\n        }\n\n\n        if (!fill) {\n            ValidationTypes.isAny(expression, \"fill\");\n        } else {\n            valid = true;\n        }\n\n        if (expression.hasNext()) {\n            part = expression.next();\n            if (valid) {\n                throw new ValidationError(\"Expected end of value but found '\" + part + \"'.\", part.line, part.col);\n            } else {\n                throw new ValidationError(\"Expected ([<number> | <percentage>]{1,4} && fill?) but found '\" + part + \"'.\", part.line, part.col);\n            }\n        }\n    },\n    \"border-image-source\"           : \"<image> | none\",\n    \"border-image-width\"            : { multi: \"<length> | <percentage> | <number> | auto\", max: 4 },\n    \"border-left\"                   : \"<border-width> || <border-style> || <color>\",\n    \"border-left-color\"             : \"<color> | inherit\",\n    \"border-left-style\"             : \"<border-style>\",\n    \"border-left-width\"             : \"<border-width>\",\n    \"border-radius\"                 : function(expression) {\n\n        var valid   = false,\n            numeric = \"<length> | <percentage>\",\n            slash   = false,\n            fill    = false,\n            count   = 0,\n            max     = 8,\n            part;\n\n        while (expression.hasNext() && count < max) {\n            valid = ValidationTypes.isAny(expression, numeric);\n            if (!valid) {\n\n                if (expression.peek() == \"/\" && count > 0 && !slash) {\n                    slash = true;\n                    max = count + 5;\n                    expression.next();\n                } else {\n                    break;\n                }\n            }\n            count++;\n        }\n\n        if (expression.hasNext()) {\n            part = expression.next();\n            if (valid) {\n                throw new ValidationError(\"Expected end of value but found '\" + part + \"'.\", part.line, part.col);\n            } else {\n                throw new ValidationError(\"Expected (<'border-radius'>) but found '\" + part + \"'.\", part.line, part.col);\n            }\n        }\n    },\n    \"border-right\"                  : \"<border-width> || <border-style> || <color>\",\n    \"border-right-color\"            : \"<color> | inherit\",\n    \"border-right-style\"            : \"<border-style>\",\n    \"border-right-width\"            : \"<border-width>\",\n    \"border-spacing\"                : { multi: \"<length> | inherit\", max: 2 },\n    \"border-style\"                  : { multi: \"<border-style>\", max: 4 },\n    \"border-top\"                    : \"<border-width> || <border-style> || <color>\",\n    \"border-top-color\"              : \"<color> | inherit\",\n    \"border-top-left-radius\"        : \"<x-one-radius>\",\n    \"border-top-right-radius\"       : \"<x-one-radius>\",\n    \"border-top-style\"              : \"<border-style>\",\n    \"border-top-width\"              : \"<border-width>\",\n    \"border-width\"                  : { multi: \"<border-width>\", max: 4 },\n    \"bottom\"                        : \"<margin-width> | inherit\",\n    \"box-align\"                     : \"start | end | center | baseline | stretch\",        //http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/\n    \"box-decoration-break\"          : \"slice |clone\",\n    \"box-direction\"                 : \"normal | reverse | inherit\",\n    \"box-flex\"                      : \"<number>\",\n    \"box-flex-group\"                : \"<integer>\",\n    \"box-lines\"                     : \"single | multiple\",\n    \"box-ordinal-group\"             : \"<integer>\",\n    \"box-orient\"                    : \"horizontal | vertical | inline-axis | block-axis | inherit\",\n    \"box-pack\"                      : \"start | end | center | justify\",\n    \"box-shadow\"                    : function (expression) {\n        var result      = false,\n            part;\n\n        if (!ValidationTypes.isAny(expression, \"none\")) {\n            Validation.multiProperty(\"<shadow>\", expression, true, Infinity);\n        } else {\n            if (expression.hasNext()) {\n                part = expression.next();\n                throw new ValidationError(\"Expected end of value but found '\" + part + \"'.\", part.line, part.col);\n            }\n        }\n    },\n    \"box-sizing\"                    : \"content-box | border-box | inherit\",\n    \"break-after\"                   : \"auto | always | avoid | left | right | page | column | avoid-page | avoid-column\",\n    \"break-before\"                  : \"auto | always | avoid | left | right | page | column | avoid-page | avoid-column\",\n    \"break-inside\"                  : \"auto | avoid | avoid-page | avoid-column\",\n\n    //C\n    \"caption-side\"                  : \"top | bottom | inherit\",\n    \"clear\"                         : \"none | right | left | both | inherit\",\n    \"clip\"                          : 1,\n    \"color\"                         : \"<color> | inherit\",\n    \"color-profile\"                 : 1,\n    \"column-count\"                  : \"<integer> | auto\",                      //http://www.w3.org/TR/css3-multicol/\n    \"column-fill\"                   : \"auto | balance\",\n    \"column-gap\"                    : \"<length> | normal\",\n    \"column-rule\"                   : \"<border-width> || <border-style> || <color>\",\n    \"column-rule-color\"             : \"<color>\",\n    \"column-rule-style\"             : \"<border-style>\",\n    \"column-rule-width\"             : \"<border-width>\",\n    \"column-span\"                   : \"none | all\",\n    \"column-width\"                  : \"<length> | auto\",\n    \"columns\"                       : 1,\n    \"content\"                       : 1,\n    \"counter-increment\"             : 1,\n    \"counter-reset\"                 : 1,\n    \"crop\"                          : \"<shape> | auto\",\n    \"cue\"                           : \"cue-after | cue-before | inherit\",\n    \"cue-after\"                     : 1,\n    \"cue-before\"                    : 1,\n    \"cursor\"                        : 1,\n\n    //D\n    \"direction\"                     : \"ltr | rtl | inherit\",\n    \"display\"                       : \"inline | block | list-item | inline-block | table | inline-table | table-row-group | table-header-group | table-footer-group | table-row | table-column-group | table-column | table-cell | table-caption | box | inline-box | grid | inline-grid | none | inherit | -moz-box | -moz-inline-block | -moz-inline-box | -moz-inline-grid | -moz-inline-stack | -moz-inline-table | -moz-grid | -moz-grid-group | -moz-grid-line | -moz-groupbox | -moz-deck | -moz-popup | -moz-stack | -moz-marker\",\n    \"dominant-baseline\"             : 1,\n    \"drop-initial-after-adjust\"     : \"central | middle | after-edge | text-after-edge | ideographic | alphabetic | mathematical | <percentage> | <length>\",\n    \"drop-initial-after-align\"      : \"baseline | use-script | before-edge | text-before-edge | after-edge | text-after-edge | central | middle | ideographic | alphabetic | hanging | mathematical\",\n    \"drop-initial-before-adjust\"    : \"before-edge | text-before-edge | central | middle | hanging | mathematical | <percentage> | <length>\",\n    \"drop-initial-before-align\"     : \"caps-height | baseline | use-script | before-edge | text-before-edge | after-edge | text-after-edge | central | middle | ideographic | alphabetic | hanging | mathematical\",\n    \"drop-initial-size\"             : \"auto | line | <length> | <percentage>\",\n    \"drop-initial-value\"            : \"initial | <integer>\",\n\n    //E\n    \"elevation\"                     : \"<angle> | below | level | above | higher | lower | inherit\",\n    \"empty-cells\"                   : \"show | hide | inherit\",\n\n    //F\n    \"filter\"                        : 1,\n    \"fit\"                           : \"fill | hidden | meet | slice\",\n    \"fit-position\"                  : 1,\n    \"float\"                         : \"left | right | none | inherit\",\n    \"float-offset\"                  : 1,\n    \"font\"                          : 1,\n    \"font-family\"                   : 1,\n    \"font-size\"                     : \"<absolute-size> | <relative-size> | <length> | <percentage> | inherit\",\n    \"font-size-adjust\"              : \"<number> | none | inherit\",\n    \"font-stretch\"                  : \"normal | ultra-condensed | extra-condensed | condensed | semi-condensed | semi-expanded | expanded | extra-expanded | ultra-expanded | inherit\",\n    \"font-style\"                    : \"normal | italic | oblique | inherit\",\n    \"font-variant\"                  : \"normal | small-caps | inherit\",\n    \"font-weight\"                   : \"normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit\",\n\n    //G\n    \"grid-cell-stacking\"            : \"columns | rows | layer\",\n    \"grid-column\"                   : 1,\n    \"grid-columns\"                  : 1,\n    \"grid-column-align\"             : \"start | end | center | stretch\",\n    \"grid-column-sizing\"            : 1,\n    \"grid-column-span\"              : \"<integer>\",\n    \"grid-flow\"                     : \"none | rows | columns\",\n    \"grid-layer\"                    : \"<integer>\",\n    \"grid-row\"                      : 1,\n    \"grid-rows\"                     : 1,\n    \"grid-row-align\"                : \"start | end | center | stretch\",\n    \"grid-row-span\"                 : \"<integer>\",\n    \"grid-row-sizing\"               : 1,\n\n    //H\n    \"hanging-punctuation\"           : 1,\n    \"height\"                        : \"<margin-width> | inherit\",\n    \"hyphenate-after\"               : \"<integer> | auto\",\n    \"hyphenate-before\"              : \"<integer> | auto\",\n    \"hyphenate-character\"           : \"<string> | auto\",\n    \"hyphenate-lines\"               : \"no-limit | <integer>\",\n    \"hyphenate-resource\"            : 1,\n    \"hyphens\"                       : \"none | manual | auto\",\n\n    //I\n    \"icon\"                          : 1,\n    \"image-orientation\"             : \"angle | auto\",\n    \"image-rendering\"               : 1,\n    \"image-resolution\"              : 1,\n    \"inline-box-align\"              : \"initial | last | <integer>\",\n\n    //L\n    \"left\"                          : \"<margin-width> | inherit\",\n    \"letter-spacing\"                : \"<length> | normal | inherit\",\n    \"line-height\"                   : \"<number> | <length> | <percentage> | normal | inherit\",\n    \"line-break\"                    : \"auto | loose | normal | strict\",\n    \"line-stacking\"                 : 1,\n    \"line-stacking-ruby\"            : \"exclude-ruby | include-ruby\",\n    \"line-stacking-shift\"           : \"consider-shifts | disregard-shifts\",\n    \"line-stacking-strategy\"        : \"inline-line-height | block-line-height | max-height | grid-height\",\n    \"list-style\"                    : 1,\n    \"list-style-image\"              : \"<uri> | none | inherit\",\n    \"list-style-position\"           : \"inside | outside | inherit\",\n    \"list-style-type\"               : \"disc | circle | square | decimal | decimal-leading-zero | lower-roman | upper-roman | lower-greek | lower-latin | upper-latin | armenian | georgian | lower-alpha | upper-alpha | none | inherit\",\n\n    //M\n    \"margin\"                        : { multi: \"<margin-width> | inherit\", max: 4 },\n    \"margin-bottom\"                 : \"<margin-width> | inherit\",\n    \"margin-left\"                   : \"<margin-width> | inherit\",\n    \"margin-right\"                  : \"<margin-width> | inherit\",\n    \"margin-top\"                    : \"<margin-width> | inherit\",\n    \"mark\"                          : 1,\n    \"mark-after\"                    : 1,\n    \"mark-before\"                   : 1,\n    \"marks\"                         : 1,\n    \"marquee-direction\"             : 1,\n    \"marquee-play-count\"            : 1,\n    \"marquee-speed\"                 : 1,\n    \"marquee-style\"                 : 1,\n    \"max-height\"                    : \"<length> | <percentage> | none | inherit\",\n    \"max-width\"                     : \"<length> | <percentage> | none | inherit\",\n    \"min-height\"                    : \"<length> | <percentage> | inherit\",\n    \"min-width\"                     : \"<length> | <percentage> | inherit\",\n    \"move-to\"                       : 1,\n\n    //N\n    \"nav-down\"                      : 1,\n    \"nav-index\"                     : 1,\n    \"nav-left\"                      : 1,\n    \"nav-right\"                     : 1,\n    \"nav-up\"                        : 1,\n\n    //O\n    \"opacity\"                       : \"<number> | inherit\",\n    \"orphans\"                       : \"<integer> | inherit\",\n    \"outline\"                       : 1,\n    \"outline-color\"                 : \"<color> | invert | inherit\",\n    \"outline-offset\"                : 1,\n    \"outline-style\"                 : \"<border-style> | inherit\",\n    \"outline-width\"                 : \"<border-width> | inherit\",\n    \"overflow\"                      : \"visible | hidden | scroll | auto | inherit\",\n    \"overflow-style\"                : 1,\n    \"overflow-x\"                    : 1,\n    \"overflow-y\"                    : 1,\n\n    //P\n    \"padding\"                       : { multi: \"<padding-width> | inherit\", max: 4 },\n    \"padding-bottom\"                : \"<padding-width> | inherit\",\n    \"padding-left\"                  : \"<padding-width> | inherit\",\n    \"padding-right\"                 : \"<padding-width> | inherit\",\n    \"padding-top\"                   : \"<padding-width> | inherit\",\n    \"page\"                          : 1,\n    \"page-break-after\"              : \"auto | always | avoid | left | right | inherit\",\n    \"page-break-before\"             : \"auto | always | avoid | left | right | inherit\",\n    \"page-break-inside\"             : \"auto | avoid | inherit\",\n    \"page-policy\"                   : 1,\n    \"pause\"                         : 1,\n    \"pause-after\"                   : 1,\n    \"pause-before\"                  : 1,\n    \"perspective\"                   : 1,\n    \"perspective-origin\"            : 1,\n    \"phonemes\"                      : 1,\n    \"pitch\"                         : 1,\n    \"pitch-range\"                   : 1,\n    \"play-during\"                   : 1,\n    \"pointer-events\"                : \"auto | none | visiblePainted | visibleFill | visibleStroke | visible | painted | fill | stroke | all | inherit\",\n    \"position\"                      : \"static | relative | absolute | fixed | inherit\",\n    \"presentation-level\"            : 1,\n    \"punctuation-trim\"              : 1,\n\n    //Q\n    \"quotes\"                        : 1,\n\n    //R\n    \"rendering-intent\"              : 1,\n    \"resize\"                        : 1,\n    \"rest\"                          : 1,\n    \"rest-after\"                    : 1,\n    \"rest-before\"                   : 1,\n    \"richness\"                      : 1,\n    \"right\"                         : \"<margin-width> | inherit\",\n    \"rotation\"                      : 1,\n    \"rotation-point\"                : 1,\n    \"ruby-align\"                    : 1,\n    \"ruby-overhang\"                 : 1,\n    \"ruby-position\"                 : 1,\n    \"ruby-span\"                     : 1,\n\n    //S\n    \"size\"                          : 1,\n    \"speak\"                         : \"normal | none | spell-out | inherit\",\n    \"speak-header\"                  : \"once | always | inherit\",\n    \"speak-numeral\"                 : \"digits | continuous | inherit\",\n    \"speak-punctuation\"             : \"code | none | inherit\",\n    \"speech-rate\"                   : 1,\n    \"src\"                           : 1,\n    \"stress\"                        : 1,\n    \"string-set\"                    : 1,\n\n    \"table-layout\"                  : \"auto | fixed | inherit\",\n    \"tab-size\"                      : \"<integer> | <length>\",\n    \"target\"                        : 1,\n    \"target-name\"                   : 1,\n    \"target-new\"                    : 1,\n    \"target-position\"               : 1,\n    \"text-align\"                    : \"left | right | center | justify | inherit\" ,\n    \"text-align-last\"               : 1,\n    \"text-decoration\"               : 1,\n    \"text-emphasis\"                 : 1,\n    \"text-height\"                   : 1,\n    \"text-indent\"                   : \"<length> | <percentage> | inherit\",\n    \"text-justify\"                  : \"auto | none | inter-word | inter-ideograph | inter-cluster | distribute | kashida\",\n    \"text-outline\"                  : 1,\n    \"text-overflow\"                 : 1,\n    \"text-rendering\"                : \"auto | optimizeSpeed | optimizeLegibility | geometricPrecision | inherit\",\n    \"text-shadow\"                   : 1,\n    \"text-transform\"                : \"capitalize | uppercase | lowercase | none | inherit\",\n    \"text-wrap\"                     : \"normal | none | avoid\",\n    \"top\"                           : \"<margin-width> | inherit\",\n    \"transform\"                     : 1,\n    \"transform-origin\"              : 1,\n    \"transform-style\"               : 1,\n    \"transition\"                    : 1,\n    \"transition-delay\"              : 1,\n    \"transition-duration\"           : 1,\n    \"transition-property\"           : 1,\n    \"transition-timing-function\"    : 1,\n\n    //U\n    \"unicode-bidi\"                  : \"normal | embed | bidi-override | inherit\",\n    \"user-modify\"                   : \"read-only | read-write | write-only | inherit\",\n    \"user-select\"                   : \"none | text | toggle | element | elements | all | inherit\",\n\n    //V\n    \"vertical-align\"                : \"auto | use-script | baseline | sub | super | top | text-top | central | middle | bottom | text-bottom | <percentage> | <length>\",\n    \"visibility\"                    : \"visible | hidden | collapse | inherit\",\n    \"voice-balance\"                 : 1,\n    \"voice-duration\"                : 1,\n    \"voice-family\"                  : 1,\n    \"voice-pitch\"                   : 1,\n    \"voice-pitch-range\"             : 1,\n    \"voice-rate\"                    : 1,\n    \"voice-stress\"                  : 1,\n    \"voice-volume\"                  : 1,\n    \"volume\"                        : 1,\n\n    //W\n    \"white-space\"                   : \"normal | pre | nowrap | pre-wrap | pre-line | inherit | -pre-wrap | -o-pre-wrap | -moz-pre-wrap | -hp-pre-wrap\", //http://perishablepress.com/wrapping-content/\n    \"white-space-collapse\"          : 1,\n    \"widows\"                        : \"<integer> | inherit\",\n    \"width\"                         : \"<length> | <percentage> | auto | inherit\" ,\n    \"word-break\"                    : \"normal | keep-all | break-all\",\n    \"word-spacing\"                  : \"<length> | normal | inherit\",\n    \"word-wrap\"                     : 1,\n\n    //Z\n    \"z-index\"                       : \"<integer> | auto | inherit\",\n    \"zoom\"                          : \"<number> | <percentage> | normal\"\n};\n/*global SyntaxUnit, Parser*/\n/**\n * Represents a selector combinator (whitespace, +, >).\n * @namespace parserlib.css\n * @class PropertyName\n * @extends parserlib.util.SyntaxUnit\n * @constructor\n * @param {String} text The text representation of the unit.\n * @param {String} hack The type of IE hack applied (\"*\", \"_\", or null).\n * @param {int} line The line of text on which the unit resides.\n * @param {int} col The column of text on which the unit resides.\n */\nfunction PropertyName(text, hack, line, col){\n\n    SyntaxUnit.call(this, text, line, col, Parser.PROPERTY_NAME_TYPE);\n\n    /**\n     * The type of IE hack applied (\"*\", \"_\", or null).\n     * @type String\n     * @property hack\n     */\n    this.hack = hack;\n\n}\n\nPropertyName.prototype = new SyntaxUnit();\nPropertyName.prototype.constructor = PropertyName;\nPropertyName.prototype.toString = function(){\n    return (this.hack ? this.hack : \"\") + this.text;\n};\n\n/*global SyntaxUnit, Parser*/\n/**\n * Represents a single part of a CSS property value, meaning that it represents\n * just everything single part between \":\" and \";\". If there are multiple values\n * separated by commas, this type represents just one of the values.\n * @param {String[]} parts An array of value parts making up this value.\n * @param {int} line The line of text on which the unit resides.\n * @param {int} col The column of text on which the unit resides.\n * @namespace parserlib.css\n * @class PropertyValue\n * @extends parserlib.util.SyntaxUnit\n * @constructor\n */\nfunction PropertyValue(parts, line, col){\n\n    SyntaxUnit.call(this, parts.join(\" \"), line, col, Parser.PROPERTY_VALUE_TYPE);\n\n    /**\n     * The parts that make up the selector.\n     * @type Array\n     * @property parts\n     */\n    this.parts = parts;\n\n}\n\nPropertyValue.prototype = new SyntaxUnit();\nPropertyValue.prototype.constructor = PropertyValue;\n\n\n/*global SyntaxUnit, Parser*/\n/**\n * A utility class that allows for easy iteration over the various parts of a\n * property value.\n * @param {parserlib.css.PropertyValue} value The property value to iterate over.\n * @namespace parserlib.css\n * @class PropertyValueIterator\n * @constructor\n */\nfunction PropertyValueIterator(value){\n\n    /**\n     * Iterator value\n     * @type int\n     * @property _i\n     * @private\n     */\n    this._i = 0;\n\n    /**\n     * The parts that make up the value.\n     * @type Array\n     * @property _parts\n     * @private\n     */\n    this._parts = value.parts;\n\n    /**\n     * Keeps track of bookmarks along the way.\n     * @type Array\n     * @property _marks\n     * @private\n     */\n    this._marks = [];\n\n    /**\n     * Holds the original property value.\n     * @type parserlib.css.PropertyValue\n     * @property value\n     */\n    this.value = value;\n\n}\n\n/**\n * Returns the total number of parts in the value.\n * @return {int} The total number of parts in the value.\n * @method count\n */\nPropertyValueIterator.prototype.count = function(){\n    return this._parts.length;\n};\n\n/**\n * Indicates if the iterator is positioned at the first item.\n * @return {Boolean} True if positioned at first item, false if not.\n * @method isFirst\n */\nPropertyValueIterator.prototype.isFirst = function(){\n    return this._i === 0;\n};\n\n/**\n * Indicates if there are more parts of the property value.\n * @return {Boolean} True if there are more parts, false if not.\n * @method hasNext\n */\nPropertyValueIterator.prototype.hasNext = function(){\n    return (this._i < this._parts.length);\n};\n\n/**\n * Marks the current spot in the iteration so it can be restored to\n * later on.\n * @return {void}\n * @method mark\n */\nPropertyValueIterator.prototype.mark = function(){\n    this._marks.push(this._i);\n};\n\n/**\n * Returns the next part of the property value or null if there is no next\n * part. Does not move the internal counter forward.\n * @return {parserlib.css.PropertyValuePart} The next part of the property value or null if there is no next\n * part.\n * @method peek\n */\nPropertyValueIterator.prototype.peek = function(count){\n    return this.hasNext() ? this._parts[this._i + (count || 0)] : null;\n};\n\n/**\n * Returns the next part of the property value or null if there is no next\n * part.\n * @return {parserlib.css.PropertyValuePart} The next part of the property value or null if there is no next\n * part.\n * @method next\n */\nPropertyValueIterator.prototype.next = function(){\n    return this.hasNext() ? this._parts[this._i++] : null;\n};\n\n/**\n * Returns the previous part of the property value or null if there is no\n * previous part.\n * @return {parserlib.css.PropertyValuePart} The previous part of the\n * property value or null if there is no next part.\n * @method previous\n */\nPropertyValueIterator.prototype.previous = function(){\n    return this._i > 0 ? this._parts[--this._i] : null;\n};\n\n/**\n * Restores the last saved bookmark.\n * @return {void}\n * @method restore\n */\nPropertyValueIterator.prototype.restore = function(){\n    if (this._marks.length){\n        this._i = this._marks.pop();\n    }\n};\n\n\n/*global SyntaxUnit, Parser, Colors*/\n/**\n * Represents a single part of a CSS property value, meaning that it represents\n * just one part of the data between \":\" and \";\".\n * @param {String} text The text representation of the unit.\n * @param {int} line The line of text on which the unit resides.\n * @param {int} col The column of text on which the unit resides.\n * @namespace parserlib.css\n * @class PropertyValuePart\n * @extends parserlib.util.SyntaxUnit\n * @constructor\n */\nfunction PropertyValuePart(text, line, col){\n\n    SyntaxUnit.call(this, text, line, col, Parser.PROPERTY_VALUE_PART_TYPE);\n\n    /**\n     * Indicates the type of value unit.\n     * @type String\n     * @property type\n     */\n    this.type = \"unknown\";\n\n    //figure out what type of data it is\n\n    var temp;\n\n    //it is a measurement?\n    if (/^([+\\-]?[\\d\\.]+)([a-z]+)$/i.test(text)){  //dimension\n        this.type = \"dimension\";\n        this.value = +RegExp.$1;\n        this.units = RegExp.$2;\n\n        //try to narrow down\n        switch(this.units.toLowerCase()){\n\n            case \"em\":\n            case \"rem\":\n            case \"ex\":\n            case \"px\":\n            case \"cm\":\n            case \"mm\":\n            case \"in\":\n            case \"pt\":\n            case \"pc\":\n            case \"ch\":\n                this.type = \"length\";\n                break;\n\n            case \"deg\":\n            case \"rad\":\n            case \"grad\":\n                this.type = \"angle\";\n                break;\n\n            case \"ms\":\n            case \"s\":\n                this.type = \"time\";\n                break;\n\n            case \"hz\":\n            case \"khz\":\n                this.type = \"frequency\";\n                break;\n\n            case \"dpi\":\n            case \"dpcm\":\n                this.type = \"resolution\";\n                break;\n\n            //default\n\n        }\n\n    } else if (/^([+\\-]?[\\d\\.]+)%$/i.test(text)){  //percentage\n        this.type = \"percentage\";\n        this.value = +RegExp.$1;\n    } else if (/^([+\\-]?[\\d\\.]+)%$/i.test(text)){  //percentage\n        this.type = \"percentage\";\n        this.value = +RegExp.$1;\n    } else if (/^([+\\-]?\\d+)$/i.test(text)){  //integer\n        this.type = \"integer\";\n        this.value = +RegExp.$1;\n    } else if (/^([+\\-]?[\\d\\.]+)$/i.test(text)){  //number\n        this.type = \"number\";\n        this.value = +RegExp.$1;\n\n    } else if (/^#([a-f0-9]{3,6})/i.test(text)){  //hexcolor\n        this.type = \"color\";\n        temp = RegExp.$1;\n        if (temp.length == 3){\n            this.red    = parseInt(temp.charAt(0)+temp.charAt(0),16);\n            this.green  = parseInt(temp.charAt(1)+temp.charAt(1),16);\n            this.blue   = parseInt(temp.charAt(2)+temp.charAt(2),16);\n        } else {\n            this.red    = parseInt(temp.substring(0,2),16);\n            this.green  = parseInt(temp.substring(2,4),16);\n            this.blue   = parseInt(temp.substring(4,6),16);\n        }\n    } else if (/^rgb\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*\\)/i.test(text)){ //rgb() color with absolute numbers\n        this.type   = \"color\";\n        this.red    = +RegExp.$1;\n        this.green  = +RegExp.$2;\n        this.blue   = +RegExp.$3;\n    } else if (/^rgb\\(\\s*(\\d+)%\\s*,\\s*(\\d+)%\\s*,\\s*(\\d+)%\\s*\\)/i.test(text)){ //rgb() color with percentages\n        this.type   = \"color\";\n        this.red    = +RegExp.$1 * 255 / 100;\n        this.green  = +RegExp.$2 * 255 / 100;\n        this.blue   = +RegExp.$3 * 255 / 100;\n    } else if (/^rgba\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*([\\d\\.]+)\\s*\\)/i.test(text)){ //rgba() color with absolute numbers\n        this.type   = \"color\";\n        this.red    = +RegExp.$1;\n        this.green  = +RegExp.$2;\n        this.blue   = +RegExp.$3;\n        this.alpha  = +RegExp.$4;\n    } else if (/^rgba\\(\\s*(\\d+)%\\s*,\\s*(\\d+)%\\s*,\\s*(\\d+)%\\s*,\\s*([\\d\\.]+)\\s*\\)/i.test(text)){ //rgba() color with percentages\n        this.type   = \"color\";\n        this.red    = +RegExp.$1 * 255 / 100;\n        this.green  = +RegExp.$2 * 255 / 100;\n        this.blue   = +RegExp.$3 * 255 / 100;\n        this.alpha  = +RegExp.$4;\n    } else if (/^hsl\\(\\s*(\\d+)\\s*,\\s*(\\d+)%\\s*,\\s*(\\d+)%\\s*\\)/i.test(text)){ //hsl()\n        this.type   = \"color\";\n        this.hue    = +RegExp.$1;\n        this.saturation = +RegExp.$2 / 100;\n        this.lightness  = +RegExp.$3 / 100;\n    } else if (/^hsla\\(\\s*(\\d+)\\s*,\\s*(\\d+)%\\s*,\\s*(\\d+)%\\s*,\\s*([\\d\\.]+)\\s*\\)/i.test(text)){ //hsla() color with percentages\n        this.type   = \"color\";\n        this.hue    = +RegExp.$1;\n        this.saturation = +RegExp.$2 / 100;\n        this.lightness  = +RegExp.$3 / 100;\n        this.alpha  = +RegExp.$4;\n    } else if (/^url\\([\"']?([^\\)\"']+)[\"']?\\)/i.test(text)){ //URI\n        this.type   = \"uri\";\n        this.uri    = RegExp.$1;\n    } else if (/^([^\\(]+)\\(/i.test(text)){\n        this.type   = \"function\";\n        this.name   = RegExp.$1;\n        this.value  = text;\n    } else if (/^[\"'][^\"']*[\"']/.test(text)){    //string\n        this.type   = \"string\";\n        this.value  = eval(text);\n    } else if (Colors[text.toLowerCase()]){  //named color\n        this.type   = \"color\";\n        temp        = Colors[text.toLowerCase()].substring(1);\n        this.red    = parseInt(temp.substring(0,2),16);\n        this.green  = parseInt(temp.substring(2,4),16);\n        this.blue   = parseInt(temp.substring(4,6),16);\n    } else if (/^[\\,\\/]$/.test(text)){\n        this.type   = \"operator\";\n        this.value  = text;\n    } else if (/^[a-z\\-\\u0080-\\uFFFF][a-z0-9\\-\\u0080-\\uFFFF]*$/i.test(text)){\n        this.type   = \"identifier\";\n        this.value  = text;\n    }\n\n}\n\nPropertyValuePart.prototype = new SyntaxUnit();\nPropertyValuePart.prototype.constructor = PropertyValuePart;\n\n/**\n * Create a new syntax unit based solely on the given token.\n * Convenience method for creating a new syntax unit when\n * it represents a single token instead of multiple.\n * @param {Object} token The token object to represent.\n * @return {parserlib.css.PropertyValuePart} The object representing the token.\n * @static\n * @method fromToken\n */\nPropertyValuePart.fromToken = function(token){\n    return new PropertyValuePart(token.value, token.startLine, token.startCol);\n};\nvar Pseudos = {\n    \":first-letter\": 1,\n    \":first-line\":   1,\n    \":before\":       1,\n    \":after\":        1\n};\n\nPseudos.ELEMENT = 1;\nPseudos.CLASS = 2;\n\nPseudos.isElement = function(pseudo){\n    return pseudo.indexOf(\"::\") === 0 || Pseudos[pseudo.toLowerCase()] == Pseudos.ELEMENT;\n};\n/*global SyntaxUnit, Parser, Specificity*/\n/**\n * Represents an entire single selector, including all parts but not\n * including multiple selectors (those separated by commas).\n * @namespace parserlib.css\n * @class Selector\n * @extends parserlib.util.SyntaxUnit\n * @constructor\n * @param {Array} parts Array of selectors parts making up this selector.\n * @param {int} line The line of text on which the unit resides.\n * @param {int} col The column of text on which the unit resides.\n */\nfunction Selector(parts, line, col){\n\n    SyntaxUnit.call(this, parts.join(\" \"), line, col, Parser.SELECTOR_TYPE);\n\n    /**\n     * The parts that make up the selector.\n     * @type Array\n     * @property parts\n     */\n    this.parts = parts;\n\n    /**\n     * The specificity of the selector.\n     * @type parserlib.css.Specificity\n     * @property specificity\n     */\n    this.specificity = Specificity.calculate(this);\n\n}\n\nSelector.prototype = new SyntaxUnit();\nSelector.prototype.constructor = Selector;\n\n\n/*global SyntaxUnit, Parser*/\n/**\n * Represents a single part of a selector string, meaning a single set of\n * element name and modifiers. This does not include combinators such as\n * spaces, +, >, etc.\n * @namespace parserlib.css\n * @class SelectorPart\n * @extends parserlib.util.SyntaxUnit\n * @constructor\n * @param {String} elementName The element name in the selector or null\n *      if there is no element name.\n * @param {Array} modifiers Array of individual modifiers for the element.\n *      May be empty if there are none.\n * @param {String} text The text representation of the unit.\n * @param {int} line The line of text on which the unit resides.\n * @param {int} col The column of text on which the unit resides.\n */\nfunction SelectorPart(elementName, modifiers, text, line, col){\n\n    SyntaxUnit.call(this, text, line, col, Parser.SELECTOR_PART_TYPE);\n\n    /**\n     * The tag name of the element to which this part\n     * of the selector affects.\n     * @type String\n     * @property elementName\n     */\n    this.elementName = elementName;\n\n    /**\n     * The parts that come after the element name, such as class names, IDs,\n     * pseudo classes/elements, etc.\n     * @type Array\n     * @property modifiers\n     */\n    this.modifiers = modifiers;\n\n}\n\nSelectorPart.prototype = new SyntaxUnit();\nSelectorPart.prototype.constructor = SelectorPart;\n\n\n/*global SyntaxUnit, Parser*/\n/**\n * Represents a selector modifier string, meaning a class name, element name,\n * element ID, pseudo rule, etc.\n * @namespace parserlib.css\n * @class SelectorSubPart\n * @extends parserlib.util.SyntaxUnit\n * @constructor\n * @param {String} text The text representation of the unit.\n * @param {String} type The type of selector modifier.\n * @param {int} line The line of text on which the unit resides.\n * @param {int} col The column of text on which the unit resides.\n */\nfunction SelectorSubPart(text, type, line, col){\n\n    SyntaxUnit.call(this, text, line, col, Parser.SELECTOR_SUB_PART_TYPE);\n\n    /**\n     * The type of modifier.\n     * @type String\n     * @property type\n     */\n    this.type = type;\n\n    /**\n     * Some subparts have arguments, this represents them.\n     * @type Array\n     * @property args\n     */\n    this.args = [];\n\n}\n\nSelectorSubPart.prototype = new SyntaxUnit();\nSelectorSubPart.prototype.constructor = SelectorSubPart;\n\n\n/*global Pseudos, SelectorPart*/\n/**\n * Represents a selector's specificity.\n * @namespace parserlib.css\n * @class Specificity\n * @constructor\n * @param {int} a Should be 1 for inline styles, zero for stylesheet styles\n * @param {int} b Number of ID selectors\n * @param {int} c Number of classes and pseudo classes\n * @param {int} d Number of element names and pseudo elements\n */\nfunction Specificity(a, b, c, d){\n    this.a = a;\n    this.b = b;\n    this.c = c;\n    this.d = d;\n}\n\nSpecificity.prototype = {\n    constructor: Specificity,\n\n    /**\n     * Compare this specificity to another.\n     * @param {Specificity} other The other specificity to compare to.\n     * @return {int} -1 if the other specificity is larger, 1 if smaller, 0 if equal.\n     * @method compare\n     */\n    compare: function(other){\n        var comps = [\"a\", \"b\", \"c\", \"d\"],\n            i, len;\n\n        for (i=0, len=comps.length; i < len; i++){\n            if (this[comps[i]] < other[comps[i]]){\n                return -1;\n            } else if (this[comps[i]] > other[comps[i]]){\n                return 1;\n            }\n        }\n\n        return 0;\n    },\n\n    /**\n     * Creates a numeric value for the specificity.\n     * @return {int} The numeric value for the specificity.\n     * @method valueOf\n     */\n    valueOf: function(){\n        return (this.a * 1000) + (this.b * 100) + (this.c * 10) + this.d;\n    },\n\n    /**\n     * Returns a string representation for specificity.\n     * @return {String} The string representation of specificity.\n     * @method toString\n     */\n    toString: function(){\n        return this.a + \",\" + this.b + \",\" + this.c + \",\" + this.d;\n    }\n\n};\n\n/**\n * Calculates the specificity of the given selector.\n * @param {parserlib.css.Selector} The selector to calculate specificity for.\n * @return {parserlib.css.Specificity} The specificity of the selector.\n * @static\n * @method calculate\n */\nSpecificity.calculate = function(selector){\n\n    var i, len,\n        part,\n        b=0, c=0, d=0;\n\n    function updateValues(part){\n\n        var i, j, len, num,\n            elementName = part.elementName ? part.elementName.text : \"\",\n            modifier;\n\n        if (elementName && elementName.charAt(elementName.length-1) != \"*\") {\n            d++;\n        }\n\n        for (i=0, len=part.modifiers.length; i < len; i++){\n            modifier = part.modifiers[i];\n            switch(modifier.type){\n                case \"class\":\n                case \"attribute\":\n                    c++;\n                    break;\n\n                case \"id\":\n                    b++;\n                    break;\n\n                case \"pseudo\":\n                    if (Pseudos.isElement(modifier.text)){\n                        d++;\n                    } else {\n                        c++;\n                    }\n                    break;\n\n                case \"not\":\n                    for (j=0, num=modifier.args.length; j < num; j++){\n                        updateValues(modifier.args[j]);\n                    }\n            }\n         }\n    }\n\n    for (i=0, len=selector.parts.length; i < len; i++){\n        part = selector.parts[i];\n\n        if (part instanceof SelectorPart){\n            updateValues(part);\n        }\n    }\n\n    return new Specificity(0, b, c, d);\n};\n\n/*global Tokens, TokenStreamBase*/\n\nvar h = /^[0-9a-fA-F]$/,\n    nonascii = /^[\\u0080-\\uFFFF]$/,\n    nl = /\\n|\\r\\n|\\r|\\f/;\n\n//-----------------------------------------------------------------------------\n// Helper functions\n//-----------------------------------------------------------------------------\n\n\nfunction isHexDigit(c){\n    return c !== null && h.test(c);\n}\n\nfunction isDigit(c){\n    return c !== null && /\\d/.test(c);\n}\n\nfunction isWhitespace(c){\n    return c !== null && /\\s/.test(c);\n}\n\nfunction isNewLine(c){\n    return c !== null && nl.test(c);\n}\n\nfunction isNameStart(c){\n    return c !== null && (/[a-z_\\u0080-\\uFFFF\\\\]/i.test(c));\n}\n\nfunction isNameChar(c){\n    return c !== null && (isNameStart(c) || /[0-9\\-\\\\]/.test(c));\n}\n\nfunction isIdentStart(c){\n    return c !== null && (isNameStart(c) || /\\-\\\\/.test(c));\n}\n\nfunction mix(receiver, supplier){\n    for (var prop in supplier){\n        if (supplier.hasOwnProperty(prop)){\n            receiver[prop] = supplier[prop];\n        }\n    }\n    return receiver;\n}\n\n//-----------------------------------------------------------------------------\n// CSS Token Stream\n//-----------------------------------------------------------------------------\n\n\n/**\n * A token stream that produces CSS tokens.\n * @param {String|Reader} input The source of text to tokenize.\n * @constructor\n * @class TokenStream\n * @namespace parserlib.css\n */\nfunction TokenStream(input){\n    TokenStreamBase.call(this, input, Tokens);\n}\n\nTokenStream.prototype = mix(new TokenStreamBase(), {\n\n    /**\n     * Overrides the TokenStreamBase method of the same name\n     * to produce CSS tokens.\n     * @param {variant} channel The name of the channel to use\n     *      for the next token.\n     * @return {Object} A token object representing the next token.\n     * @method _getToken\n     * @private\n     */\n    _getToken: function(channel){\n\n        var c,\n            reader = this._reader,\n            token   = null,\n            startLine   = reader.getLine(),\n            startCol    = reader.getCol();\n\n        c = reader.read();\n\n\n        while(c){\n            switch(c){\n\n                /*\n                 * Potential tokens:\n                 * - COMMENT\n                 * - SLASH\n                 * - CHAR\n                 */\n                case \"/\":\n\n                    if(reader.peek() == \"*\"){\n                        token = this.commentToken(c, startLine, startCol);\n                    } else {\n                        token = this.charToken(c, startLine, startCol);\n                    }\n                    break;\n\n                /*\n                 * Potential tokens:\n                 * - DASHMATCH\n                 * - INCLUDES\n                 * - PREFIXMATCH\n                 * - SUFFIXMATCH\n                 * - SUBSTRINGMATCH\n                 * - CHAR\n                 */\n                case \"|\":\n                case \"~\":\n                case \"^\":\n                case \"$\":\n                case \"*\":\n                    if(reader.peek() == \"=\"){\n                        token = this.comparisonToken(c, startLine, startCol);\n                    } else {\n                        token = this.charToken(c, startLine, startCol);\n                    }\n                    break;\n\n                /*\n                 * Potential tokens:\n                 * - STRING\n                 * - INVALID\n                 */\n                case \"\\\"\":\n                case \"'\":\n                    token = this.stringToken(c, startLine, startCol);\n                    break;\n\n                /*\n                 * Potential tokens:\n                 * - HASH\n                 * - CHAR\n                 */\n                case \"#\":\n                    if (isNameChar(reader.peek())){\n                        token = this.hashToken(c, startLine, startCol);\n                    } else {\n                        token = this.charToken(c, startLine, startCol);\n                    }\n                    break;\n\n                /*\n                 * Potential tokens:\n                 * - DOT\n                 * - NUMBER\n                 * - DIMENSION\n                 * - PERCENTAGE\n                 */\n                case \".\":\n                    if (isDigit(reader.peek())){\n                        token = this.numberToken(c, startLine, startCol);\n                    } else {\n                        token = this.charToken(c, startLine, startCol);\n                    }\n                    break;\n\n                /*\n                 * Potential tokens:\n                 * - CDC\n                 * - MINUS\n                 * - NUMBER\n                 * - DIMENSION\n                 * - PERCENTAGE\n                 */\n                case \"-\":\n                    if (reader.peek() == \"-\"){  //could be closing HTML-style comment\n                        token = this.htmlCommentEndToken(c, startLine, startCol);\n                    } else if (isNameStart(reader.peek())){\n                        token = this.identOrFunctionToken(c, startLine, startCol);\n                    } else {\n                        token = this.charToken(c, startLine, startCol);\n                    }\n                    break;\n\n                /*\n                 * Potential tokens:\n                 * - IMPORTANT_SYM\n                 * - CHAR\n                 */\n                case \"!\":\n                    token = this.importantToken(c, startLine, startCol);\n                    break;\n\n                /*\n                 * Any at-keyword or CHAR\n                 */\n                case \"@\":\n                    token = this.atRuleToken(c, startLine, startCol);\n                    break;\n\n                /*\n                 * Potential tokens:\n                 * - NOT\n                 * - CHAR\n                 */\n                case \":\":\n                    token = this.notToken(c, startLine, startCol);\n                    break;\n\n                /*\n                 * Potential tokens:\n                 * - CDO\n                 * - CHAR\n                 */\n                case \"<\":\n                    token = this.htmlCommentStartToken(c, startLine, startCol);\n                    break;\n\n                /*\n                 * Potential tokens:\n                 * - UNICODE_RANGE\n                 * - URL\n                 * - CHAR\n                 */\n                case \"U\":\n                case \"u\":\n                    if (reader.peek() == \"+\"){\n                        token = this.unicodeRangeToken(c, startLine, startCol);\n                        break;\n                    }\n                    /* falls through */\n                default:\n\n                    /*\n                     * Potential tokens:\n                     * - NUMBER\n                     * - DIMENSION\n                     * - LENGTH\n                     * - FREQ\n                     * - TIME\n                     * - EMS\n                     * - EXS\n                     * - ANGLE\n                     */\n                    if (isDigit(c)){\n                        token = this.numberToken(c, startLine, startCol);\n                    } else\n\n                    /*\n                     * Potential tokens:\n                     * - S\n                     */\n                    if (isWhitespace(c)){\n                        token = this.whitespaceToken(c, startLine, startCol);\n                    } else\n\n                    /*\n                     * Potential tokens:\n                     * - IDENT\n                     */\n                    if (isIdentStart(c)){\n                        token = this.identOrFunctionToken(c, startLine, startCol);\n                    } else\n\n                    /*\n                     * Potential tokens:\n                     * - CHAR\n                     * - PLUS\n                     */\n                    {\n                        token = this.charToken(c, startLine, startCol);\n                    }\n\n\n\n\n\n\n            }\n\n            //make sure this token is wanted\n            //TODO: check channel\n            break;\n        }\n\n        if (!token && c === null){\n            token = this.createToken(Tokens.EOF,null,startLine,startCol);\n        }\n\n        return token;\n    },\n\n    //-------------------------------------------------------------------------\n    // Methods to create tokens\n    //-------------------------------------------------------------------------\n\n    /**\n     * Produces a token based on available data and the current\n     * reader position information. This method is called by other\n     * private methods to create tokens and is never called directly.\n     * @param {int} tt The token type.\n     * @param {String} value The text value of the token.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @param {Object} options (Optional) Specifies a channel property\n     *      to indicate that a different channel should be scanned\n     *      and/or a hide property indicating that the token should\n     *      be hidden.\n     * @return {Object} A token object.\n     * @method createToken\n     */\n    createToken: function(tt, value, startLine, startCol, options){\n        var reader = this._reader;\n        options = options || {};\n\n        return {\n            value:      value,\n            type:       tt,\n            channel:    options.channel,\n            hide:       options.hide || false,\n            startLine:  startLine,\n            startCol:   startCol,\n            endLine:    reader.getLine(),\n            endCol:     reader.getCol()\n        };\n    },\n\n    //-------------------------------------------------------------------------\n    // Methods to create specific tokens\n    //-------------------------------------------------------------------------\n\n    /**\n     * Produces a token for any at-rule. If the at-rule is unknown, then\n     * the token is for a single \"@\" character.\n     * @param {String} first The first character for the token.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method atRuleToken\n     */\n    atRuleToken: function(first, startLine, startCol){\n        var rule    = first,\n            reader  = this._reader,\n            tt      = Tokens.CHAR,\n            valid   = false,\n            ident,\n            c;\n\n        /*\n         * First, mark where we are. There are only four @ rules,\n         * so anything else is really just an invalid token.\n         * Basically, if this doesn't match one of the known @\n         * rules, just return '@' as an unknown token and allow\n         * parsing to continue after that point.\n         */\n        reader.mark();\n\n        //try to find the at-keyword\n        ident = this.readName();\n        rule = first + ident;\n        tt = Tokens.type(rule.toLowerCase());\n\n        //if it's not valid, use the first character only and reset the reader\n        if (tt == Tokens.CHAR || tt == Tokens.UNKNOWN){\n            if (rule.length > 1){\n                tt = Tokens.UNKNOWN_SYM;\n            } else {\n                tt = Tokens.CHAR;\n                rule = first;\n                reader.reset();\n            }\n        }\n\n        return this.createToken(tt, rule, startLine, startCol);\n    },\n\n    /**\n     * Produces a character token based on the given character\n     * and location in the stream. If there's a special (non-standard)\n     * token name, this is used; otherwise CHAR is used.\n     * @param {String} c The character for the token.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method charToken\n     */\n    charToken: function(c, startLine, startCol){\n        var tt = Tokens.type(c);\n\n        if (tt == -1){\n            tt = Tokens.CHAR;\n        }\n\n        return this.createToken(tt, c, startLine, startCol);\n    },\n\n    /**\n     * Produces a character token based on the given character\n     * and location in the stream. If there's a special (non-standard)\n     * token name, this is used; otherwise CHAR is used.\n     * @param {String} first The first character for the token.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method commentToken\n     */\n    commentToken: function(first, startLine, startCol){\n        var reader  = this._reader,\n            comment = this.readComment(first);\n\n        return this.createToken(Tokens.COMMENT, comment, startLine, startCol);\n    },\n\n    /**\n     * Produces a comparison token based on the given character\n     * and location in the stream. The next character must be\n     * read and is already known to be an equals sign.\n     * @param {String} c The character for the token.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method comparisonToken\n     */\n    comparisonToken: function(c, startLine, startCol){\n        var reader  = this._reader,\n            comparison  = c + reader.read(),\n            tt      = Tokens.type(comparison) || Tokens.CHAR;\n\n        return this.createToken(tt, comparison, startLine, startCol);\n    },\n\n    /**\n     * Produces a hash token based on the specified information. The\n     * first character provided is the pound sign (#) and then this\n     * method reads a name afterward.\n     * @param {String} first The first character (#) in the hash name.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method hashToken\n     */\n    hashToken: function(first, startLine, startCol){\n        var reader  = this._reader,\n            name    = this.readName(first);\n\n        return this.createToken(Tokens.HASH, name, startLine, startCol);\n    },\n\n    /**\n     * Produces a CDO or CHAR token based on the specified information. The\n     * first character is provided and the rest is read by the function to determine\n     * the correct token to create.\n     * @param {String} first The first character in the token.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method htmlCommentStartToken\n     */\n    htmlCommentStartToken: function(first, startLine, startCol){\n        var reader      = this._reader,\n            text        = first;\n\n        reader.mark();\n        text += reader.readCount(3);\n\n        if (text == \"<!--\"){\n            return this.createToken(Tokens.CDO, text, startLine, startCol);\n        } else {\n            reader.reset();\n            return this.charToken(first, startLine, startCol);\n        }\n    },\n\n    /**\n     * Produces a CDC or CHAR token based on the specified information. The\n     * first character is provided and the rest is read by the function to determine\n     * the correct token to create.\n     * @param {String} first The first character in the token.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method htmlCommentEndToken\n     */\n    htmlCommentEndToken: function(first, startLine, startCol){\n        var reader      = this._reader,\n            text        = first;\n\n        reader.mark();\n        text += reader.readCount(2);\n\n        if (text == \"-->\"){\n            return this.createToken(Tokens.CDC, text, startLine, startCol);\n        } else {\n            reader.reset();\n            return this.charToken(first, startLine, startCol);\n        }\n    },\n\n    /**\n     * Produces an IDENT or FUNCTION token based on the specified information. The\n     * first character is provided and the rest is read by the function to determine\n     * the correct token to create.\n     * @param {String} first The first character in the identifier.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method identOrFunctionToken\n     */\n    identOrFunctionToken: function(first, startLine, startCol){\n        var reader  = this._reader,\n            ident   = this.readName(first),\n            tt      = Tokens.IDENT;\n\n        //if there's a left paren immediately after, it's a URI or function\n        if (reader.peek() == \"(\"){\n            ident += reader.read();\n            if (ident.toLowerCase() == \"url(\"){\n                tt = Tokens.URI;\n                ident = this.readURI(ident);\n\n                //didn't find a valid URL or there's no closing paren\n                if (ident.toLowerCase() == \"url(\"){\n                    tt = Tokens.FUNCTION;\n                }\n            } else {\n                tt = Tokens.FUNCTION;\n            }\n        } else if (reader.peek() == \":\"){  //might be an IE function\n\n            //IE-specific functions always being with progid:\n            if (ident.toLowerCase() == \"progid\"){\n                ident += reader.readTo(\"(\");\n                tt = Tokens.IE_FUNCTION;\n            }\n        }\n\n        return this.createToken(tt, ident, startLine, startCol);\n    },\n\n    /**\n     * Produces an IMPORTANT_SYM or CHAR token based on the specified information. The\n     * first character is provided and the rest is read by the function to determine\n     * the correct token to create.\n     * @param {String} first The first character in the token.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method importantToken\n     */\n    importantToken: function(first, startLine, startCol){\n        var reader      = this._reader,\n            important   = first,\n            tt          = Tokens.CHAR,\n            temp,\n            c;\n\n        reader.mark();\n        c = reader.read();\n\n        while(c){\n\n            //there can be a comment in here\n            if (c == \"/\"){\n\n                //if the next character isn't a star, then this isn't a valid !important token\n                if (reader.peek() != \"*\"){\n                    break;\n                } else {\n                    temp = this.readComment(c);\n                    if (temp === \"\"){    //broken!\n                        break;\n                    }\n                }\n            } else if (isWhitespace(c)){\n                important += c + this.readWhitespace();\n            } else if (/i/i.test(c)){\n                temp = reader.readCount(8);\n                if (/mportant/i.test(temp)){\n                    important += c + temp;\n                    tt = Tokens.IMPORTANT_SYM;\n\n                }\n                break;  //we're done\n            } else {\n                break;\n            }\n\n            c = reader.read();\n        }\n\n        if (tt == Tokens.CHAR){\n            reader.reset();\n            return this.charToken(first, startLine, startCol);\n        } else {\n            return this.createToken(tt, important, startLine, startCol);\n        }\n\n\n    },\n\n    /**\n     * Produces a NOT or CHAR token based on the specified information. The\n     * first character is provided and the rest is read by the function to determine\n     * the correct token to create.\n     * @param {String} first The first character in the token.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method notToken\n     */\n    notToken: function(first, startLine, startCol){\n        var reader      = this._reader,\n            text        = first;\n\n        reader.mark();\n        text += reader.readCount(4);\n\n        if (text.toLowerCase() == \":not(\"){\n            return this.createToken(Tokens.NOT, text, startLine, startCol);\n        } else {\n            reader.reset();\n            return this.charToken(first, startLine, startCol);\n        }\n    },\n\n    /**\n     * Produces a number token based on the given character\n     * and location in the stream. This may return a token of\n     * NUMBER, EMS, EXS, LENGTH, ANGLE, TIME, FREQ, DIMENSION,\n     * or PERCENTAGE.\n     * @param {String} first The first character for the token.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method numberToken\n     */\n    numberToken: function(first, startLine, startCol){\n        var reader  = this._reader,\n            value   = this.readNumber(first),\n            ident,\n            tt      = Tokens.NUMBER,\n            c       = reader.peek();\n\n        if (isIdentStart(c)){\n            ident = this.readName(reader.read());\n            value += ident;\n\n            if (/^em$|^ex$|^px$|^gd$|^rem$|^vw$|^vh$|^vm$|^ch$|^cm$|^mm$|^in$|^pt$|^pc$/i.test(ident)){\n                tt = Tokens.LENGTH;\n            } else if (/^deg|^rad$|^grad$/i.test(ident)){\n                tt = Tokens.ANGLE;\n            } else if (/^ms$|^s$/i.test(ident)){\n                tt = Tokens.TIME;\n            } else if (/^hz$|^khz$/i.test(ident)){\n                tt = Tokens.FREQ;\n            } else if (/^dpi$|^dpcm$/i.test(ident)){\n                tt = Tokens.RESOLUTION;\n            } else {\n                tt = Tokens.DIMENSION;\n            }\n\n        } else if (c == \"%\"){\n            value += reader.read();\n            tt = Tokens.PERCENTAGE;\n        }\n\n        return this.createToken(tt, value, startLine, startCol);\n    },\n\n    /**\n     * Produces a string token based on the given character\n     * and location in the stream. Since strings may be indicated\n     * by single or double quotes, a failure to match starting\n     * and ending quotes results in an INVALID token being generated.\n     * The first character in the string is passed in and then\n     * the rest are read up to and including the final quotation mark.\n     * @param {String} first The first character in the string.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method stringToken\n     */\n    stringToken: function(first, startLine, startCol){\n        var delim   = first,\n            string  = first,\n            reader  = this._reader,\n            prev    = first,\n            tt      = Tokens.STRING,\n            c       = reader.read();\n\n        while(c){\n            string += c;\n\n            //if the delimiter is found with an escapement, we're done.\n            if (c == delim && prev != \"\\\\\"){\n                break;\n            }\n\n            //if there's a newline without an escapement, it's an invalid string\n            if (isNewLine(reader.peek()) && c != \"\\\\\"){\n                tt = Tokens.INVALID;\n                break;\n            }\n\n            //save previous and get next\n            prev = c;\n            c = reader.read();\n        }\n\n        //if c is null, that means we're out of input and the string was never closed\n        if (c === null){\n            tt = Tokens.INVALID;\n        }\n\n        return this.createToken(tt, string, startLine, startCol);\n    },\n\n    unicodeRangeToken: function(first, startLine, startCol){\n        var reader  = this._reader,\n            value   = first,\n            temp,\n            tt      = Tokens.CHAR;\n\n        //then it should be a unicode range\n        if (reader.peek() == \"+\"){\n            reader.mark();\n            value += reader.read();\n            value += this.readUnicodeRangePart(true);\n\n            //ensure there's an actual unicode range here\n            if (value.length == 2){\n                reader.reset();\n            } else {\n\n                tt = Tokens.UNICODE_RANGE;\n\n                //if there's a ? in the first part, there can't be a second part\n                if (value.indexOf(\"?\") == -1){\n\n                    if (reader.peek() == \"-\"){\n                        reader.mark();\n                        temp = reader.read();\n                        temp += this.readUnicodeRangePart(false);\n\n                        //if there's not another value, back up and just take the first\n                        if (temp.length == 1){\n                            reader.reset();\n                        } else {\n                            value += temp;\n                        }\n                    }\n\n                }\n            }\n        }\n\n        return this.createToken(tt, value, startLine, startCol);\n    },\n\n    /**\n     * Produces a S token based on the specified information. Since whitespace\n     * may have multiple characters, this consumes all whitespace characters\n     * into a single token.\n     * @param {String} first The first character in the token.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method whitespaceToken\n     */\n    whitespaceToken: function(first, startLine, startCol){\n        var reader  = this._reader,\n            value   = first + this.readWhitespace();\n        return this.createToken(Tokens.S, value, startLine, startCol);\n    },\n\n\n\n\n    //-------------------------------------------------------------------------\n    // Methods to read values from the string stream\n    //-------------------------------------------------------------------------\n\n    readUnicodeRangePart: function(allowQuestionMark){\n        var reader  = this._reader,\n            part = \"\",\n            c       = reader.peek();\n\n        //first read hex digits\n        while(isHexDigit(c) && part.length < 6){\n            reader.read();\n            part += c;\n            c = reader.peek();\n        }\n\n        //then read question marks if allowed\n        if (allowQuestionMark){\n            while(c == \"?\" && part.length < 6){\n                reader.read();\n                part += c;\n                c = reader.peek();\n            }\n        }\n\n        //there can't be any other characters after this point\n\n        return part;\n    },\n\n    readWhitespace: function(){\n        var reader  = this._reader,\n            whitespace = \"\",\n            c       = reader.peek();\n\n        while(isWhitespace(c)){\n            reader.read();\n            whitespace += c;\n            c = reader.peek();\n        }\n\n        return whitespace;\n    },\n    readNumber: function(first){\n        var reader  = this._reader,\n            number  = first,\n            hasDot  = (first == \".\"),\n            c       = reader.peek();\n\n\n        while(c){\n            if (isDigit(c)){\n                number += reader.read();\n            } else if (c == \".\"){\n                if (hasDot){\n                    break;\n                } else {\n                    hasDot = true;\n                    number += reader.read();\n                }\n            } else {\n                break;\n            }\n\n            c = reader.peek();\n        }\n\n        return number;\n    },\n    readString: function(){\n        var reader  = this._reader,\n            delim   = reader.read(),\n            string  = delim,\n            prev    = delim,\n            c       = reader.peek();\n\n        while(c){\n            c = reader.read();\n            string += c;\n\n            //if the delimiter is found with an escapement, we're done.\n            if (c == delim && prev != \"\\\\\"){\n                break;\n            }\n\n            //if there's a newline without an escapement, it's an invalid string\n            if (isNewLine(reader.peek()) && c != \"\\\\\"){\n                string = \"\";\n                break;\n            }\n\n            //save previous and get next\n            prev = c;\n            c = reader.peek();\n        }\n\n        //if c is null, that means we're out of input and the string was never closed\n        if (c === null){\n            string = \"\";\n        }\n\n        return string;\n    },\n    readURI: function(first){\n        var reader  = this._reader,\n            uri     = first,\n            inner   = \"\",\n            c       = reader.peek();\n\n        reader.mark();\n\n        //skip whitespace before\n        while(c && isWhitespace(c)){\n            reader.read();\n            c = reader.peek();\n        }\n\n        //it's a string\n        if (c == \"'\" || c == \"\\\"\"){\n            inner = this.readString();\n        } else {\n            inner = this.readURL();\n        }\n\n        c = reader.peek();\n\n        //skip whitespace after\n        while(c && isWhitespace(c)){\n            reader.read();\n            c = reader.peek();\n        }\n\n        //if there was no inner value or the next character isn't closing paren, it's not a URI\n        if (inner === \"\" || c != \")\"){\n            uri = first;\n            reader.reset();\n        } else {\n            uri += inner + reader.read();\n        }\n\n        return uri;\n    },\n    readURL: function(){\n        var reader  = this._reader,\n            url     = \"\",\n            c       = reader.peek();\n\n        //TODO: Check for escape and nonascii\n        while (/^[!#$%&\\\\*-~]$/.test(c)){\n            url += reader.read();\n            c = reader.peek();\n        }\n\n        return url;\n\n    },\n    readName: function(first){\n        var reader  = this._reader,\n            ident   = first || \"\",\n            c       = reader.peek();\n\n        while(true){\n            if (c == \"\\\\\"){\n                ident += this.readEscape(reader.read());\n                c = reader.peek();\n            } else if(c && isNameChar(c)){\n                ident += reader.read();\n                c = reader.peek();\n            } else {\n                break;\n            }\n        }\n\n        return ident;\n    },\n\n    readEscape: function(first){\n        var reader  = this._reader,\n            cssEscape = first || \"\",\n            i       = 0,\n            c       = reader.peek();\n\n        if (isHexDigit(c)){\n            do {\n                cssEscape += reader.read();\n                c = reader.peek();\n            } while(c && isHexDigit(c) && ++i < 6);\n        }\n\n        if (cssEscape.length == 3 && /\\s/.test(c) ||\n            cssEscape.length == 7 || cssEscape.length == 1){\n                reader.read();\n        } else {\n            c = \"\";\n        }\n\n        return cssEscape + c;\n    },\n\n    readComment: function(first){\n        var reader  = this._reader,\n            comment = first || \"\",\n            c       = reader.read();\n\n        if (c == \"*\"){\n            while(c){\n                comment += c;\n\n                //look for end of comment\n                if (comment.length > 2 && c == \"*\" && reader.peek() == \"/\"){\n                    comment += reader.read();\n                    break;\n                }\n\n                c = reader.read();\n            }\n\n            return comment;\n        } else {\n            return \"\";\n        }\n\n    }\n});\n\n\nvar Tokens  = [\n\n    /*\n     * The following token names are defined in CSS3 Grammar: http://www.w3.org/TR/css3-syntax/#lexical\n     */\n\n    //HTML-style comments\n    { name: \"CDO\"},\n    { name: \"CDC\"},\n\n    //ignorables\n    { name: \"S\", whitespace: true/*, channel: \"ws\"*/},\n    { name: \"COMMENT\", comment: true, hide: true, channel: \"comment\" },\n\n    //attribute equality\n    { name: \"INCLUDES\", text: \"~=\"},\n    { name: \"DASHMATCH\", text: \"|=\"},\n    { name: \"PREFIXMATCH\", text: \"^=\"},\n    { name: \"SUFFIXMATCH\", text: \"$=\"},\n    { name: \"SUBSTRINGMATCH\", text: \"*=\"},\n\n    //identifier types\n    { name: \"STRING\"},\n    { name: \"IDENT\"},\n    { name: \"HASH\"},\n\n    //at-keywords\n    { name: \"IMPORT_SYM\", text: \"@import\"},\n    { name: \"PAGE_SYM\", text: \"@page\"},\n    { name: \"MEDIA_SYM\", text: \"@media\"},\n    { name: \"FONT_FACE_SYM\", text: \"@font-face\"},\n    { name: \"CHARSET_SYM\", text: \"@charset\"},\n    { name: \"NAMESPACE_SYM\", text: \"@namespace\"},\n    { name: \"UNKNOWN_SYM\" },\n    //{ name: \"ATKEYWORD\"},\n\n    //CSS3 animations\n    { name: \"KEYFRAMES_SYM\", text: [ \"@keyframes\", \"@-webkit-keyframes\", \"@-moz-keyframes\", \"@-o-keyframes\" ] },\n\n    //important symbol\n    { name: \"IMPORTANT_SYM\"},\n\n    //measurements\n    { name: \"LENGTH\"},\n    { name: \"ANGLE\"},\n    { name: \"TIME\"},\n    { name: \"FREQ\"},\n    { name: \"DIMENSION\"},\n    { name: \"PERCENTAGE\"},\n    { name: \"NUMBER\"},\n\n    //functions\n    { name: \"URI\"},\n    { name: \"FUNCTION\"},\n\n    //Unicode ranges\n    { name: \"UNICODE_RANGE\"},\n\n    /*\n     * The following token names are defined in CSS3 Selectors: http://www.w3.org/TR/css3-selectors/#selector-syntax\n     */\n\n    //invalid string\n    { name: \"INVALID\"},\n\n    //combinators\n    { name: \"PLUS\", text: \"+\" },\n    { name: \"GREATER\", text: \">\"},\n    { name: \"COMMA\", text: \",\"},\n    { name: \"TILDE\", text: \"~\"},\n\n    //modifier\n    { name: \"NOT\"},\n\n    /*\n     * Defined in CSS3 Paged Media\n     */\n    { name: \"TOPLEFTCORNER_SYM\", text: \"@top-left-corner\"},\n    { name: \"TOPLEFT_SYM\", text: \"@top-left\"},\n    { name: \"TOPCENTER_SYM\", text: \"@top-center\"},\n    { name: \"TOPRIGHT_SYM\", text: \"@top-right\"},\n    { name: \"TOPRIGHTCORNER_SYM\", text: \"@top-right-corner\"},\n    { name: \"BOTTOMLEFTCORNER_SYM\", text: \"@bottom-left-corner\"},\n    { name: \"BOTTOMLEFT_SYM\", text: \"@bottom-left\"},\n    { name: \"BOTTOMCENTER_SYM\", text: \"@bottom-center\"},\n    { name: \"BOTTOMRIGHT_SYM\", text: \"@bottom-right\"},\n    { name: \"BOTTOMRIGHTCORNER_SYM\", text: \"@bottom-right-corner\"},\n    { name: \"LEFTTOP_SYM\", text: \"@left-top\"},\n    { name: \"LEFTMIDDLE_SYM\", text: \"@left-middle\"},\n    { name: \"LEFTBOTTOM_SYM\", text: \"@left-bottom\"},\n    { name: \"RIGHTTOP_SYM\", text: \"@right-top\"},\n    { name: \"RIGHTMIDDLE_SYM\", text: \"@right-middle\"},\n    { name: \"RIGHTBOTTOM_SYM\", text: \"@right-bottom\"},\n\n    /*\n     * The following token names are defined in CSS3 Media Queries: http://www.w3.org/TR/css3-mediaqueries/#syntax\n     */\n    /*{ name: \"MEDIA_ONLY\", state: \"media\"},\n    { name: \"MEDIA_NOT\", state: \"media\"},\n    { name: \"MEDIA_AND\", state: \"media\"},*/\n    { name: \"RESOLUTION\", state: \"media\"},\n\n    /*\n     * The following token names are not defined in any CSS specification but are used by the lexer.\n     */\n\n    //not a real token, but useful for stupid IE filters\n    { name: \"IE_FUNCTION\" },\n\n    //part of CSS3 grammar but not the Flex code\n    { name: \"CHAR\" },\n\n    //TODO: Needed?\n    //Not defined as tokens, but might as well be\n    {\n        name: \"PIPE\",\n        text: \"|\"\n    },\n    {\n        name: \"SLASH\",\n        text: \"/\"\n    },\n    {\n        name: \"MINUS\",\n        text: \"-\"\n    },\n    {\n        name: \"STAR\",\n        text: \"*\"\n    },\n\n    {\n        name: \"LBRACE\",\n        text: \"{\"\n    },\n    {\n        name: \"RBRACE\",\n        text: \"}\"\n    },\n    {\n        name: \"LBRACKET\",\n        text: \"[\"\n    },\n    {\n        name: \"RBRACKET\",\n        text: \"]\"\n    },\n    {\n        name: \"EQUALS\",\n        text: \"=\"\n    },\n    {\n        name: \"COLON\",\n        text: \":\"\n    },\n    {\n        name: \"SEMICOLON\",\n        text: \";\"\n    },\n\n    {\n        name: \"LPAREN\",\n        text: \"(\"\n    },\n    {\n        name: \"RPAREN\",\n        text: \")\"\n    },\n    {\n        name: \"DOT\",\n        text: \".\"\n    }\n];\n\n(function(){\n\n    var nameMap = [],\n        typeMap = {};\n\n    Tokens.UNKNOWN = -1;\n    Tokens.unshift({name:\"EOF\"});\n    for (var i=0, len = Tokens.length; i < len; i++){\n        nameMap.push(Tokens[i].name);\n        Tokens[Tokens[i].name] = i;\n        if (Tokens[i].text){\n            if (Tokens[i].text instanceof Array){\n                for (var j=0; j < Tokens[i].text.length; j++){\n                    typeMap[Tokens[i].text[j]] = i;\n                }\n            } else {\n                typeMap[Tokens[i].text] = i;\n            }\n        }\n    }\n\n    Tokens.name = function(tt){\n        return nameMap[tt];\n    };\n\n    Tokens.type = function(c){\n        return typeMap[c] || -1;\n    };\n\n})();\n\n\n\n\n//This file will likely change a lot! Very experimental!\n/*global Properties, ValidationTypes, ValidationError, PropertyValueIterator */\nvar Validation = {\n\n    validate: function(property, value){\n\n        //normalize name\n        var name        = property.toString().toLowerCase(),\n            parts       = value.parts,\n            expression  = new PropertyValueIterator(value),\n            spec        = Properties[name],\n            part,\n            valid,\n            j, count,\n            msg,\n            types,\n            last,\n            literals,\n            max, multi, group;\n\n        if (!spec) {\n            if (name.indexOf(\"-\") !== 0){    //vendor prefixed are ok\n                throw new ValidationError(\"Unknown property '\" + property + \"'.\", property.line, property.col);\n            }\n        } else if (typeof spec != \"number\"){\n\n            //initialization\n            if (typeof spec == \"string\"){\n                if (spec.indexOf(\"||\") > -1) {\n                    this.groupProperty(spec, expression);\n                } else {\n                    this.singleProperty(spec, expression, 1);\n                }\n\n            } else if (spec.multi) {\n                this.multiProperty(spec.multi, expression, spec.comma, spec.max || Infinity);\n            } else if (typeof spec == \"function\") {\n                spec(expression);\n            }\n\n        }\n\n    },\n\n    singleProperty: function(types, expression, max, partial) {\n\n        var result      = false,\n            value       = expression.value,\n            count       = 0,\n            part;\n\n        while (expression.hasNext() && count < max) {\n            result = ValidationTypes.isAny(expression, types);\n            if (!result) {\n                break;\n            }\n            count++;\n        }\n\n        if (!result) {\n            if (expression.hasNext() && !expression.isFirst()) {\n                part = expression.peek();\n                throw new ValidationError(\"Expected end of value but found '\" + part + \"'.\", part.line, part.col);\n            } else {\n                 throw new ValidationError(\"Expected (\" + types + \") but found '\" + value + \"'.\", value.line, value.col);\n            }\n        } else if (expression.hasNext()) {\n            part = expression.next();\n            throw new ValidationError(\"Expected end of value but found '\" + part + \"'.\", part.line, part.col);\n        }\n\n    },\n\n    multiProperty: function (types, expression, comma, max) {\n\n        var result      = false,\n            value       = expression.value,\n            count       = 0,\n            sep         = false,\n            part;\n\n        while(expression.hasNext() && !result && count < max) {\n            if (ValidationTypes.isAny(expression, types)) {\n                count++;\n                if (!expression.hasNext()) {\n                    result = true;\n\n                } else if (comma) {\n                    if (expression.peek() == \",\") {\n                        part = expression.next();\n                    } else {\n                        break;\n                    }\n                }\n            } else {\n                break;\n\n            }\n        }\n\n        if (!result) {\n            if (expression.hasNext() && !expression.isFirst()) {\n                part = expression.peek();\n                throw new ValidationError(\"Expected end of value but found '\" + part + \"'.\", part.line, part.col);\n            } else {\n                part = expression.previous();\n                if (comma && part == \",\") {\n                    throw new ValidationError(\"Expected end of value but found '\" + part + \"'.\", part.line, part.col);\n                } else {\n                    throw new ValidationError(\"Expected (\" + types + \") but found '\" + value + \"'.\", value.line, value.col);\n                }\n            }\n\n        } else if (expression.hasNext()) {\n            part = expression.next();\n            throw new ValidationError(\"Expected end of value but found '\" + part + \"'.\", part.line, part.col);\n        }\n\n    },\n\n    groupProperty: function (types, expression, comma) {\n\n        var result      = false,\n            value       = expression.value,\n            typeCount   = types.split(\"||\").length,\n            groups      = { count: 0 },\n            partial     = false,\n            name,\n            part;\n\n        while(expression.hasNext() && !result) {\n            name = ValidationTypes.isAnyOfGroup(expression, types);\n            if (name) {\n\n                //no dupes\n                if (groups[name]) {\n                    break;\n                } else {\n                    groups[name] = 1;\n                    groups.count++;\n                    partial = true;\n\n                    if (groups.count == typeCount || !expression.hasNext()) {\n                        result = true;\n                    }\n                }\n            } else {\n                break;\n            }\n        }\n\n        if (!result) {\n            if (partial && expression.hasNext()) {\n                    part = expression.peek();\n                    throw new ValidationError(\"Expected end of value but found '\" + part + \"'.\", part.line, part.col);\n            } else {\n                throw new ValidationError(\"Expected (\" + types + \") but found '\" + value + \"'.\", value.line, value.col);\n            }\n        } else if (expression.hasNext()) {\n            part = expression.next();\n            throw new ValidationError(\"Expected end of value but found '\" + part + \"'.\", part.line, part.col);\n        }\n    }\n\n\n\n};\n/**\n * Type to use when a validation error occurs.\n * @class ValidationError\n * @namespace parserlib.util\n * @constructor\n * @param {String} message The error message.\n * @param {int} line The line at which the error occurred.\n * @param {int} col The column at which the error occurred.\n */\nfunction ValidationError(message, line, col){\n\n    /**\n     * The column at which the error occurred.\n     * @type int\n     * @property col\n     */\n    this.col = col;\n\n    /**\n     * The line at which the error occurred.\n     * @type int\n     * @property line\n     */\n    this.line = line;\n\n    /**\n     * The text representation of the unit.\n     * @type String\n     * @property text\n     */\n    this.message = message;\n\n}\n\n//inherit from Error\nValidationError.prototype = new Error();\n//This file will likely change a lot! Very experimental!\n/*global Properties, Validation, ValidationError, PropertyValueIterator, console*/\nvar ValidationTypes = {\n\n    isLiteral: function (part, literals) {\n        var text = part.text.toString().toLowerCase(),\n            args = literals.split(\" | \"),\n            i, len, found = false;\n\n        for (i=0,len=args.length; i < len && !found; i++){\n            if (text == args[i].toLowerCase()){\n                found = true;\n            }\n        }\n\n        return found;\n    },\n\n    isSimple: function(type) {\n        return !!this.simple[type];\n    },\n\n    isComplex: function(type) {\n        return !!this.complex[type];\n    },\n\n    /**\n     * Determines if the next part(s) of the given expression\n     * are any of the given types.\n     */\n    isAny: function (expression, types) {\n        var args = types.split(\" | \"),\n            i, len, found = false;\n\n        for (i=0,len=args.length; i < len && !found && expression.hasNext(); i++){\n            found = this.isType(expression, args[i]);\n        }\n\n        return found;\n    },\n\n    /**\n     * Determines if the next part(s) of the given expression\n     * are one of a group.\n     */\n    isAnyOfGroup: function(expression, types) {\n        var args = types.split(\" || \"),\n            i, len, found = false;\n\n        for (i=0,len=args.length; i < len && !found; i++){\n            found = this.isType(expression, args[i]);\n        }\n\n        return found ? args[i-1] : false;\n    },\n\n    /**\n     * Determines if the next part(s) of the given expression\n     * are of a given type.\n     */\n    isType: function (expression, type) {\n        var part = expression.peek(),\n            result = false;\n\n        if (type.charAt(0) != \"<\") {\n            result = this.isLiteral(part, type);\n            if (result) {\n                expression.next();\n            }\n        } else if (this.simple[type]) {\n            result = this.simple[type](part);\n            if (result) {\n                expression.next();\n            }\n        } else {\n            result = this.complex[type](expression);\n        }\n\n        return result;\n    },\n\n\n\n    simple: {\n\n        \"<absolute-size>\": function(part){\n            return ValidationTypes.isLiteral(part, \"xx-small | x-small | small | medium | large | x-large | xx-large\");\n        },\n\n        \"<attachment>\": function(part){\n            return ValidationTypes.isLiteral(part, \"scroll | fixed | local\");\n        },\n\n        \"<attr>\": function(part){\n            return part.type == \"function\" && part.name == \"attr\";\n        },\n\n        \"<bg-image>\": function(part){\n            return this[\"<image>\"](part) || this[\"<gradient>\"](part) ||  part == \"none\";\n        },\n\n        \"<gradient>\": function(part) {\n            return part.type == \"function\" && /^(?:\\-(?:ms|moz|o|webkit)\\-)?(?:repeating\\-)?(?:radial\\-|linear\\-)?gradient/i.test(part);\n        },\n\n        \"<box>\": function(part){\n            return ValidationTypes.isLiteral(part, \"padding-box | border-box | content-box\");\n        },\n\n        \"<content>\": function(part){\n            return part.type == \"function\" && part.name == \"content\";\n        },\n\n        \"<relative-size>\": function(part){\n            return ValidationTypes.isLiteral(part, \"smaller | larger\");\n        },\n\n        //any identifier\n        \"<ident>\": function(part){\n            return part.type == \"identifier\";\n        },\n\n        \"<length>\": function(part){\n            if (part.type == \"function\" && /^(?:\\-(?:ms|moz|o|webkit)\\-)?calc/i.test(part)){\n                return true;\n            }else{\n                return part.type == \"length\" || part.type == \"number\" || part.type == \"integer\" || part == \"0\";\n            }\n        },\n\n        \"<color>\": function(part){\n            return part.type == \"color\" || part == \"transparent\";\n        },\n\n        \"<number>\": function(part){\n            return part.type == \"number\" || this[\"<integer>\"](part);\n        },\n\n        \"<integer>\": function(part){\n            return part.type == \"integer\";\n        },\n\n        \"<line>\": function(part){\n            return part.type == \"integer\";\n        },\n\n        \"<angle>\": function(part){\n            return part.type == \"angle\";\n        },\n\n        \"<uri>\": function(part){\n            return part.type == \"uri\";\n        },\n\n        \"<image>\": function(part){\n            return this[\"<uri>\"](part);\n        },\n\n        \"<percentage>\": function(part){\n            return part.type == \"percentage\" || part == \"0\";\n        },\n\n        \"<border-width>\": function(part){\n            return this[\"<length>\"](part) || ValidationTypes.isLiteral(part, \"thin | medium | thick\");\n        },\n\n        \"<border-style>\": function(part){\n            return ValidationTypes.isLiteral(part, \"none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset\");\n        },\n\n        \"<margin-width>\": function(part){\n            return this[\"<length>\"](part) || this[\"<percentage>\"](part) || ValidationTypes.isLiteral(part, \"auto\");\n        },\n\n        \"<padding-width>\": function(part){\n            return this[\"<length>\"](part) || this[\"<percentage>\"](part);\n        },\n\n        \"<shape>\": function(part){\n            return part.type == \"function\" && (part.name == \"rect\" || part.name == \"inset-rect\");\n        },\n\n        \"<time>\": function(part) {\n            return part.type == \"time\";\n        }\n    },\n\n    complex: {\n\n        \"<bg-position>\": function(expression){\n            var types   = this,\n                result  = false,\n                numeric = \"<percentage> | <length>\",\n                xDir    = \"left | right\",\n                yDir    = \"top | bottom\",\n                count = 0,\n                hasNext = function() {\n                    return expression.hasNext() && expression.peek() != \",\";\n                };\n\n            while (expression.peek(count) && expression.peek(count) != \",\") {\n                count++;\n            }\n\n/*\n<position> = [\n  [ left | center | right | top | bottom | <percentage> | <length> ]\n|\n  [ left | center | right | <percentage> | <length> ]\n  [ top | center | bottom | <percentage> | <length> ]\n|\n  [ center | [ left | right ] [ <percentage> | <length> ]? ] &&\n  [ center | [ top | bottom ] [ <percentage> | <length> ]? ]\n]\n*/\n\n            if (count < 3) {\n                if (ValidationTypes.isAny(expression, xDir + \" | center | \" + numeric)) {\n                        result = true;\n                        ValidationTypes.isAny(expression, yDir + \" | center | \" + numeric);\n                } else if (ValidationTypes.isAny(expression, yDir)) {\n                        result = true;\n                        ValidationTypes.isAny(expression, xDir + \" | center\");\n                }\n            } else {\n                if (ValidationTypes.isAny(expression, xDir)) {\n                    if (ValidationTypes.isAny(expression, yDir)) {\n                        result = true;\n                        ValidationTypes.isAny(expression, numeric);\n                    } else if (ValidationTypes.isAny(expression, numeric)) {\n                        if (ValidationTypes.isAny(expression, yDir)) {\n                            result = true;\n                            ValidationTypes.isAny(expression, numeric);\n                        } else if (ValidationTypes.isAny(expression, \"center\")) {\n                            result = true;\n                        }\n                    }\n                } else if (ValidationTypes.isAny(expression, yDir)) {\n                    if (ValidationTypes.isAny(expression, xDir)) {\n                        result = true;\n                        ValidationTypes.isAny(expression, numeric);\n                    } else if (ValidationTypes.isAny(expression, numeric)) {\n                        if (ValidationTypes.isAny(expression, xDir)) {\n                                result = true;\n                                ValidationTypes.isAny(expression, numeric);\n                        } else if (ValidationTypes.isAny(expression, \"center\")) {\n                            result = true;\n                        }\n                    }\n                } else if (ValidationTypes.isAny(expression, \"center\")) {\n                    if (ValidationTypes.isAny(expression, xDir + \" | \" + yDir)) {\n                        result = true;\n                        ValidationTypes.isAny(expression, numeric);\n                    }\n                }\n            }\n\n            return result;\n        },\n\n        \"<bg-size>\": function(expression){\n            //<bg-size> = [ <length> | <percentage> | auto ]{1,2} | cover | contain\n            var types   = this,\n                result  = false,\n                numeric = \"<percentage> | <length> | auto\",\n                part,\n                i, len;\n\n            if (ValidationTypes.isAny(expression, \"cover | contain\")) {\n                result = true;\n            } else if (ValidationTypes.isAny(expression, numeric)) {\n                result = true;\n                ValidationTypes.isAny(expression, numeric);\n            }\n\n            return result;\n        },\n\n        \"<repeat-style>\": function(expression){\n            //repeat-x | repeat-y | [repeat | space | round | no-repeat]{1,2}\n            var result  = false,\n                values  = \"repeat | space | round | no-repeat\",\n                part;\n\n            if (expression.hasNext()){\n                part = expression.next();\n\n                if (ValidationTypes.isLiteral(part, \"repeat-x | repeat-y\")) {\n                    result = true;\n                } else if (ValidationTypes.isLiteral(part, values)) {\n                    result = true;\n\n                    if (expression.hasNext() && ValidationTypes.isLiteral(expression.peek(), values)) {\n                        expression.next();\n                    }\n                }\n            }\n\n            return result;\n\n        },\n\n        \"<shadow>\": function(expression) {\n            //inset? && [ <length>{2,4} && <color>? ]\n            var result  = false,\n                count   = 0,\n                inset   = false,\n                color   = false,\n                part;\n\n            if (expression.hasNext()) {\n\n                if (ValidationTypes.isAny(expression, \"inset\")){\n                    inset = true;\n                }\n\n                if (ValidationTypes.isAny(expression, \"<color>\")) {\n                    color = true;\n                }\n\n                while (ValidationTypes.isAny(expression, \"<length>\") && count < 4) {\n                    count++;\n                }\n\n\n                if (expression.hasNext()) {\n                    if (!color) {\n                        ValidationTypes.isAny(expression, \"<color>\");\n                    }\n\n                    if (!inset) {\n                        ValidationTypes.isAny(expression, \"inset\");\n                    }\n\n                }\n\n                result = (count >= 2 && count <= 4);\n\n            }\n\n            return result;\n        },\n\n        \"<x-one-radius>\": function(expression) {\n            //[ <length> | <percentage> ] [ <length> | <percentage> ]?\n            var result  = false,\n                count   = 0,\n                numeric = \"<length> | <percentage>\",\n                part;\n\n            if (ValidationTypes.isAny(expression, numeric)){\n                result = true;\n\n                ValidationTypes.isAny(expression, numeric);\n            }\n\n            return result;\n        }\n    }\n};\n\n\n\nparserlib.css = {\nColors              :Colors,\nCombinator          :Combinator,\nParser              :Parser,\nPropertyName        :PropertyName,\nPropertyValue       :PropertyValue,\nPropertyValuePart   :PropertyValuePart,\nMediaFeature        :MediaFeature,\nMediaQuery          :MediaQuery,\nSelector            :Selector,\nSelectorPart        :SelectorPart,\nSelectorSubPart     :SelectorSubPart,\nSpecificity         :Specificity,\nTokenStream         :TokenStream,\nTokens              :Tokens,\nValidationError     :ValidationError\n};\n})();\n\n\n/**\n * Main CSSLint object.\n * @class CSSLint\n * @static\n * @extends parserlib.util.EventTarget\n */\n/*global parserlib, Reporter*/\nvar CSSLint = (function(){\n\n    var rules           = [],\n        formatters      = [],\n        embeddedRuleset = /\\/\\*csslint([^\\*]*)\\*\\//,\n        api             = new parserlib.util.EventTarget();\n\n    api.version = \"0.9.10\";\n\n    //-------------------------------------------------------------------------\n    // Rule Management\n    //-------------------------------------------------------------------------\n\n    /**\n     * Adds a new rule to the engine.\n     * @param {Object} rule The rule to add.\n     * @method addRule\n     */\n    api.addRule = function(rule){\n        rules.push(rule);\n        rules[rule.id] = rule;\n    };\n\n    /**\n     * Clears all rule from the engine.\n     * @method clearRules\n     */\n    api.clearRules = function(){\n        rules = [];\n    };\n\n    /**\n     * Returns the rule objects.\n     * @return An array of rule objects.\n     * @method getRules\n     */\n    api.getRules = function(){\n        return [].concat(rules).sort(function(a,b){\n            return a.id > b.id ? 1 : 0;\n        });\n    };\n\n    /**\n     * Returns a ruleset configuration object with all current rules.\n     * @return A ruleset object.\n     * @method getRuleset\n     */\n    api.getRuleset = function() {\n        var ruleset = {},\n            i = 0,\n            len = rules.length;\n\n        while (i < len){\n            ruleset[rules[i++].id] = 1;    //by default, everything is a warning\n        }\n\n        return ruleset;\n    };\n\n    /**\n     * Returns a ruleset object based on embedded rules.\n     * @param {String} text A string of css containing embedded rules.\n     * @param {Object} ruleset A ruleset object to modify.\n     * @return {Object} A ruleset object.\n     * @method getEmbeddedRuleset\n     */\n    function applyEmbeddedRuleset(text, ruleset){\n        var valueMap,\n            embedded = text && text.match(embeddedRuleset),\n            rules = embedded && embedded[1];\n\n        if (rules) {\n            valueMap = {\n                \"true\": 2,  // true is error\n                \"\": 1,      // blank is warning\n                \"false\": 0, // false is ignore\n\n                \"2\": 2,     // explicit error\n                \"1\": 1,     // explicit warning\n                \"0\": 0      // explicit ignore\n            };\n\n            rules.toLowerCase().split(\",\").forEach(function(rule){\n                var pair = rule.split(\":\"),\n                    property = pair[0] || \"\",\n                    value = pair[1] || \"\";\n\n                ruleset[property.trim()] = valueMap[value.trim()];\n            });\n        }\n\n        return ruleset;\n    }\n\n    //-------------------------------------------------------------------------\n    // Formatters\n    //-------------------------------------------------------------------------\n\n    /**\n     * Adds a new formatter to the engine.\n     * @param {Object} formatter The formatter to add.\n     * @method addFormatter\n     */\n    api.addFormatter = function(formatter) {\n        // formatters.push(formatter);\n        formatters[formatter.id] = formatter;\n    };\n\n    /**\n     * Retrieves a formatter for use.\n     * @param {String} formatId The name of the format to retrieve.\n     * @return {Object} The formatter or undefined.\n     * @method getFormatter\n     */\n    api.getFormatter = function(formatId){\n        return formatters[formatId];\n    };\n\n    /**\n     * Formats the results in a particular format for a single file.\n     * @param {Object} result The results returned from CSSLint.verify().\n     * @param {String} filename The filename for which the results apply.\n     * @param {String} formatId The name of the formatter to use.\n     * @param {Object} options (Optional) for special output handling.\n     * @return {String} A formatted string for the results.\n     * @method format\n     */\n    api.format = function(results, filename, formatId, options) {\n        var formatter = this.getFormatter(formatId),\n            result = null;\n\n        if (formatter){\n            result = formatter.startFormat();\n            result += formatter.formatResults(results, filename, options || {});\n            result += formatter.endFormat();\n        }\n\n        return result;\n    };\n\n    /**\n     * Indicates if the given format is supported.\n     * @param {String} formatId The ID of the format to check.\n     * @return {Boolean} True if the format exists, false if not.\n     * @method hasFormat\n     */\n    api.hasFormat = function(formatId){\n        return formatters.hasOwnProperty(formatId);\n    };\n\n    //-------------------------------------------------------------------------\n    // Verification\n    //-------------------------------------------------------------------------\n\n    /**\n     * Starts the verification process for the given CSS text.\n     * @param {String} text The CSS text to verify.\n     * @param {Object} ruleset (Optional) List of rules to apply. If null, then\n     *      all rules are used. If a rule has a value of 1 then it's a warning,\n     *      a value of 2 means it's an error.\n     * @return {Object} Results of the verification.\n     * @method verify\n     */\n    api.verify = function(text, ruleset){\n\n        var i       = 0,\n            len     = rules.length,\n            reporter,\n            lines,\n            report,\n            parser = new parserlib.css.Parser({ starHack: true, ieFilters: true,\n                                                underscoreHack: true, strict: false });\n\n        // normalize line endings\n        lines = text.replace(/\\n\\r?/g, \"$split$\").split('$split$');\n\n        if (!ruleset){\n            ruleset = this.getRuleset();\n        }\n\n        if (embeddedRuleset.test(text)){\n            ruleset = applyEmbeddedRuleset(text, ruleset);\n        }\n\n        reporter = new Reporter(lines, ruleset);\n\n        ruleset.errors = 2;       //always report parsing errors as errors\n        for (i in ruleset){\n            if(ruleset.hasOwnProperty(i) && ruleset[i]){\n                if (rules[i]){\n                    rules[i].init(parser, reporter);\n                }\n            }\n        }\n\n\n        //capture most horrible error type\n        try {\n            parser.parse(text);\n        } catch (ex) {\n            reporter.error(\"Fatal error, cannot continue: \" + ex.message, ex.line, ex.col, {});\n        }\n\n        report = {\n            messages    : reporter.messages,\n            stats       : reporter.stats,\n            ruleset     : reporter.ruleset\n        };\n\n        //sort by line numbers, rollups at the bottom\n        report.messages.sort(function (a, b){\n            if (a.rollup && !b.rollup){\n                return 1;\n            } else if (!a.rollup && b.rollup){\n                return -1;\n            } else {\n                return a.line - b.line;\n            }\n        });\n\n        return report;\n    };\n\n    //-------------------------------------------------------------------------\n    // Publish the API\n    //-------------------------------------------------------------------------\n\n    return api;\n\n})();\n/*global CSSLint*/\n/**\n * An instance of Report is used to report results of the\n * verification back to the main API.\n * @class Reporter\n * @constructor\n * @param {String[]} lines The text lines of the source.\n * @param {Object} ruleset The set of rules to work with, including if\n *      they are errors or warnings.\n */\nfunction Reporter(lines, ruleset){\n\n    /**\n     * List of messages being reported.\n     * @property messages\n     * @type String[]\n     */\n    this.messages = [];\n\n    /**\n     * List of statistics being reported.\n     * @property stats\n     * @type String[]\n     */\n    this.stats = [];\n\n    /**\n     * Lines of code being reported on. Used to provide contextual information\n     * for messages.\n     * @property lines\n     * @type String[]\n     */\n    this.lines = lines;\n\n    /**\n     * Information about the rules. Used to determine whether an issue is an\n     * error or warning.\n     * @property ruleset\n     * @type Object\n     */\n    this.ruleset = ruleset;\n}\n\nReporter.prototype = {\n\n    //restore constructor\n    constructor: Reporter,\n\n    /**\n     * Report an error.\n     * @param {String} message The message to store.\n     * @param {int} line The line number.\n     * @param {int} col The column number.\n     * @param {Object} rule The rule this message relates to.\n     * @method error\n     */\n    error: function(message, line, col, rule){\n        this.messages.push({\n            type    : \"error\",\n            line    : line,\n            col     : col,\n            message : message,\n            evidence: this.lines[line-1],\n            rule    : rule || {}\n        });\n    },\n\n    /**\n     * Report an warning.\n     * @param {String} message The message to store.\n     * @param {int} line The line number.\n     * @param {int} col The column number.\n     * @param {Object} rule The rule this message relates to.\n     * @method warn\n     * @deprecated Use report instead.\n     */\n    warn: function(message, line, col, rule){\n        this.report(message, line, col, rule);\n    },\n\n    /**\n     * Report an issue.\n     * @param {String} message The message to store.\n     * @param {int} line The line number.\n     * @param {int} col The column number.\n     * @param {Object} rule The rule this message relates to.\n     * @method report\n     */\n    report: function(message, line, col, rule){\n        this.messages.push({\n            type    : this.ruleset[rule.id] == 2 ? \"error\" : \"warning\",\n            line    : line,\n            col     : col,\n            message : message,\n            evidence: this.lines[line-1],\n            rule    : rule\n        });\n    },\n\n    /**\n     * Report some informational text.\n     * @param {String} message The message to store.\n     * @param {int} line The line number.\n     * @param {int} col The column number.\n     * @param {Object} rule The rule this message relates to.\n     * @method info\n     */\n    info: function(message, line, col, rule){\n        this.messages.push({\n            type    : \"info\",\n            line    : line,\n            col     : col,\n            message : message,\n            evidence: this.lines[line-1],\n            rule    : rule\n        });\n    },\n\n    /**\n     * Report some rollup error information.\n     * @param {String} message The message to store.\n     * @param {Object} rule The rule this message relates to.\n     * @method rollupError\n     */\n    rollupError: function(message, rule){\n        this.messages.push({\n            type    : \"error\",\n            rollup  : true,\n            message : message,\n            rule    : rule\n        });\n    },\n\n    /**\n     * Report some rollup warning information.\n     * @param {String} message The message to store.\n     * @param {Object} rule The rule this message relates to.\n     * @method rollupWarn\n     */\n    rollupWarn: function(message, rule){\n        this.messages.push({\n            type    : \"warning\",\n            rollup  : true,\n            message : message,\n            rule    : rule\n        });\n    },\n\n    /**\n     * Report a statistic.\n     * @param {String} name The name of the stat to store.\n     * @param {Variant} value The value of the stat.\n     * @method stat\n     */\n    stat: function(name, value){\n        this.stats[name] = value;\n    }\n};\n\n//expose for testing purposes\nCSSLint._Reporter = Reporter;\n\n/*global CSSLint*/\n\n/*\n * Utility functions that make life easier.\n */\nCSSLint.Util = {\n    /*\n     * Adds all properties from supplier onto receiver,\n     * overwriting if the same name already exists on\n     * reciever.\n     * @param {Object} The object to receive the properties.\n     * @param {Object} The object to provide the properties.\n     * @return {Object} The receiver\n     */\n    mix: function(receiver, supplier){\n        var prop;\n\n        for (prop in supplier){\n            if (supplier.hasOwnProperty(prop)){\n                receiver[prop] = supplier[prop];\n            }\n        }\n\n        return prop;\n    },\n\n    /*\n     * Polyfill for array indexOf() method.\n     * @param {Array} values The array to search.\n     * @param {Variant} value The value to search for.\n     * @return {int} The index of the value if found, -1 if not.\n     */\n    indexOf: function(values, value){\n        if (values.indexOf){\n            return values.indexOf(value);\n        } else {\n            for (var i=0, len=values.length; i < len; i++){\n                if (values[i] === value){\n                    return i;\n                }\n            }\n            return -1;\n        }\n    },\n\n    /*\n     * Polyfill for array forEach() method.\n     * @param {Array} values The array to operate on.\n     * @param {Function} func The function to call on each item.\n     * @return {void}\n     */\n    forEach: function(values, func) {\n        if (values.forEach){\n            return values.forEach(func);\n        } else {\n            for (var i=0, len=values.length; i < len; i++){\n                func(values[i], i, values);\n            }\n        }\n    }\n};\n/*global CSSLint*/\n/*\n * Rule: Don't use adjoining classes (.foo.bar).\n */\nCSSLint.addRule({\n\n    //rule information\n    id: \"adjoining-classes\",\n    name: \"Disallow adjoining classes\",\n    desc: \"Don't use adjoining classes.\",\n    browsers: \"IE6\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n        parser.addListener(\"startrule\", function(event){\n            var selectors = event.selectors,\n                selector,\n                part,\n                modifier,\n                classCount,\n                i, j, k;\n\n            for (i=0; i < selectors.length; i++){\n                selector = selectors[i];\n                for (j=0; j < selector.parts.length; j++){\n                    part = selector.parts[j];\n                    if (part.type == parser.SELECTOR_PART_TYPE){\n                        classCount = 0;\n                        for (k=0; k < part.modifiers.length; k++){\n                            modifier = part.modifiers[k];\n                            if (modifier.type == \"class\"){\n                                classCount++;\n                            }\n                            if (classCount > 1){\n                                reporter.report(\"Don't use adjoining classes.\", part.line, part.col, rule);\n                            }\n                        }\n                    }\n                }\n            }\n        });\n    }\n\n});\n/*global CSSLint*/\n\n/*\n * Rule: Don't use width or height when using padding or border.\n */\nCSSLint.addRule({\n\n    //rule information\n    id: \"box-model\",\n    name: \"Beware of broken box size\",\n    desc: \"Don't use width or height when using padding or border.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            widthProperties = {\n                border: 1,\n                \"border-left\": 1,\n                \"border-right\": 1,\n                padding: 1,\n                \"padding-left\": 1,\n                \"padding-right\": 1\n            },\n            heightProperties = {\n                border: 1,\n                \"border-bottom\": 1,\n                \"border-top\": 1,\n                padding: 1,\n                \"padding-bottom\": 1,\n                \"padding-top\": 1\n            },\n            properties,\n            boxSizing = false;\n\n        function startRule(){\n            properties = {};\n            boxSizing = false;\n        }\n\n        function endRule(){\n            var prop, value;\n\n            if (!boxSizing) {\n                if (properties.height){\n                    for (prop in heightProperties){\n                        if (heightProperties.hasOwnProperty(prop) && properties[prop]){\n                            value = properties[prop].value;\n                            //special case for padding\n                            if (!(prop == \"padding\" && value.parts.length === 2 && value.parts[0].value === 0)){\n                                reporter.report(\"Using height with \" + prop + \" can sometimes make elements larger than you expect.\", properties[prop].line, properties[prop].col, rule);\n                            }\n                        }\n                    }\n                }\n\n                if (properties.width){\n                    for (prop in widthProperties){\n                        if (widthProperties.hasOwnProperty(prop) && properties[prop]){\n                            value = properties[prop].value;\n\n                            if (!(prop == \"padding\" && value.parts.length === 2 && value.parts[1].value === 0)){\n                                reporter.report(\"Using width with \" + prop + \" can sometimes make elements larger than you expect.\", properties[prop].line, properties[prop].col, rule);\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        parser.addListener(\"startrule\", startRule);\n        parser.addListener(\"startfontface\", startRule);\n        parser.addListener(\"startpage\", startRule);\n        parser.addListener(\"startpagemargin\", startRule);\n        parser.addListener(\"startkeyframerule\", startRule);\n\n        parser.addListener(\"property\", function(event){\n            var name = event.property.text.toLowerCase();\n\n            if (heightProperties[name] || widthProperties[name]){\n                if (!/^0\\S*$/.test(event.value) && !(name == \"border\" && event.value == \"none\")){\n                    properties[name] = { line: event.property.line, col: event.property.col, value: event.value };\n                }\n            } else {\n                if (/^(width|height)/i.test(name) && /^(length|percentage)/.test(event.value.parts[0].type)){\n                    properties[name] = 1;\n                } else if (name == \"box-sizing\") {\n                    boxSizing = true;\n                }\n            }\n\n        });\n\n        parser.addListener(\"endrule\", endRule);\n        parser.addListener(\"endfontface\", endRule);\n        parser.addListener(\"endpage\", endRule);\n        parser.addListener(\"endpagemargin\", endRule);\n        parser.addListener(\"endkeyframerule\", endRule);\n    }\n\n});\n/*global CSSLint*/\n\n/*\n * Rule: box-sizing doesn't work in IE6 and IE7.\n */\nCSSLint.addRule({\n\n    //rule information\n    id: \"box-sizing\",\n    name: \"Disallow use of box-sizing\",\n    desc: \"The box-sizing properties isn't supported in IE6 and IE7.\",\n    browsers: \"IE6, IE7\",\n    tags: [\"Compatibility\"],\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n\n        parser.addListener(\"property\", function(event){\n            var name = event.property.text.toLowerCase();\n\n            if (name == \"box-sizing\"){\n                reporter.report(\"The box-sizing property isn't supported in IE6 and IE7.\", event.line, event.col, rule);\n            }\n        });\n    }\n\n});\n/*\n * Rule: Use the bulletproof @font-face syntax to avoid 404's in old IE\n * (http://www.fontspring.com/blog/the-new-bulletproof-font-face-syntax)\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"bulletproof-font-face\",\n    name: \"Use the bulletproof @font-face syntax\",\n    desc: \"Use the bulletproof @font-face syntax to avoid 404's in old IE (http://www.fontspring.com/blog/the-new-bulletproof-font-face-syntax).\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            count = 0,\n            fontFaceRule = false,\n            firstSrc     = true,\n            ruleFailed    = false,\n            line, col;\n\n        // Mark the start of a @font-face declaration so we only test properties inside it\n        parser.addListener(\"startfontface\", function(event){\n            fontFaceRule = true;\n        });\n\n        parser.addListener(\"property\", function(event){\n            // If we aren't inside an @font-face declaration then just return\n            if (!fontFaceRule) {\n                return;\n            }\n\n            var propertyName = event.property.toString().toLowerCase(),\n                value        = event.value.toString();\n\n            // Set the line and col numbers for use in the endfontface listener\n            line = event.line;\n            col  = event.col;\n\n            // This is the property that we care about, we can ignore the rest\n            if (propertyName === 'src') {\n                var regex = /^\\s?url\\(['\"].+\\.eot\\?.*['\"]\\)\\s*format\\(['\"]embedded-opentype['\"]\\).*$/i;\n\n                // We need to handle the advanced syntax with two src properties\n                if (!value.match(regex) && firstSrc) {\n                    ruleFailed = true;\n                    firstSrc = false;\n                } else if (value.match(regex) && !firstSrc) {\n                    ruleFailed = false;\n                }\n            }\n\n\n        });\n\n        // Back to normal rules that we don't need to test\n        parser.addListener(\"endfontface\", function(event){\n            fontFaceRule = false;\n\n            if (ruleFailed) {\n                reporter.report(\"@font-face declaration doesn't follow the fontspring bulletproof syntax.\", line, col, rule);\n            }\n        });\n    }\n});\n/*\n * Rule: Include all compatible vendor prefixes to reach a wider\n * range of users.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"compatible-vendor-prefixes\",\n    name: \"Require compatible vendor prefixes\",\n    desc: \"Include all compatible vendor prefixes to reach a wider range of users.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function (parser, reporter) {\n        var rule = this,\n            compatiblePrefixes,\n            properties,\n            prop,\n            variations,\n            prefixed,\n            i,\n            len,\n            inKeyFrame = false,\n            arrayPush = Array.prototype.push,\n            applyTo = [];\n\n        // See http://peter.sh/experiments/vendor-prefixed-css-property-overview/ for details\n        compatiblePrefixes = {\n            \"animation\"                  : \"webkit moz\",\n            \"animation-delay\"            : \"webkit moz\",\n            \"animation-direction\"        : \"webkit moz\",\n            \"animation-duration\"         : \"webkit moz\",\n            \"animation-fill-mode\"        : \"webkit moz\",\n            \"animation-iteration-count\"  : \"webkit moz\",\n            \"animation-name\"             : \"webkit moz\",\n            \"animation-play-state\"       : \"webkit moz\",\n            \"animation-timing-function\"  : \"webkit moz\",\n            \"appearance\"                 : \"webkit moz\",\n            \"border-end\"                 : \"webkit moz\",\n            \"border-end-color\"           : \"webkit moz\",\n            \"border-end-style\"           : \"webkit moz\",\n            \"border-end-width\"           : \"webkit moz\",\n            \"border-image\"               : \"webkit moz o\",\n            \"border-radius\"              : \"webkit\",\n            \"border-start\"               : \"webkit moz\",\n            \"border-start-color\"         : \"webkit moz\",\n            \"border-start-style\"         : \"webkit moz\",\n            \"border-start-width\"         : \"webkit moz\",\n            \"box-align\"                  : \"webkit moz ms\",\n            \"box-direction\"              : \"webkit moz ms\",\n            \"box-flex\"                   : \"webkit moz ms\",\n            \"box-lines\"                  : \"webkit ms\",\n            \"box-ordinal-group\"          : \"webkit moz ms\",\n            \"box-orient\"                 : \"webkit moz ms\",\n            \"box-pack\"                   : \"webkit moz ms\",\n            \"box-sizing\"                 : \"webkit moz\",\n            \"box-shadow\"                 : \"webkit moz\",\n            \"column-count\"               : \"webkit moz ms\",\n            \"column-gap\"                 : \"webkit moz ms\",\n            \"column-rule\"                : \"webkit moz ms\",\n            \"column-rule-color\"          : \"webkit moz ms\",\n            \"column-rule-style\"          : \"webkit moz ms\",\n            \"column-rule-width\"          : \"webkit moz ms\",\n            \"column-width\"               : \"webkit moz ms\",\n            \"hyphens\"                    : \"epub moz\",\n            \"line-break\"                 : \"webkit ms\",\n            \"margin-end\"                 : \"webkit moz\",\n            \"margin-start\"               : \"webkit moz\",\n            \"marquee-speed\"              : \"webkit wap\",\n            \"marquee-style\"              : \"webkit wap\",\n            \"padding-end\"                : \"webkit moz\",\n            \"padding-start\"              : \"webkit moz\",\n            \"tab-size\"                   : \"moz o\",\n            \"text-size-adjust\"           : \"webkit ms\",\n            \"transform\"                  : \"webkit moz ms o\",\n            \"transform-origin\"           : \"webkit moz ms o\",\n            \"transition\"                 : \"webkit moz o\",\n            \"transition-delay\"           : \"webkit moz o\",\n            \"transition-duration\"        : \"webkit moz o\",\n            \"transition-property\"        : \"webkit moz o\",\n            \"transition-timing-function\" : \"webkit moz o\",\n            \"user-modify\"                : \"webkit moz\",\n            \"user-select\"                : \"webkit moz ms\",\n            \"word-break\"                 : \"epub ms\",\n            \"writing-mode\"               : \"epub ms\"\n        };\n\n\n        for (prop in compatiblePrefixes) {\n            if (compatiblePrefixes.hasOwnProperty(prop)) {\n                variations = [];\n                prefixed = compatiblePrefixes[prop].split(' ');\n                for (i = 0, len = prefixed.length; i < len; i++) {\n                    variations.push('-' + prefixed[i] + '-' + prop);\n                }\n                compatiblePrefixes[prop] = variations;\n                arrayPush.apply(applyTo, variations);\n            }\n        }\n\n        parser.addListener(\"startrule\", function () {\n            properties = [];\n        });\n\n        parser.addListener(\"startkeyframes\", function (event) {\n            inKeyFrame = event.prefix || true;\n        });\n\n        parser.addListener(\"endkeyframes\", function (event) {\n            inKeyFrame = false;\n        });\n\n        parser.addListener(\"property\", function (event) {\n            var name = event.property;\n            if (CSSLint.Util.indexOf(applyTo, name.text) > -1) {\n\n                // e.g., -moz-transform is okay to be alone in @-moz-keyframes\n                if (!inKeyFrame || typeof inKeyFrame != \"string\" ||\n                        name.text.indexOf(\"-\" + inKeyFrame + \"-\") !== 0) {\n                    properties.push(name);\n                }\n            }\n        });\n\n        parser.addListener(\"endrule\", function (event) {\n            if (!properties.length) {\n                return;\n            }\n\n            var propertyGroups = {},\n                i,\n                len,\n                name,\n                prop,\n                variations,\n                value,\n                full,\n                actual,\n                item,\n                propertiesSpecified;\n\n            for (i = 0, len = properties.length; i < len; i++) {\n                name = properties[i];\n\n                for (prop in compatiblePrefixes) {\n                    if (compatiblePrefixes.hasOwnProperty(prop)) {\n                        variations = compatiblePrefixes[prop];\n                        if (CSSLint.Util.indexOf(variations, name.text) > -1) {\n                            if (!propertyGroups[prop]) {\n                                propertyGroups[prop] = {\n                                    full : variations.slice(0),\n                                    actual : [],\n                                    actualNodes: []\n                                };\n                            }\n                            if (CSSLint.Util.indexOf(propertyGroups[prop].actual, name.text) === -1) {\n                                propertyGroups[prop].actual.push(name.text);\n                                propertyGroups[prop].actualNodes.push(name);\n                            }\n                        }\n                    }\n                }\n            }\n\n            for (prop in propertyGroups) {\n                if (propertyGroups.hasOwnProperty(prop)) {\n                    value = propertyGroups[prop];\n                    full = value.full;\n                    actual = value.actual;\n\n                    if (full.length > actual.length) {\n                        for (i = 0, len = full.length; i < len; i++) {\n                            item = full[i];\n                            if (CSSLint.Util.indexOf(actual, item) === -1) {\n                                propertiesSpecified = (actual.length === 1) ? actual[0] : (actual.length == 2) ? actual.join(\" and \") : actual.join(\", \");\n                                reporter.report(\"The property \" + item + \" is compatible with \" + propertiesSpecified + \" and should be included as well.\", value.actualNodes[0].line, value.actualNodes[0].col, rule);\n                            }\n                        }\n\n                    }\n                }\n            }\n        });\n    }\n});\n/*\n * Rule: Certain properties don't play well with certain display values.\n * - float should not be used with inline-block\n * - height, width, margin-top, margin-bottom, float should not be used with inline\n * - vertical-align should not be used with block\n * - margin, float should not be used with table-*\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"display-property-grouping\",\n    name: \"Require properties appropriate for display\",\n    desc: \"Certain properties shouldn't be used with certain display property values.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n\n        var propertiesToCheck = {\n                display: 1,\n                \"float\": \"none\",\n                height: 1,\n                width: 1,\n                margin: 1,\n                \"margin-left\": 1,\n                \"margin-right\": 1,\n                \"margin-bottom\": 1,\n                \"margin-top\": 1,\n                padding: 1,\n                \"padding-left\": 1,\n                \"padding-right\": 1,\n                \"padding-bottom\": 1,\n                \"padding-top\": 1,\n                \"vertical-align\": 1\n            },\n            properties;\n\n        function reportProperty(name, display, msg){\n            if (properties[name]){\n                if (typeof propertiesToCheck[name] != \"string\" || properties[name].value.toLowerCase() != propertiesToCheck[name]){\n                    reporter.report(msg || name + \" can't be used with display: \" + display + \".\", properties[name].line, properties[name].col, rule);\n                }\n            }\n        }\n\n        function startRule(){\n            properties = {};\n        }\n\n        function endRule(){\n\n            var display = properties.display ? properties.display.value : null;\n            if (display){\n                switch(display){\n\n                    case \"inline\":\n                        //height, width, margin-top, margin-bottom, float should not be used with inline\n                        reportProperty(\"height\", display);\n                        reportProperty(\"width\", display);\n                        reportProperty(\"margin\", display);\n                        reportProperty(\"margin-top\", display);\n                        reportProperty(\"margin-bottom\", display);\n                        reportProperty(\"float\", display, \"display:inline has no effect on floated elements (but may be used to fix the IE6 double-margin bug).\");\n                        break;\n\n                    case \"block\":\n                        //vertical-align should not be used with block\n                        reportProperty(\"vertical-align\", display);\n                        break;\n\n                    case \"inline-block\":\n                        //float should not be used with inline-block\n                        reportProperty(\"float\", display);\n                        break;\n\n                    default:\n                        //margin, float should not be used with table\n                        if (display.indexOf(\"table-\") === 0){\n                            reportProperty(\"margin\", display);\n                            reportProperty(\"margin-left\", display);\n                            reportProperty(\"margin-right\", display);\n                            reportProperty(\"margin-top\", display);\n                            reportProperty(\"margin-bottom\", display);\n                            reportProperty(\"float\", display);\n                        }\n\n                        //otherwise do nothing\n                }\n            }\n\n        }\n\n        parser.addListener(\"startrule\", startRule);\n        parser.addListener(\"startfontface\", startRule);\n        parser.addListener(\"startkeyframerule\", startRule);\n        parser.addListener(\"startpagemargin\", startRule);\n        parser.addListener(\"startpage\", startRule);\n\n        parser.addListener(\"property\", function(event){\n            var name = event.property.text.toLowerCase();\n\n            if (propertiesToCheck[name]){\n                properties[name] = { value: event.value.text, line: event.property.line, col: event.property.col };\n            }\n        });\n\n        parser.addListener(\"endrule\", endRule);\n        parser.addListener(\"endfontface\", endRule);\n        parser.addListener(\"endkeyframerule\", endRule);\n        parser.addListener(\"endpagemargin\", endRule);\n        parser.addListener(\"endpage\", endRule);\n\n    }\n\n});\n/*\n * Rule: Disallow duplicate background-images (using url).\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"duplicate-background-images\",\n    name: \"Disallow duplicate background images\",\n    desc: \"Every background-image should be unique. Use a common class for e.g. sprites.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            stack = {};\n\n        parser.addListener(\"property\", function(event){\n            var name = event.property.text,\n                value = event.value,\n                i, len;\n\n            if (name.match(/background/i)) {\n                for (i=0, len=value.parts.length; i < len; i++) {\n                    if (value.parts[i].type == 'uri') {\n                        if (typeof stack[value.parts[i].uri] === 'undefined') {\n                            stack[value.parts[i].uri] = event;\n                        }\n                        else {\n                            reporter.report(\"Background image '\" + value.parts[i].uri + \"' was used multiple times, first declared at line \" + stack[value.parts[i].uri].line + \", col \" + stack[value.parts[i].uri].col + \".\", event.line, event.col, rule);\n                        }\n                    }\n                }\n            }\n        });\n    }\n});\n/*\n * Rule: Duplicate properties must appear one after the other. If an already-defined\n * property appears somewhere else in the rule, then it's likely an error.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"duplicate-properties\",\n    name: \"Disallow duplicate properties\",\n    desc: \"Duplicate properties must appear one after the other.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            properties,\n            lastProperty;\n\n        function startRule(event){\n            properties = {};\n        }\n\n        parser.addListener(\"startrule\", startRule);\n        parser.addListener(\"startfontface\", startRule);\n        parser.addListener(\"startpage\", startRule);\n        parser.addListener(\"startpagemargin\", startRule);\n        parser.addListener(\"startkeyframerule\", startRule);\n\n        parser.addListener(\"property\", function(event){\n            var property = event.property,\n                name = property.text.toLowerCase();\n\n            if (properties[name] && (lastProperty != name || properties[name] == event.value.text)){\n                reporter.report(\"Duplicate property '\" + event.property + \"' found.\", event.line, event.col, rule);\n            }\n\n            properties[name] = event.value.text;\n            lastProperty = name;\n\n        });\n\n\n    }\n\n});\n/*\n * Rule: Style rules without any properties defined should be removed.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"empty-rules\",\n    name: \"Disallow empty rules\",\n    desc: \"Rules without any properties specified should be removed.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            count = 0;\n\n        parser.addListener(\"startrule\", function(){\n            count=0;\n        });\n\n        parser.addListener(\"property\", function(){\n            count++;\n        });\n\n        parser.addListener(\"endrule\", function(event){\n            var selectors = event.selectors;\n            if (count === 0){\n                reporter.report(\"Rule is empty.\", selectors[0].line, selectors[0].col, rule);\n            }\n        });\n    }\n\n});\n/*\n * Rule: There should be no syntax errors. (Duh.)\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"errors\",\n    name: \"Parsing Errors\",\n    desc: \"This rule looks for recoverable syntax errors.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n\n        parser.addListener(\"error\", function(event){\n            reporter.error(event.message, event.line, event.col, rule);\n        });\n\n    }\n\n});\n\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"fallback-colors\",\n    name: \"Require fallback colors\",\n    desc: \"For older browsers that don't support RGBA, HSL, or HSLA, provide a fallback color.\",\n    browsers: \"IE6,IE7,IE8\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            lastProperty,\n            propertiesToCheck = {\n                color: 1,\n                background: 1,\n                \"border-color\": 1,\n                \"border-top-color\": 1,\n                \"border-right-color\": 1,\n                \"border-bottom-color\": 1,\n                \"border-left-color\": 1,\n                border: 1,\n                \"border-top\": 1,\n                \"border-right\": 1,\n                \"border-bottom\": 1,\n                \"border-left\": 1,\n                \"background-color\": 1\n            },\n            properties;\n\n        function startRule(event){\n            properties = {};\n            lastProperty = null;\n        }\n\n        parser.addListener(\"startrule\", startRule);\n        parser.addListener(\"startfontface\", startRule);\n        parser.addListener(\"startpage\", startRule);\n        parser.addListener(\"startpagemargin\", startRule);\n        parser.addListener(\"startkeyframerule\", startRule);\n\n        parser.addListener(\"property\", function(event){\n            var property = event.property,\n                name = property.text.toLowerCase(),\n                parts = event.value.parts,\n                i = 0,\n                colorType = \"\",\n                len = parts.length;\n\n            if(propertiesToCheck[name]){\n                while(i < len){\n                    if (parts[i].type == \"color\"){\n                        if (\"alpha\" in parts[i] || \"hue\" in parts[i]){\n\n                            if (/([^\\)]+)\\(/.test(parts[i])){\n                                colorType = RegExp.$1.toUpperCase();\n                            }\n\n                            if (!lastProperty || (lastProperty.property.text.toLowerCase() != name || lastProperty.colorType != \"compat\")){\n                                reporter.report(\"Fallback \" + name + \" (hex or RGB) should precede \" + colorType + \" \" + name + \".\", event.line, event.col, rule);\n                            }\n                        } else {\n                            event.colorType = \"compat\";\n                        }\n                    }\n\n                    i++;\n                }\n            }\n\n            lastProperty = event;\n        });\n\n    }\n\n});\n/*\n * Rule: You shouldn't use more than 10 floats. If you do, there's probably\n * room for some abstraction.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"floats\",\n    name: \"Disallow too many floats\",\n    desc: \"This rule tests if the float property is used too many times\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n        var count = 0;\n\n        //count how many times \"float\" is used\n        parser.addListener(\"property\", function(event){\n            if (event.property.text.toLowerCase() == \"float\" &&\n                    event.value.text.toLowerCase() != \"none\"){\n                count++;\n            }\n        });\n\n        //report the results\n        parser.addListener(\"endstylesheet\", function(){\n            reporter.stat(\"floats\", count);\n            if (count >= 10){\n                reporter.rollupWarn(\"Too many floats (\" + count + \"), you're probably using them for layout. Consider using a grid system instead.\", rule);\n            }\n        });\n    }\n\n});\n/*\n * Rule: Avoid too many @font-face declarations in the same stylesheet.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"font-faces\",\n    name: \"Don't use too many web fonts\",\n    desc: \"Too many different web fonts in the same stylesheet.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            count = 0;\n\n\n        parser.addListener(\"startfontface\", function(){\n            count++;\n        });\n\n        parser.addListener(\"endstylesheet\", function(){\n            if (count > 5){\n                reporter.rollupWarn(\"Too many @font-face declarations (\" + count + \").\", rule);\n            }\n        });\n    }\n\n});\n/*\n * Rule: You shouldn't need more than 9 font-size declarations.\n */\n\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"font-sizes\",\n    name: \"Disallow too many font sizes\",\n    desc: \"Checks the number of font-size declarations.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            count = 0;\n\n        //check for use of \"font-size\"\n        parser.addListener(\"property\", function(event){\n            if (event.property == \"font-size\"){\n                count++;\n            }\n        });\n\n        //report the results\n        parser.addListener(\"endstylesheet\", function(){\n            reporter.stat(\"font-sizes\", count);\n            if (count >= 10){\n                reporter.rollupWarn(\"Too many font-size declarations (\" + count + \"), abstraction needed.\", rule);\n            }\n        });\n    }\n\n});\n/*\n * Rule: When using a vendor-prefixed gradient, make sure to use them all.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"gradients\",\n    name: \"Require all gradient definitions\",\n    desc: \"When using a vendor-prefixed gradient, make sure to use them all.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            gradients;\n\n        parser.addListener(\"startrule\", function(){\n            gradients = {\n                moz: 0,\n                webkit: 0,\n                oldWebkit: 0,\n                o: 0\n            };\n        });\n\n        parser.addListener(\"property\", function(event){\n\n            if (/\\-(moz|o|webkit)(?:\\-(?:linear|radial))\\-gradient/i.test(event.value)){\n                gradients[RegExp.$1] = 1;\n            } else if (/\\-webkit\\-gradient/i.test(event.value)){\n                gradients.oldWebkit = 1;\n            }\n\n        });\n\n        parser.addListener(\"endrule\", function(event){\n            var missing = [];\n\n            if (!gradients.moz){\n                missing.push(\"Firefox 3.6+\");\n            }\n\n            if (!gradients.webkit){\n                missing.push(\"Webkit (Safari 5+, Chrome)\");\n            }\n\n            if (!gradients.oldWebkit){\n                missing.push(\"Old Webkit (Safari 4+, Chrome)\");\n            }\n\n            if (!gradients.o){\n                missing.push(\"Opera 11.1+\");\n            }\n\n            if (missing.length && missing.length < 4){\n                reporter.report(\"Missing vendor-prefixed CSS gradients for \" + missing.join(\", \") + \".\", event.selectors[0].line, event.selectors[0].col, rule);\n            }\n\n        });\n\n    }\n\n});\n/*\n * Rule: Don't use IDs for selectors.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"ids\",\n    name: \"Disallow IDs in selectors\",\n    desc: \"Selectors should not contain IDs.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n        parser.addListener(\"startrule\", function(event){\n            var selectors = event.selectors,\n                selector,\n                part,\n                modifier,\n                idCount,\n                i, j, k;\n\n            for (i=0; i < selectors.length; i++){\n                selector = selectors[i];\n                idCount = 0;\n\n                for (j=0; j < selector.parts.length; j++){\n                    part = selector.parts[j];\n                    if (part.type == parser.SELECTOR_PART_TYPE){\n                        for (k=0; k < part.modifiers.length; k++){\n                            modifier = part.modifiers[k];\n                            if (modifier.type == \"id\"){\n                                idCount++;\n                            }\n                        }\n                    }\n                }\n\n                if (idCount == 1){\n                    reporter.report(\"Don't use IDs in selectors.\", selector.line, selector.col, rule);\n                } else if (idCount > 1){\n                    reporter.report(idCount + \" IDs in the selector, really?\", selector.line, selector.col, rule);\n                }\n            }\n\n        });\n    }\n\n});\n/*\n * Rule: Don't use @import, use <link> instead.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"import\",\n    name: \"Disallow @import\",\n    desc: \"Don't use @import, use <link> instead.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n\n        parser.addListener(\"import\", function(event){\n            reporter.report(\"@import prevents parallel downloads, use <link> instead.\", event.line, event.col, rule);\n        });\n\n    }\n\n});\n/*\n * Rule: Make sure !important is not overused, this could lead to specificity\n * war. Display a warning on !important declarations, an error if it's\n * used more at least 10 times.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"important\",\n    name: \"Disallow !important\",\n    desc: \"Be careful when using !important declaration\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            count = 0;\n\n        //warn that important is used and increment the declaration counter\n        parser.addListener(\"property\", function(event){\n            if (event.important === true){\n                count++;\n                reporter.report(\"Use of !important\", event.line, event.col, rule);\n            }\n        });\n\n        //if there are more than 10, show an error\n        parser.addListener(\"endstylesheet\", function(){\n            reporter.stat(\"important\", count);\n            if (count >= 10){\n                reporter.rollupWarn(\"Too many !important declarations (\" + count + \"), try to use less than 10 to avoid specificity issues.\", rule);\n            }\n        });\n    }\n\n});\n/*\n * Rule: Properties should be known (listed in CSS3 specification) or\n * be a vendor-prefixed property.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"known-properties\",\n    name: \"Require use of known properties\",\n    desc: \"Properties should be known (listed in CSS3 specification) or be a vendor-prefixed property.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n\n        parser.addListener(\"property\", function(event){\n            var name = event.property.text.toLowerCase();\n\n            // the check is handled entirely by the parser-lib (https://github.com/nzakas/parser-lib)\n            if (event.invalid) {\n                reporter.report(event.invalid.message, event.line, event.col, rule);\n            }\n\n        });\n    }\n\n});\n/*\n * Rule: outline: none or outline: 0 should only be used in a :focus rule\n *       and only if there are other properties in the same rule.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"outline-none\",\n    name: \"Disallow outline: none\",\n    desc: \"Use of outline: none or outline: 0 should be limited to :focus rules.\",\n    browsers: \"All\",\n    tags: [\"Accessibility\"],\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            lastRule;\n\n        function startRule(event){\n            if (event.selectors){\n                lastRule = {\n                    line: event.line,\n                    col: event.col,\n                    selectors: event.selectors,\n                    propCount: 0,\n                    outline: false\n                };\n            } else {\n                lastRule = null;\n            }\n        }\n\n        function endRule(event){\n            if (lastRule){\n                if (lastRule.outline){\n                    if (lastRule.selectors.toString().toLowerCase().indexOf(\":focus\") == -1){\n                        reporter.report(\"Outlines should only be modified using :focus.\", lastRule.line, lastRule.col, rule);\n                    } else if (lastRule.propCount == 1) {\n                        reporter.report(\"Outlines shouldn't be hidden unless other visual changes are made.\", lastRule.line, lastRule.col, rule);\n                    }\n                }\n            }\n        }\n\n        parser.addListener(\"startrule\", startRule);\n        parser.addListener(\"startfontface\", startRule);\n        parser.addListener(\"startpage\", startRule);\n        parser.addListener(\"startpagemargin\", startRule);\n        parser.addListener(\"startkeyframerule\", startRule);\n\n        parser.addListener(\"property\", function(event){\n            var name = event.property.text.toLowerCase(),\n                value = event.value;\n\n            if (lastRule){\n                lastRule.propCount++;\n                if (name == \"outline\" && (value == \"none\" || value == \"0\")){\n                    lastRule.outline = true;\n                }\n            }\n\n        });\n\n        parser.addListener(\"endrule\", endRule);\n        parser.addListener(\"endfontface\", endRule);\n        parser.addListener(\"endpage\", endRule);\n        parser.addListener(\"endpagemargin\", endRule);\n        parser.addListener(\"endkeyframerule\", endRule);\n\n    }\n\n});\n/*\n * Rule: Don't use classes or IDs with elements (a.foo or a#foo).\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"overqualified-elements\",\n    name: \"Disallow overqualified elements\",\n    desc: \"Don't use classes or IDs with elements (a.foo or a#foo).\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            classes = {};\n\n        parser.addListener(\"startrule\", function(event){\n            var selectors = event.selectors,\n                selector,\n                part,\n                modifier,\n                i, j, k;\n\n            for (i=0; i < selectors.length; i++){\n                selector = selectors[i];\n\n                for (j=0; j < selector.parts.length; j++){\n                    part = selector.parts[j];\n                    if (part.type == parser.SELECTOR_PART_TYPE){\n                        for (k=0; k < part.modifiers.length; k++){\n                            modifier = part.modifiers[k];\n                            if (part.elementName && modifier.type == \"id\"){\n                                reporter.report(\"Element (\" + part + \") is overqualified, just use \" + modifier + \" without element name.\", part.line, part.col, rule);\n                            } else if (modifier.type == \"class\"){\n\n                                if (!classes[modifier]){\n                                    classes[modifier] = [];\n                                }\n                                classes[modifier].push({ modifier: modifier, part: part });\n                            }\n                        }\n                    }\n                }\n            }\n        });\n\n        parser.addListener(\"endstylesheet\", function(){\n\n            var prop;\n            for (prop in classes){\n                if (classes.hasOwnProperty(prop)){\n\n                    //one use means that this is overqualified\n                    if (classes[prop].length == 1 && classes[prop][0].part.elementName){\n                        reporter.report(\"Element (\" + classes[prop][0].part + \") is overqualified, just use \" + classes[prop][0].modifier + \" without element name.\", classes[prop][0].part.line, classes[prop][0].part.col, rule);\n                    }\n                }\n            }\n        });\n    }\n\n});\n/*\n * Rule: Headings (h1-h6) should not be qualified (namespaced).\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"qualified-headings\",\n    name: \"Disallow qualified headings\",\n    desc: \"Headings should not be qualified (namespaced).\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n\n        parser.addListener(\"startrule\", function(event){\n            var selectors = event.selectors,\n                selector,\n                part,\n                i, j;\n\n            for (i=0; i < selectors.length; i++){\n                selector = selectors[i];\n\n                for (j=0; j < selector.parts.length; j++){\n                    part = selector.parts[j];\n                    if (part.type == parser.SELECTOR_PART_TYPE){\n                        if (part.elementName && /h[1-6]/.test(part.elementName.toString()) && j > 0){\n                            reporter.report(\"Heading (\" + part.elementName + \") should not be qualified.\", part.line, part.col, rule);\n                        }\n                    }\n                }\n            }\n        });\n    }\n\n});\n/*\n * Rule: Selectors that look like regular expressions are slow and should be avoided.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"regex-selectors\",\n    name: \"Disallow selectors that look like regexs\",\n    desc: \"Selectors that look like regular expressions are slow and should be avoided.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n\n        parser.addListener(\"startrule\", function(event){\n            var selectors = event.selectors,\n                selector,\n                part,\n                modifier,\n                i, j, k;\n\n            for (i=0; i < selectors.length; i++){\n                selector = selectors[i];\n                for (j=0; j < selector.parts.length; j++){\n                    part = selector.parts[j];\n                    if (part.type == parser.SELECTOR_PART_TYPE){\n                        for (k=0; k < part.modifiers.length; k++){\n                            modifier = part.modifiers[k];\n                            if (modifier.type == \"attribute\"){\n                                if (/([\\~\\|\\^\\$\\*]=)/.test(modifier)){\n                                    reporter.report(\"Attribute selectors with \" + RegExp.$1 + \" are slow!\", modifier.line, modifier.col, rule);\n                                }\n                            }\n\n                        }\n                    }\n                }\n            }\n        });\n    }\n\n});\n/*\n * Rule: Total number of rules should not exceed x.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"rules-count\",\n    name: \"Rules Count\",\n    desc: \"Track how many rules there are.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            count = 0;\n\n        //count each rule\n        parser.addListener(\"startrule\", function(){\n            count++;\n        });\n\n        parser.addListener(\"endstylesheet\", function(){\n            reporter.stat(\"rule-count\", count);\n        });\n    }\n\n});\n/*\n * Rule: Warn people with approaching the IE 4095 limit\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"selector-max-approaching\",\n    name: \"Warn when approaching the 4095 selector limit for IE\",\n    desc: \"Will warn when selector count is >= 3800 selectors.\",\n    browsers: \"IE\",\n\n    //initialization\n    init: function(parser, reporter) {\n        var rule = this, count = 0;\n\n        parser.addListener('startrule', function(event) {\n            count += event.selectors.length;\n        });\n\n        parser.addListener(\"endstylesheet\", function() {\n            if (count >= 3800) {\n                reporter.report(\"You have \" + count + \" selectors. Internet Explorer supports a maximum of 4095 selectors per stylesheet. Consider refactoring.\",0,0,rule);\n            }\n        });\n    }\n\n});\n/*\n * Rule: Warn people past the IE 4095 limit\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"selector-max\",\n    name: \"Error when past the 4095 selector limit for IE\",\n    desc: \"Will error when selector count is > 4095.\",\n    browsers: \"IE\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this, count = 0;\n\n        parser.addListener('startrule',function(event) {\n            count += event.selectors.length;\n        });\n\n        parser.addListener(\"endstylesheet\", function() {\n            if (count > 4095) {\n                reporter.report(\"You have \" + count + \" selectors. Internet Explorer supports a maximum of 4095 selectors per stylesheet. Consider refactoring.\",0,0,rule);\n            }\n        });\n    }\n\n});\n/*\n * Rule: Use shorthand properties where possible.\n *\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"shorthand\",\n    name: \"Require shorthand properties\",\n    desc: \"Use shorthand properties where possible.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            prop, i, len,\n            propertiesToCheck = {},\n            properties,\n            mapping = {\n                \"margin\": [\n                    \"margin-top\",\n                    \"margin-bottom\",\n                    \"margin-left\",\n                    \"margin-right\"\n                ],\n                \"padding\": [\n                    \"padding-top\",\n                    \"padding-bottom\",\n                    \"padding-left\",\n                    \"padding-right\"\n                ]\n            };\n\n        //initialize propertiesToCheck\n        for (prop in mapping){\n            if (mapping.hasOwnProperty(prop)){\n                for (i=0, len=mapping[prop].length; i < len; i++){\n                    propertiesToCheck[mapping[prop][i]] = prop;\n                }\n            }\n        }\n\n        function startRule(event){\n            properties = {};\n        }\n\n        //event handler for end of rules\n        function endRule(event){\n\n            var prop, i, len, total;\n\n            //check which properties this rule has\n            for (prop in mapping){\n                if (mapping.hasOwnProperty(prop)){\n                    total=0;\n\n                    for (i=0, len=mapping[prop].length; i < len; i++){\n                        total += properties[mapping[prop][i]] ? 1 : 0;\n                    }\n\n                    if (total == mapping[prop].length){\n                        reporter.report(\"The properties \" + mapping[prop].join(\", \") + \" can be replaced by \" + prop + \".\", event.line, event.col, rule);\n                    }\n                }\n            }\n        }\n\n        parser.addListener(\"startrule\", startRule);\n        parser.addListener(\"startfontface\", startRule);\n\n        //check for use of \"font-size\"\n        parser.addListener(\"property\", function(event){\n            var name = event.property.toString().toLowerCase(),\n                value = event.value.parts[0].value;\n\n            if (propertiesToCheck[name]){\n                properties[name] = 1;\n            }\n        });\n\n        parser.addListener(\"endrule\", endRule);\n        parser.addListener(\"endfontface\", endRule);\n\n    }\n\n});\n/*\n * Rule: Don't use properties with a star prefix.\n *\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"star-property-hack\",\n    name: \"Disallow properties with a star prefix\",\n    desc: \"Checks for the star property hack (targets IE6/7)\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n\n        //check if property name starts with \"*\"\n        parser.addListener(\"property\", function(event){\n            var property = event.property;\n\n            if (property.hack == \"*\") {\n                reporter.report(\"Property with star prefix found.\", event.property.line, event.property.col, rule);\n            }\n        });\n    }\n});\n/*\n * Rule: Don't use text-indent for image replacement if you need to support rtl.\n *\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"text-indent\",\n    name: \"Disallow negative text-indent\",\n    desc: \"Checks for text indent less than -99px\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            textIndent,\n            direction;\n\n\n        function startRule(event){\n            textIndent = false;\n            direction = \"inherit\";\n        }\n\n        //event handler for end of rules\n        function endRule(event){\n            if (textIndent && direction != \"ltr\"){\n                reporter.report(\"Negative text-indent doesn't work well with RTL. If you use text-indent for image replacement explicitly set direction for that item to ltr.\", textIndent.line, textIndent.col, rule);\n            }\n        }\n\n        parser.addListener(\"startrule\", startRule);\n        parser.addListener(\"startfontface\", startRule);\n\n        //check for use of \"font-size\"\n        parser.addListener(\"property\", function(event){\n            var name = event.property.toString().toLowerCase(),\n                value = event.value;\n\n            if (name == \"text-indent\" && value.parts[0].value < -99){\n                textIndent = event.property;\n            } else if (name == \"direction\" && value == \"ltr\"){\n                direction = \"ltr\";\n            }\n        });\n\n        parser.addListener(\"endrule\", endRule);\n        parser.addListener(\"endfontface\", endRule);\n\n    }\n\n});\n/*\n * Rule: Don't use properties with a underscore prefix.\n *\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"underscore-property-hack\",\n    name: \"Disallow properties with an underscore prefix\",\n    desc: \"Checks for the underscore property hack (targets IE6)\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n\n        //check if property name starts with \"_\"\n        parser.addListener(\"property\", function(event){\n            var property = event.property;\n\n            if (property.hack == \"_\") {\n                reporter.report(\"Property with underscore prefix found.\", event.property.line, event.property.col, rule);\n            }\n        });\n    }\n});\n/*\n * Rule: Headings (h1-h6) should be defined only once.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"unique-headings\",\n    name: \"Headings should only be defined once\",\n    desc: \"Headings should be defined only once.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n\n        var headings =  {\n                h1: 0,\n                h2: 0,\n                h3: 0,\n                h4: 0,\n                h5: 0,\n                h6: 0\n            };\n\n        parser.addListener(\"startrule\", function(event){\n            var selectors = event.selectors,\n                selector,\n                part,\n                pseudo,\n                i, j;\n\n            for (i=0; i < selectors.length; i++){\n                selector = selectors[i];\n                part = selector.parts[selector.parts.length-1];\n\n                if (part.elementName && /(h[1-6])/i.test(part.elementName.toString())){\n\n                    for (j=0; j < part.modifiers.length; j++){\n                        if (part.modifiers[j].type == \"pseudo\"){\n                            pseudo = true;\n                            break;\n                        }\n                    }\n\n                    if (!pseudo){\n                        headings[RegExp.$1]++;\n                        if (headings[RegExp.$1] > 1) {\n                            reporter.report(\"Heading (\" + part.elementName + \") has already been defined.\", part.line, part.col, rule);\n                        }\n                    }\n                }\n            }\n        });\n\n        parser.addListener(\"endstylesheet\", function(event){\n            var prop,\n                messages = [];\n\n            for (prop in headings){\n                if (headings.hasOwnProperty(prop)){\n                    if (headings[prop] > 1){\n                        messages.push(headings[prop] + \" \" + prop + \"s\");\n                    }\n                }\n            }\n\n            if (messages.length){\n                reporter.rollupWarn(\"You have \" + messages.join(\", \") + \" defined in this stylesheet.\", rule);\n            }\n        });\n    }\n\n});\n/*\n * Rule: Don't use universal selector because it's slow.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"universal-selector\",\n    name: \"Disallow universal selector\",\n    desc: \"The universal selector (*) is known to be slow.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n\n        parser.addListener(\"startrule\", function(event){\n            var selectors = event.selectors,\n                selector,\n                part,\n                modifier,\n                i, j, k;\n\n            for (i=0; i < selectors.length; i++){\n                selector = selectors[i];\n\n                part = selector.parts[selector.parts.length-1];\n                if (part.elementName == \"*\"){\n                    reporter.report(rule.desc, part.line, part.col, rule);\n                }\n            }\n        });\n    }\n\n});\n/*\n * Rule: Don't use unqualified attribute selectors because they're just like universal selectors.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"unqualified-attributes\",\n    name: \"Disallow unqualified attribute selectors\",\n    desc: \"Unqualified attribute selectors are known to be slow.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n\n        parser.addListener(\"startrule\", function(event){\n\n            var selectors = event.selectors,\n                selector,\n                part,\n                modifier,\n                i, j, k;\n\n            for (i=0; i < selectors.length; i++){\n                selector = selectors[i];\n\n                part = selector.parts[selector.parts.length-1];\n                if (part.type == parser.SELECTOR_PART_TYPE){\n                    for (k=0; k < part.modifiers.length; k++){\n                        modifier = part.modifiers[k];\n                        if (modifier.type == \"attribute\" && (!part.elementName || part.elementName == \"*\")){\n                            reporter.report(rule.desc, part.line, part.col, rule);\n                        }\n                    }\n                }\n\n            }\n        });\n    }\n\n});\n/*\n * Rule: When using a vendor-prefixed property, make sure to\n * include the standard one.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"vendor-prefix\",\n    name: \"Require standard property with vendor prefix\",\n    desc: \"When using a vendor-prefixed property, make sure to include the standard one.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            properties,\n            num,\n            propertiesToCheck = {\n                \"-webkit-border-radius\": \"border-radius\",\n                \"-webkit-border-top-left-radius\": \"border-top-left-radius\",\n                \"-webkit-border-top-right-radius\": \"border-top-right-radius\",\n                \"-webkit-border-bottom-left-radius\": \"border-bottom-left-radius\",\n                \"-webkit-border-bottom-right-radius\": \"border-bottom-right-radius\",\n\n                \"-o-border-radius\": \"border-radius\",\n                \"-o-border-top-left-radius\": \"border-top-left-radius\",\n                \"-o-border-top-right-radius\": \"border-top-right-radius\",\n                \"-o-border-bottom-left-radius\": \"border-bottom-left-radius\",\n                \"-o-border-bottom-right-radius\": \"border-bottom-right-radius\",\n\n                \"-moz-border-radius\": \"border-radius\",\n                \"-moz-border-radius-topleft\": \"border-top-left-radius\",\n                \"-moz-border-radius-topright\": \"border-top-right-radius\",\n                \"-moz-border-radius-bottomleft\": \"border-bottom-left-radius\",\n                \"-moz-border-radius-bottomright\": \"border-bottom-right-radius\",\n\n                \"-moz-column-count\": \"column-count\",\n                \"-webkit-column-count\": \"column-count\",\n\n                \"-moz-column-gap\": \"column-gap\",\n                \"-webkit-column-gap\": \"column-gap\",\n\n                \"-moz-column-rule\": \"column-rule\",\n                \"-webkit-column-rule\": \"column-rule\",\n\n                \"-moz-column-rule-style\": \"column-rule-style\",\n                \"-webkit-column-rule-style\": \"column-rule-style\",\n\n                \"-moz-column-rule-color\": \"column-rule-color\",\n                \"-webkit-column-rule-color\": \"column-rule-color\",\n\n                \"-moz-column-rule-width\": \"column-rule-width\",\n                \"-webkit-column-rule-width\": \"column-rule-width\",\n\n                \"-moz-column-width\": \"column-width\",\n                \"-webkit-column-width\": \"column-width\",\n\n                \"-webkit-column-span\": \"column-span\",\n                \"-webkit-columns\": \"columns\",\n\n                \"-moz-box-shadow\": \"box-shadow\",\n                \"-webkit-box-shadow\": \"box-shadow\",\n\n                \"-moz-transform\" : \"transform\",\n                \"-webkit-transform\" : \"transform\",\n                \"-o-transform\" : \"transform\",\n                \"-ms-transform\" : \"transform\",\n\n                \"-moz-transform-origin\" : \"transform-origin\",\n                \"-webkit-transform-origin\" : \"transform-origin\",\n                \"-o-transform-origin\" : \"transform-origin\",\n                \"-ms-transform-origin\" : \"transform-origin\",\n\n                \"-moz-box-sizing\" : \"box-sizing\",\n                \"-webkit-box-sizing\" : \"box-sizing\",\n\n                \"-moz-user-select\" : \"user-select\",\n                \"-khtml-user-select\" : \"user-select\",\n                \"-webkit-user-select\" : \"user-select\"\n            };\n\n        //event handler for beginning of rules\n        function startRule(){\n            properties = {};\n            num=1;\n        }\n\n        //event handler for end of rules\n        function endRule(event){\n            var prop,\n                i, len,\n                standard,\n                needed,\n                actual,\n                needsStandard = [];\n\n            for (prop in properties){\n                if (propertiesToCheck[prop]){\n                    needsStandard.push({ actual: prop, needed: propertiesToCheck[prop]});\n                }\n            }\n\n            for (i=0, len=needsStandard.length; i < len; i++){\n                needed = needsStandard[i].needed;\n                actual = needsStandard[i].actual;\n\n                if (!properties[needed]){\n                    reporter.report(\"Missing standard property '\" + needed + \"' to go along with '\" + actual + \"'.\", properties[actual][0].name.line, properties[actual][0].name.col, rule);\n                } else {\n                    //make sure standard property is last\n                    if (properties[needed][0].pos < properties[actual][0].pos){\n                        reporter.report(\"Standard property '\" + needed + \"' should come after vendor-prefixed property '\" + actual + \"'.\", properties[actual][0].name.line, properties[actual][0].name.col, rule);\n                    }\n                }\n            }\n\n        }\n\n        parser.addListener(\"startrule\", startRule);\n        parser.addListener(\"startfontface\", startRule);\n        parser.addListener(\"startpage\", startRule);\n        parser.addListener(\"startpagemargin\", startRule);\n        parser.addListener(\"startkeyframerule\", startRule);\n\n        parser.addListener(\"property\", function(event){\n            var name = event.property.text.toLowerCase();\n\n            if (!properties[name]){\n                properties[name] = [];\n            }\n\n            properties[name].push({ name: event.property, value : event.value, pos:num++ });\n        });\n\n        parser.addListener(\"endrule\", endRule);\n        parser.addListener(\"endfontface\", endRule);\n        parser.addListener(\"endpage\", endRule);\n        parser.addListener(\"endpagemargin\", endRule);\n        parser.addListener(\"endkeyframerule\", endRule);\n    }\n\n});\n/*\n * Rule: You don't need to specify units when a value is 0.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"zero-units\",\n    name: \"Disallow units for 0 values\",\n    desc: \"You don't need to specify units when a value is 0.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n\n        //count how many times \"float\" is used\n        parser.addListener(\"property\", function(event){\n            var parts = event.value.parts,\n                i = 0,\n                len = parts.length;\n\n            while(i < len){\n                if ((parts[i].units || parts[i].type == \"percentage\") && parts[i].value === 0 && parts[i].type != \"time\"){\n                    reporter.report(\"Values of 0 shouldn't have units specified.\", parts[i].line, parts[i].col, rule);\n                }\n                i++;\n            }\n\n        });\n\n    }\n\n});\n/*global CSSLint*/\n(function() {\n\n    /**\n     * Replace special characters before write to output.\n     *\n     * Rules:\n     *  - single quotes is the escape sequence for double-quotes\n     *  - &amp; is the escape sequence for &\n     *  - &lt; is the escape sequence for <\n     *  - &gt; is the escape sequence for >\n     *\n     * @param {String} message to escape\n     * @return escaped message as {String}\n     */\n    var xmlEscape = function(str) {\n        if (!str || str.constructor !== String) {\n            return \"\";\n        }\n\n        return str.replace(/[\\\"&><]/g, function(match) {\n            switch (match) {\n                case \"\\\"\":\n                    return \"&quot;\";\n                case \"&\":\n                    return \"&amp;\";\n                case \"<\":\n                    return \"&lt;\";\n                case \">\":\n                    return \"&gt;\";\n            }\n        });\n    };\n\n    CSSLint.addFormatter({\n        //format information\n        id: \"checkstyle-xml\",\n        name: \"Checkstyle XML format\",\n\n        /**\n         * Return opening root XML tag.\n         * @return {String} to prepend before all results\n         */\n        startFormat: function(){\n            return \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?><checkstyle>\";\n        },\n\n        /**\n         * Return closing root XML tag.\n         * @return {String} to append after all results\n         */\n        endFormat: function(){\n            return \"</checkstyle>\";\n        },\n\n        /**\n         * Returns message when there is a file read error.\n         * @param {String} filename The name of the file that caused the error.\n         * @param {String} message The error message\n         * @return {String} The error message.\n         */\n        readError: function(filename, message) {\n            return \"<file name=\\\"\" + xmlEscape(filename) + \"\\\"><error line=\\\"0\\\" column=\\\"0\\\" severty=\\\"error\\\" message=\\\"\" + xmlEscape(message) + \"\\\"></error></file>\";\n        },\n\n        /**\n         * Given CSS Lint results for a file, return output for this format.\n         * @param results {Object} with error and warning messages\n         * @param filename {String} relative file path\n         * @param options {Object} (UNUSED for now) specifies special handling of output\n         * @return {String} output for results\n         */\n        formatResults: function(results, filename, options) {\n            var messages = results.messages,\n                output = [];\n\n            /**\n             * Generate a source string for a rule.\n             * Checkstyle source strings usually resemble Java class names e.g\n             * net.csslint.SomeRuleName\n             * @param {Object} rule\n             * @return rule source as {String}\n             */\n            var generateSource = function(rule) {\n                if (!rule || !('name' in rule)) {\n                    return \"\";\n                }\n                return 'net.csslint.' + rule.name.replace(/\\s/g,'');\n            };\n\n\n\n            if (messages.length > 0) {\n                output.push(\"<file name=\\\"\"+filename+\"\\\">\");\n                CSSLint.Util.forEach(messages, function (message, i) {\n                    //ignore rollups for now\n                    if (!message.rollup) {\n                      output.push(\"<error line=\\\"\" + message.line + \"\\\" column=\\\"\" + message.col + \"\\\" severity=\\\"\" + message.type + \"\\\"\" +\n                          \" message=\\\"\" + xmlEscape(message.message) + \"\\\" source=\\\"\" + generateSource(message.rule) +\"\\\"/>\");\n                    }\n                });\n                output.push(\"</file>\");\n            }\n\n            return output.join(\"\");\n        }\n    });\n\n}());\n/*global CSSLint*/\nCSSLint.addFormatter({\n    //format information\n    id: \"compact\",\n    name: \"Compact, 'porcelain' format\",\n\n    /**\n     * Return content to be printed before all file results.\n     * @return {String} to prepend before all results\n     */\n    startFormat: function() {\n        return \"\";\n    },\n\n    /**\n     * Return content to be printed after all file results.\n     * @return {String} to append after all results\n     */\n    endFormat: function() {\n        return \"\";\n    },\n\n    /**\n     * Given CSS Lint results for a file, return output for this format.\n     * @param results {Object} with error and warning messages\n     * @param filename {String} relative file path\n     * @param options {Object} (Optional) specifies special handling of output\n     * @return {String} output for results\n     */\n    formatResults: function(results, filename, options) {\n        var messages = results.messages,\n            output = \"\";\n        options = options || {};\n\n        /**\n         * Capitalize and return given string.\n         * @param str {String} to capitalize\n         * @return {String} capitalized\n         */\n        var capitalize = function(str) {\n            return str.charAt(0).toUpperCase() + str.slice(1);\n        };\n\n        if (messages.length === 0) {\n            return options.quiet ? \"\" : filename + \": Lint Free!\";\n        }\n\n        CSSLint.Util.forEach(messages, function(message, i) {\n            if (message.rollup) {\n                output += filename + \": \" + capitalize(message.type) + \" - \" + message.message + \"\\n\";\n            } else {\n                output += filename + \": \" + \"line \" + message.line +\n                    \", col \" + message.col + \", \" + capitalize(message.type) + \" - \" + message.message + \"\\n\";\n            }\n        });\n\n        return output;\n    }\n});\n/*global CSSLint*/\nCSSLint.addFormatter({\n    //format information\n    id: \"csslint-xml\",\n    name: \"CSSLint XML format\",\n\n    /**\n     * Return opening root XML tag.\n     * @return {String} to prepend before all results\n     */\n    startFormat: function(){\n        return \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?><csslint>\";\n    },\n\n    /**\n     * Return closing root XML tag.\n     * @return {String} to append after all results\n     */\n    endFormat: function(){\n        return \"</csslint>\";\n    },\n\n    /**\n     * Given CSS Lint results for a file, return output for this format.\n     * @param results {Object} with error and warning messages\n     * @param filename {String} relative file path\n     * @param options {Object} (UNUSED for now) specifies special handling of output\n     * @return {String} output for results\n     */\n    formatResults: function(results, filename, options) {\n        var messages = results.messages,\n            output = [];\n\n        /**\n         * Replace special characters before write to output.\n         *\n         * Rules:\n         *  - single quotes is the escape sequence for double-quotes\n         *  - &amp; is the escape sequence for &\n         *  - &lt; is the escape sequence for <\n         *  - &gt; is the escape sequence for >\n         *\n         * @param {String} message to escape\n         * @return escaped message as {String}\n         */\n        var escapeSpecialCharacters = function(str) {\n            if (!str || str.constructor !== String) {\n                return \"\";\n            }\n            return str.replace(/\\\"/g, \"'\").replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n        };\n\n        if (messages.length > 0) {\n            output.push(\"<file name=\\\"\"+filename+\"\\\">\");\n            CSSLint.Util.forEach(messages, function (message, i) {\n                if (message.rollup) {\n                    output.push(\"<issue severity=\\\"\" + message.type + \"\\\" reason=\\\"\" + escapeSpecialCharacters(message.message) + \"\\\" evidence=\\\"\" + escapeSpecialCharacters(message.evidence) + \"\\\"/>\");\n                } else {\n                    output.push(\"<issue line=\\\"\" + message.line + \"\\\" char=\\\"\" + message.col + \"\\\" severity=\\\"\" + message.type + \"\\\"\" +\n                        \" reason=\\\"\" + escapeSpecialCharacters(message.message) + \"\\\" evidence=\\\"\" + escapeSpecialCharacters(message.evidence) + \"\\\"/>\");\n                }\n            });\n            output.push(\"</file>\");\n        }\n\n        return output.join(\"\");\n    }\n});\n/*global CSSLint*/\nCSSLint.addFormatter({\n    //format information\n    id: \"junit-xml\",\n    name: \"JUNIT XML format\",\n\n    /**\n     * Return opening root XML tag.\n     * @return {String} to prepend before all results\n     */\n    startFormat: function(){\n        return \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?><testsuites>\";\n    },\n\n    /**\n     * Return closing root XML tag.\n     * @return {String} to append after all results\n     */\n    endFormat: function() {\n        return \"</testsuites>\";\n    },\n\n    /**\n     * Given CSS Lint results for a file, return output for this format.\n     * @param results {Object} with error and warning messages\n     * @param filename {String} relative file path\n     * @param options {Object} (UNUSED for now) specifies special handling of output\n     * @return {String} output for results\n     */\n    formatResults: function(results, filename, options) {\n\n        var messages = results.messages,\n            output = [],\n            tests = {\n                'error': 0,\n                'failure': 0\n            };\n\n        /**\n         * Generate a source string for a rule.\n         * JUNIT source strings usually resemble Java class names e.g\n         * net.csslint.SomeRuleName\n         * @param {Object} rule\n         * @return rule source as {String}\n         */\n        var generateSource = function(rule) {\n            if (!rule || !('name' in rule)) {\n                return \"\";\n            }\n            return 'net.csslint.' + rule.name.replace(/\\s/g,'');\n        };\n\n        /**\n         * Replace special characters before write to output.\n         *\n         * Rules:\n         *  - single quotes is the escape sequence for double-quotes\n         *  - &lt; is the escape sequence for <\n         *  - &gt; is the escape sequence for >\n         *\n         * @param {String} message to escape\n         * @return escaped message as {String}\n         */\n        var escapeSpecialCharacters = function(str) {\n\n            if (!str || str.constructor !== String) {\n                return \"\";\n            }\n\n            return str.replace(/\\\"/g, \"'\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n\n        };\n\n        if (messages.length > 0) {\n\n            messages.forEach(function (message, i) {\n\n                // since junit has no warning class\n                // all issues as errors\n                var type = message.type === 'warning' ? 'error' : message.type;\n\n                //ignore rollups for now\n                if (!message.rollup) {\n\n                    // build the test case seperately, once joined\n                    // we'll add it to a custom array filtered by type\n                    output.push(\"<testcase time=\\\"0\\\" name=\\\"\" + generateSource(message.rule) + \"\\\">\");\n                    output.push(\"<\" + type + \" message=\\\"\" + escapeSpecialCharacters(message.message) + \"\\\"><![CDATA[\" + message.line + ':' + message.col + ':' + escapeSpecialCharacters(message.evidence)  + \"]]></\" + type + \">\");\n                    output.push(\"</testcase>\");\n\n                    tests[type] += 1;\n\n                }\n\n            });\n\n            output.unshift(\"<testsuite time=\\\"0\\\" tests=\\\"\" + messages.length + \"\\\" skipped=\\\"0\\\" errors=\\\"\" + tests.error + \"\\\" failures=\\\"\" + tests.failure + \"\\\" package=\\\"net.csslint\\\" name=\\\"\" + filename + \"\\\">\");\n            output.push(\"</testsuite>\");\n\n        }\n\n        return output.join(\"\");\n\n    }\n});\n/*global CSSLint*/\nCSSLint.addFormatter({\n    //format information\n    id: \"lint-xml\",\n    name: \"Lint XML format\",\n\n    /**\n     * Return opening root XML tag.\n     * @return {String} to prepend before all results\n     */\n    startFormat: function(){\n        return \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?><lint>\";\n    },\n\n    /**\n     * Return closing root XML tag.\n     * @return {String} to append after all results\n     */\n    endFormat: function(){\n        return \"</lint>\";\n    },\n\n    /**\n     * Given CSS Lint results for a file, return output for this format.\n     * @param results {Object} with error and warning messages\n     * @param filename {String} relative file path\n     * @param options {Object} (UNUSED for now) specifies special handling of output\n     * @return {String} output for results\n     */\n    formatResults: function(results, filename, options) {\n        var messages = results.messages,\n            output = [];\n\n        /**\n         * Replace special characters before write to output.\n         *\n         * Rules:\n         *  - single quotes is the escape sequence for double-quotes\n         *  - &amp; is the escape sequence for &\n         *  - &lt; is the escape sequence for <\n         *  - &gt; is the escape sequence for >\n         *\n         * @param {String} message to escape\n         * @return escaped message as {String}\n         */\n        var escapeSpecialCharacters = function(str) {\n            if (!str || str.constructor !== String) {\n                return \"\";\n            }\n            return str.replace(/\\\"/g, \"'\").replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n        };\n\n        if (messages.length > 0) {\n\n            output.push(\"<file name=\\\"\"+filename+\"\\\">\");\n            CSSLint.Util.forEach(messages, function (message, i) {\n                if (message.rollup) {\n                    output.push(\"<issue severity=\\\"\" + message.type + \"\\\" reason=\\\"\" + escapeSpecialCharacters(message.message) + \"\\\" evidence=\\\"\" + escapeSpecialCharacters(message.evidence) + \"\\\"/>\");\n                } else {\n                    output.push(\"<issue line=\\\"\" + message.line + \"\\\" char=\\\"\" + message.col + \"\\\" severity=\\\"\" + message.type + \"\\\"\" +\n                        \" reason=\\\"\" + escapeSpecialCharacters(message.message) + \"\\\" evidence=\\\"\" + escapeSpecialCharacters(message.evidence) + \"\\\"/>\");\n                }\n            });\n            output.push(\"</file>\");\n        }\n\n        return output.join(\"\");\n    }\n});\n/*global CSSLint*/\nCSSLint.addFormatter({\n    //format information\n    id: \"text\",\n    name: \"Plain Text\",\n\n    /**\n     * Return content to be printed before all file results.\n     * @return {String} to prepend before all results\n     */\n    startFormat: function() {\n        return \"\";\n    },\n\n    /**\n     * Return content to be printed after all file results.\n     * @return {String} to append after all results\n     */\n    endFormat: function() {\n        return \"\";\n    },\n\n    /**\n     * Given CSS Lint results for a file, return output for this format.\n     * @param results {Object} with error and warning messages\n     * @param filename {String} relative file path\n     * @param options {Object} (Optional) specifies special handling of output\n     * @return {String} output for results\n     */\n    formatResults: function(results, filename, options) {\n        var messages = results.messages,\n            output = \"\";\n        options = options || {};\n\n        if (messages.length === 0) {\n            return options.quiet ? \"\" : \"\\n\\ncsslint: No errors in \" + filename + \".\";\n        }\n\n        output = \"\\n\\ncsslint: There are \" + messages.length  +  \" problems in \" + filename + \".\";\n        var pos = filename.lastIndexOf(\"/\"),\n            shortFilename = filename;\n\n        if (pos === -1){\n            pos = filename.lastIndexOf(\"\\\\\");\n        }\n        if (pos > -1){\n            shortFilename = filename.substring(pos+1);\n        }\n\n        CSSLint.Util.forEach(messages, function (message, i) {\n            output = output + \"\\n\\n\" + shortFilename;\n            if (message.rollup) {\n                output += \"\\n\" + (i+1) + \": \" + message.type;\n                output += \"\\n\" + message.message;\n            } else {\n                output += \"\\n\" + (i+1) + \": \" + message.type + \" at line \" + message.line + \", col \" + message.col;\n                output += \"\\n\" + message.message;\n                output += \"\\n\" + message.evidence;\n            }\n        });\n\n        return output;\n    }\n});\n\nexports.CSSLint = CSSLint;\n"
  },
  {
    "path": "sublimelinter/modules/libs/csslint/linter.js",
    "content": "/*jslint node: true, sloppy: true */\n/*globals LINTER_PATH, load */\n\nvar CSSLint = require(\"./csslint-node\").CSSLint;\n\nexports.lint = function (code, config) {\n    var results = [];\n\n    var ruleset = {};\n\n    // rules that are `false` will be ignored.\n    for (var ruleName in config) {\n\n        if (config[ruleName] === 'warning') {\n            ruleset[ruleName] = 1;\n        // Rules set to `true` or 'error' will be considered errors\n        } else if (config[ruleName]) {\n            ruleset[ruleName] = 2;\n        }\n\n    }\n\n    var report = CSSLint.verify(code, ruleset);\n\n    report.messages.forEach(function (message) {\n        if (message) {\n\n            // message.type // warning|error\n            // message.line\n            // message.col\n            // message.message\n            // message.evidence // Requires sanitizing as it can include CR, LF\n            // message.rule // The rule object\n\n            // We don't pass on the rollup messages\n            if (message.rollup !== true) {\n                results.push({\n                    'line': message.line,\n                    'character': message.col,\n                    'type': message.type,\n                    'reason': message.message\n                });\n            }\n        }\n    });\n\n    return results;\n};\n"
  },
  {
    "path": "sublimelinter/modules/libs/jsengines/jsc.js",
    "content": "/*jshint boss: true, evil: true */\n/*globals load quit readline lint JSHINT */\n\n// usage:\n//   jsc ${envHome}/jsc.js -- /path/to/linter/ ${lineCount} {option1:true,option2:false}\n\nvar USING_JSC = true,\n    LINTER_PATH = arguments[0].replace(/\\/$/, '') + '/';\n\nvar require = function (file) {\n        load(LINTER_PATH + file.replace(/\\.js$/, '') + '.js');\n        return this;\n    },\n    exports = {};\n\nrequire('linter');\n\nif (typeof exports.lint === 'undefined') {\n    print('JSC: Could not load linter.js.');\n    quit();\n}\n\nvar process = function (args) {\n    var opts,\n        lineCount = parseInt(args[1], 10);\n\n    if (isNaN(lineCount)) {\n        print('JSC: Must provide number of lines to read from stdin.');\n        quit();\n    }\n\n    try {\n        opts = JSON.parse(args[2]);\n    } catch (e) {\n    } finally {\n        if (!opts) opts = {};\n    }\n\n    var code = readline();\n\n    for (var i = 0; i < lineCount; ++i) {\n        code += '\\n' + readline();\n    }\n\n    var results = exports.lint(code, opts);\n\n    print(JSON.stringify(results));\n    quit();\n};\n\nprocess(arguments);\n"
  },
  {
    "path": "sublimelinter/modules/libs/jsengines/node.js",
    "content": "/*jshint node:true */\n\n/*\n    usage: node /path/to/node.js /path/to/linter/ [\"{option1:true,option2:false}\"]\n    */\n\nvar _fs = require('fs'),\n    _path = require('path'),\n    linterPath = process.argv[2].replace(/\\/$/, '') + '/',\n    _linter = require(linterPath + 'linter');\n\nfunction run() {\n    var code = '',\n        results,\n        config = JSON.parse(process.argv[3] || '{}'),\n        filename = process.argv[4] || '';\n\n    if (filename) {\n        results = _linter.lint(_fs.readFileSync(filename, 'utf-8'), config, linterPath);\n        console.log(JSON.stringify(results));\n    } else {\n        process.stdin.resume();\n        process.stdin.setEncoding('utf8');\n\n        process.stdin.on('data', function (chunk) {\n            code += chunk;\n        });\n\n        process.stdin.on('end', function () {\n            results = _linter.lint(code, config, linterPath);\n            console.log(JSON.stringify(results));\n        });\n    }\n}\n\nrun();\n"
  },
  {
    "path": "sublimelinter/modules/libs/jshint/jshint.js",
    "content": "var window = {};//2.1.8\nvar JSHINT;\n(function () {\nvar require;\nrequire=(function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require==\"function\"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error(\"Cannot find module '\"+n+\"'\")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require==\"function\"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({1:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\n\nprocess.nextTick = (function () {\n    var canSetImmediate = typeof window !== 'undefined'\n    && window.setImmediate;\n    var canPost = typeof window !== 'undefined'\n    && window.postMessage && window.addEventListener\n    ;\n\n    if (canSetImmediate) {\n        return function (f) { return window.setImmediate(f) };\n    }\n\n    if (canPost) {\n        var queue = [];\n        window.addEventListener('message', function (ev) {\n            if (ev.source === window && ev.data === 'process-tick') {\n                ev.stopPropagation();\n                if (queue.length > 0) {\n                    var fn = queue.shift();\n                    fn();\n                }\n            }\n        }, true);\n\n        return function nextTick(fn) {\n            queue.push(fn);\n            window.postMessage('process-tick', '*');\n        };\n    }\n\n    return function nextTick(fn) {\n        setTimeout(fn, 0);\n    };\n})();\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n}\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\n\n},{}],2:[function(require,module,exports){\n(function(process){if (!process.EventEmitter) process.EventEmitter = function () {};\n\nvar EventEmitter = exports.EventEmitter = process.EventEmitter;\nvar isArray = typeof Array.isArray === 'function'\n    ? Array.isArray\n    : function (xs) {\n        return Object.prototype.toString.call(xs) === '[object Array]'\n    }\n;\nfunction indexOf (xs, x) {\n    if (xs.indexOf) return xs.indexOf(x);\n    for (var i = 0; i < xs.length; i++) {\n        if (x === xs[i]) return i;\n    }\n    return -1;\n}\n\n// By default EventEmitters will print a warning if more than\n// 10 listeners are added to it. This is a useful default which\n// helps finding memory leaks.\n//\n// Obviously not all Emitters should be limited to 10. This function allows\n// that to be increased. Set to zero for unlimited.\nvar defaultMaxListeners = 10;\nEventEmitter.prototype.setMaxListeners = function(n) {\n  if (!this._events) this._events = {};\n  this._events.maxListeners = n;\n};\n\n\nEventEmitter.prototype.emit = function(type) {\n  // If there is no 'error' event listener then throw.\n  if (type === 'error') {\n    if (!this._events || !this._events.error ||\n        (isArray(this._events.error) && !this._events.error.length))\n    {\n      if (arguments[1] instanceof Error) {\n        throw arguments[1]; // Unhandled 'error' event\n      } else {\n        throw new Error(\"Uncaught, unspecified 'error' event.\");\n      }\n      return false;\n    }\n  }\n\n  if (!this._events) return false;\n  var handler = this._events[type];\n  if (!handler) return false;\n\n  if (typeof handler == 'function') {\n    switch (arguments.length) {\n      // fast cases\n      case 1:\n        handler.call(this);\n        break;\n      case 2:\n        handler.call(this, arguments[1]);\n        break;\n      case 3:\n        handler.call(this, arguments[1], arguments[2]);\n        break;\n      // slower\n      default:\n        var args = Array.prototype.slice.call(arguments, 1);\n        handler.apply(this, args);\n    }\n    return true;\n\n  } else if (isArray(handler)) {\n    var args = Array.prototype.slice.call(arguments, 1);\n\n    var listeners = handler.slice();\n    for (var i = 0, l = listeners.length; i < l; i++) {\n      listeners[i].apply(this, args);\n    }\n    return true;\n\n  } else {\n    return false;\n  }\n};\n\n// EventEmitter is defined in src/node_events.cc\n// EventEmitter.prototype.emit() is also defined there.\nEventEmitter.prototype.addListener = function(type, listener) {\n  if ('function' !== typeof listener) {\n    throw new Error('addListener only takes instances of Function');\n  }\n\n  if (!this._events) this._events = {};\n\n  // To avoid recursion in the case that type == \"newListeners\"! Before\n  // adding it to the listeners, first emit \"newListeners\".\n  this.emit('newListener', type, listener);\n\n  if (!this._events[type]) {\n    // Optimize the case of one listener. Don't need the extra array object.\n    this._events[type] = listener;\n  } else if (isArray(this._events[type])) {\n\n    // Check for listener leak\n    if (!this._events[type].warned) {\n      var m;\n      if (this._events.maxListeners !== undefined) {\n        m = this._events.maxListeners;\n      } else {\n        m = defaultMaxListeners;\n      }\n\n      if (m && m > 0 && this._events[type].length > m) {\n        this._events[type].warned = true;\n        console.error('(node) warning: possible EventEmitter memory ' +\n                      'leak detected. %d listeners added. ' +\n                      'Use emitter.setMaxListeners() to increase limit.',\n                      this._events[type].length);\n        console.trace();\n      }\n    }\n\n    // If we've already got an array, just append.\n    this._events[type].push(listener);\n  } else {\n    // Adding the second element, need to change to array.\n    this._events[type] = [this._events[type], listener];\n  }\n\n  return this;\n};\n\nEventEmitter.prototype.on = EventEmitter.prototype.addListener;\n\nEventEmitter.prototype.once = function(type, listener) {\n  var self = this;\n  self.on(type, function g() {\n    self.removeListener(type, g);\n    listener.apply(this, arguments);\n  });\n\n  return this;\n};\n\nEventEmitter.prototype.removeListener = function(type, listener) {\n  if ('function' !== typeof listener) {\n    throw new Error('removeListener only takes instances of Function');\n  }\n\n  // does not use listeners(), so no side effect of creating _events[type]\n  if (!this._events || !this._events[type]) return this;\n\n  var list = this._events[type];\n\n  if (isArray(list)) {\n    var i = indexOf(list, listener);\n    if (i < 0) return this;\n    list.splice(i, 1);\n    if (list.length == 0)\n      delete this._events[type];\n  } else if (this._events[type] === listener) {\n    delete this._events[type];\n  }\n\n  return this;\n};\n\nEventEmitter.prototype.removeAllListeners = function(type) {\n  if (arguments.length === 0) {\n    this._events = {};\n    return this;\n  }\n\n  // does not use listeners(), so no side effect of creating _events[type]\n  if (type && this._events && this._events[type]) this._events[type] = null;\n  return this;\n};\n\nEventEmitter.prototype.listeners = function(type) {\n  if (!this._events) this._events = {};\n  if (!this._events[type]) this._events[type] = [];\n  if (!isArray(this._events[type])) {\n    this._events[type] = [this._events[type]];\n  }\n  return this._events[type];\n};\n\n})(require(\"__browserify_process\"))\n},{\"__browserify_process\":1}],3:[function(require,module,exports){\n(function(){// jshint -W001\n\n\"use strict\";\n\n// Identifiers provided by the ECMAScript standard.\n\nexports.reservedVars = {\n    arguments : false,\n    NaN       : false\n};\n\nexports.ecmaIdentifiers = {\n    Array              : false,\n    Boolean            : false,\n    Date               : false,\n    decodeURI          : false,\n    decodeURIComponent : false,\n    encodeURI          : false,\n    encodeURIComponent : false,\n    Error              : false,\n    \"eval\"             : false,\n    EvalError          : false,\n    Function           : false,\n    hasOwnProperty     : false,\n    isFinite           : false,\n    isNaN              : false,\n    JSON               : false,\n    Math               : false,\n    Map                : false,\n    Number             : false,\n    Object             : false,\n    parseInt           : false,\n    parseFloat         : false,\n    RangeError         : false,\n    ReferenceError     : false,\n    RegExp             : false,\n    Set                : false,\n    String             : false,\n    SyntaxError        : false,\n    TypeError          : false,\n    URIError           : false,\n    WeakMap            : false\n};\n\n// Global variables commonly provided by a web browser environment.\n\nexports.browser = {\n    ArrayBuffer          : false,\n    ArrayBufferView      : false,\n    Audio                : false,\n    Blob                 : false,\n    addEventListener     : false,\n    applicationCache     : false,\n    atob                 : false,\n    blur                 : false,\n    btoa                 : false,\n    clearInterval        : false,\n    clearTimeout         : false,\n    close                : false,\n    closed               : false,\n    CustomEvent          : false,\n    DataView             : false,\n    DOMParser            : false,\n    defaultStatus        : false,\n    document             : false,\n    Element              : false,\n    ElementTimeControl   : false,\n    event                : false,\n    FileReader           : false,\n    Float32Array         : false,\n    Float64Array         : false,\n    FormData             : false,\n    focus                : false,\n    frames               : false,\n    getComputedStyle     : false,\n    HTMLElement          : false,\n    HTMLAnchorElement    : false,\n    HTMLBaseElement      : false,\n    HTMLBlockquoteElement: false,\n    HTMLBodyElement      : false,\n    HTMLBRElement        : false,\n    HTMLButtonElement    : false,\n    HTMLCanvasElement    : false,\n    HTMLDirectoryElement : false,\n    HTMLDivElement       : false,\n    HTMLDListElement     : false,\n    HTMLFieldSetElement  : false,\n    HTMLFontElement      : false,\n    HTMLFormElement      : false,\n    HTMLFrameElement     : false,\n    HTMLFrameSetElement  : false,\n    HTMLHeadElement      : false,\n    HTMLHeadingElement   : false,\n    HTMLHRElement        : false,\n    HTMLHtmlElement      : false,\n    HTMLIFrameElement    : false,\n    HTMLImageElement     : false,\n    HTMLInputElement     : false,\n    HTMLIsIndexElement   : false,\n    HTMLLabelElement     : false,\n    HTMLLayerElement     : false,\n    HTMLLegendElement    : false,\n    HTMLLIElement        : false,\n    HTMLLinkElement      : false,\n    HTMLMapElement       : false,\n    HTMLMenuElement      : false,\n    HTMLMetaElement      : false,\n    HTMLModElement       : false,\n    HTMLObjectElement    : false,\n    HTMLOListElement     : false,\n    HTMLOptGroupElement  : false,\n    HTMLOptionElement    : false,\n    HTMLParagraphElement : false,\n    HTMLParamElement     : false,\n    HTMLPreElement       : false,\n    HTMLQuoteElement     : false,\n    HTMLScriptElement    : false,\n    HTMLSelectElement    : false,\n    HTMLStyleElement     : false,\n    HTMLTableCaptionElement: false,\n    HTMLTableCellElement : false,\n    HTMLTableColElement  : false,\n    HTMLTableElement     : false,\n    HTMLTableRowElement  : false,\n    HTMLTableSectionElement: false,\n    HTMLTextAreaElement  : false,\n    HTMLTitleElement     : false,\n    HTMLUListElement     : false,\n    HTMLVideoElement     : false,\n    history              : false,\n    Int16Array           : false,\n    Int32Array           : false,\n    Int8Array            : false,\n    Image                : false,\n    length               : false,\n    localStorage         : false,\n    location             : false,\n    MessageChannel       : false,\n    MessageEvent         : false,\n    MessagePort          : false,\n    MouseEvent           : false,\n    moveBy               : false,\n    moveTo               : false,\n    MutationObserver     : false,\n    name                 : false,\n    Node                 : false,\n    NodeFilter           : false,\n    navigator            : false,\n    onbeforeunload       : true,\n    onblur               : true,\n    onerror              : true,\n    onfocus              : true,\n    onload               : true,\n    onresize             : true,\n    onunload             : true,\n    open                 : false,\n    openDatabase         : false,\n    opener               : false,\n    Option               : false,\n    parent               : false,\n    print                : false,\n    removeEventListener  : false,\n    resizeBy             : false,\n    resizeTo             : false,\n    screen               : false,\n    scroll               : false,\n    scrollBy             : false,\n    scrollTo             : false,\n    sessionStorage       : false,\n    setInterval          : false,\n    setTimeout           : false,\n    SharedWorker         : false,\n    status               : false,\n    SVGAElement          : false,\n    SVGAltGlyphDefElement: false,\n    SVGAltGlyphElement   : false,\n    SVGAltGlyphItemElement: false,\n    SVGAngle             : false,\n    SVGAnimateColorElement: false,\n    SVGAnimateElement    : false,\n    SVGAnimateMotionElement: false,\n    SVGAnimateTransformElement: false,\n    SVGAnimatedAngle     : false,\n    SVGAnimatedBoolean   : false,\n    SVGAnimatedEnumeration: false,\n    SVGAnimatedInteger   : false,\n    SVGAnimatedLength    : false,\n    SVGAnimatedLengthList: false,\n    SVGAnimatedNumber    : false,\n    SVGAnimatedNumberList: false,\n    SVGAnimatedPathData  : false,\n    SVGAnimatedPoints    : false,\n    SVGAnimatedPreserveAspectRatio: false,\n    SVGAnimatedRect      : false,\n    SVGAnimatedString    : false,\n    SVGAnimatedTransformList: false,\n    SVGAnimationElement  : false,\n    SVGCSSRule           : false,\n    SVGCircleElement     : false,\n    SVGClipPathElement   : false,\n    SVGColor             : false,\n    SVGColorProfileElement: false,\n    SVGColorProfileRule  : false,\n    SVGComponentTransferFunctionElement: false,\n    SVGCursorElement     : false,\n    SVGDefsElement       : false,\n    SVGDescElement       : false,\n    SVGDocument          : false,\n    SVGElement           : false,\n    SVGElementInstance   : false,\n    SVGElementInstanceList: false,\n    SVGEllipseElement    : false,\n    SVGExternalResourcesRequired: false,\n    SVGFEBlendElement    : false,\n    SVGFEColorMatrixElement: false,\n    SVGFEComponentTransferElement: false,\n    SVGFECompositeElement: false,\n    SVGFEConvolveMatrixElement: false,\n    SVGFEDiffuseLightingElement: false,\n    SVGFEDisplacementMapElement: false,\n    SVGFEDistantLightElement: false,\n    SVGFEFloodElement    : false,\n    SVGFEFuncAElement    : false,\n    SVGFEFuncBElement    : false,\n    SVGFEFuncGElement    : false,\n    SVGFEFuncRElement    : false,\n    SVGFEGaussianBlurElement: false,\n    SVGFEImageElement    : false,\n    SVGFEMergeElement    : false,\n    SVGFEMergeNodeElement: false,\n    SVGFEMorphologyElement: false,\n    SVGFEOffsetElement   : false,\n    SVGFEPointLightElement: false,\n    SVGFESpecularLightingElement: false,\n    SVGFESpotLightElement: false,\n    SVGFETileElement     : false,\n    SVGFETurbulenceElement: false,\n    SVGFilterElement     : false,\n    SVGFilterPrimitiveStandardAttributes: false,\n    SVGFitToViewBox      : false,\n    SVGFontElement       : false,\n    SVGFontFaceElement   : false,\n    SVGFontFaceFormatElement: false,\n    SVGFontFaceNameElement: false,\n    SVGFontFaceSrcElement: false,\n    SVGFontFaceUriElement: false,\n    SVGForeignObjectElement: false,\n    SVGGElement          : false,\n    SVGGlyphElement      : false,\n    SVGGlyphRefElement   : false,\n    SVGGradientElement   : false,\n    SVGHKernElement      : false,\n    SVGICCColor          : false,\n    SVGImageElement      : false,\n    SVGLangSpace         : false,\n    SVGLength            : false,\n    SVGLengthList        : false,\n    SVGLineElement       : false,\n    SVGLinearGradientElement: false,\n    SVGLocatable         : false,\n    SVGMPathElement      : false,\n    SVGMarkerElement     : false,\n    SVGMaskElement       : false,\n    SVGMatrix            : false,\n    SVGMetadataElement   : false,\n    SVGMissingGlyphElement: false,\n    SVGNumber            : false,\n    SVGNumberList        : false,\n    SVGPaint             : false,\n    SVGPathElement       : false,\n    SVGPathSeg           : false,\n    SVGPathSegArcAbs     : false,\n    SVGPathSegArcRel     : false,\n    SVGPathSegClosePath  : false,\n    SVGPathSegCurvetoCubicAbs: false,\n    SVGPathSegCurvetoCubicRel: false,\n    SVGPathSegCurvetoCubicSmoothAbs: false,\n    SVGPathSegCurvetoCubicSmoothRel: false,\n    SVGPathSegCurvetoQuadraticAbs: false,\n    SVGPathSegCurvetoQuadraticRel: false,\n    SVGPathSegCurvetoQuadraticSmoothAbs: false,\n    SVGPathSegCurvetoQuadraticSmoothRel: false,\n    SVGPathSegLinetoAbs  : false,\n    SVGPathSegLinetoHorizontalAbs: false,\n    SVGPathSegLinetoHorizontalRel: false,\n    SVGPathSegLinetoRel  : false,\n    SVGPathSegLinetoVerticalAbs: false,\n    SVGPathSegLinetoVerticalRel: false,\n    SVGPathSegList       : false,\n    SVGPathSegMovetoAbs  : false,\n    SVGPathSegMovetoRel  : false,\n    SVGPatternElement    : false,\n    SVGPoint             : false,\n    SVGPointList         : false,\n    SVGPolygonElement    : false,\n    SVGPolylineElement   : false,\n    SVGPreserveAspectRatio: false,\n    SVGRadialGradientElement: false,\n    SVGRect              : false,\n    SVGRectElement       : false,\n    SVGRenderingIntent   : false,\n    SVGSVGElement        : false,\n    SVGScriptElement     : false,\n    SVGSetElement        : false,\n    SVGStopElement       : false,\n    SVGStringList        : false,\n    SVGStylable          : false,\n    SVGStyleElement      : false,\n    SVGSwitchElement     : false,\n    SVGSymbolElement     : false,\n    SVGTRefElement       : false,\n    SVGTSpanElement      : false,\n    SVGTests             : false,\n    SVGTextContentElement: false,\n    SVGTextElement       : false,\n    SVGTextPathElement   : false,\n    SVGTextPositioningElement: false,\n    SVGTitleElement      : false,\n    SVGTransform         : false,\n    SVGTransformList     : false,\n    SVGTransformable     : false,\n    SVGURIReference      : false,\n    SVGUnitTypes         : false,\n    SVGUseElement        : false,\n    SVGVKernElement      : false,\n    SVGViewElement       : false,\n    SVGViewSpec          : false,\n    SVGZoomAndPan        : false,\n    TimeEvent            : false,\n    top                  : false,\n    Uint16Array          : false,\n    Uint32Array          : false,\n    Uint8Array           : false,\n    Uint8ClampedArray    : false,\n    WebSocket            : false,\n    window               : false,\n    Worker               : false,\n    XMLHttpRequest       : false,\n    XMLSerializer        : false,\n    XPathEvaluator       : false,\n    XPathException       : false,\n    XPathExpression      : false,\n    XPathNamespace       : false,\n    XPathNSResolver      : false,\n    XPathResult          : false\n};\n\nexports.devel = {\n    alert  : false,\n    confirm: false,\n    console: false,\n    Debug  : false,\n    opera  : false,\n    prompt : false\n};\n\nexports.worker = {\n    importScripts: true,\n    postMessage  : true,\n    self         : true\n};\n\n// Widely adopted global names that are not part of ECMAScript standard\nexports.nonstandard = {\n    escape  : false,\n    unescape: false\n};\n\n// Globals provided by popular JavaScript environments.\n\nexports.couch = {\n    \"require\" : false,\n    respond   : false,\n    getRow    : false,\n    emit      : false,\n    send      : false,\n    start     : false,\n    sum       : false,\n    log       : false,\n    exports   : false,\n    module    : false,\n    provides  : false\n};\n\nexports.node = {\n    __filename    : false,\n    __dirname     : false,\n    Buffer        : false,\n    DataView      : false,\n    console       : false,\n    exports       : true,  // In Node it is ok to exports = module.exports = foo();\n    GLOBAL        : false,\n    global        : false,\n    module        : false,\n    process       : false,\n    require       : false,\n    setTimeout    : false,\n    clearTimeout  : false,\n    setInterval   : false,\n    clearInterval : false,\n    setImmediate  : false, // v0.9.1+\n    clearImmediate: false  // v0.9.1+\n};\n\nexports.phantom = {\n    phantom      : true,\n    require      : true,\n    WebPage      : true\n};\n\nexports.rhino = {\n    defineClass  : false,\n    deserialize  : false,\n    gc           : false,\n    help         : false,\n    importPackage: false,\n    \"java\"       : false,\n    load         : false,\n    loadClass    : false,\n    print        : false,\n    quit         : false,\n    readFile     : false,\n    readUrl      : false,\n    runCommand   : false,\n    seal         : false,\n    serialize    : false,\n    spawn        : false,\n    sync         : false,\n    toint32      : false,\n    version      : false\n};\n\nexports.shelljs = {\n    target       : false,\n    echo         : false,\n    exit         : false,\n    cd           : false,\n    pwd          : false,\n    ls           : false,\n    find         : false,\n    cp           : false,\n    rm           : false,\n    mv           : false,\n    mkdir        : false,\n    test         : false,\n    cat          : false,\n    sed          : false,\n    grep         : false,\n    which        : false,\n    dirs         : false,\n    pushd        : false,\n    popd         : false,\n    env          : false,\n    exec         : false,\n    chmod        : false,\n    config       : false,\n    error        : false,\n    tempdir      : false\n};\n\nexports.wsh = {\n    ActiveXObject            : true,\n    Enumerator               : true,\n    GetObject                : true,\n    ScriptEngine             : true,\n    ScriptEngineBuildVersion : true,\n    ScriptEngineMajorVersion : true,\n    ScriptEngineMinorVersion : true,\n    VBArray                  : true,\n    WSH                      : true,\n    WScript                  : true,\n    XDomainRequest           : true\n};\n\n// Globals provided by popular JavaScript libraries.\n\nexports.dojo = {\n    dojo     : false,\n    dijit    : false,\n    dojox    : false,\n    define   : false,\n    \"require\": false\n};\n\nexports.jquery = {\n    \"$\"    : false,\n    jQuery : false\n};\n\nexports.mootools = {\n    \"$\"           : false,\n    \"$$\"          : false,\n    Asset         : false,\n    Browser       : false,\n    Chain         : false,\n    Class         : false,\n    Color         : false,\n    Cookie        : false,\n    Core          : false,\n    Document      : false,\n    DomReady      : false,\n    DOMEvent      : false,\n    DOMReady      : false,\n    Drag          : false,\n    Element       : false,\n    Elements      : false,\n    Event         : false,\n    Events        : false,\n    Fx            : false,\n    Group         : false,\n    Hash          : false,\n    HtmlTable     : false,\n    Iframe        : false,\n    IframeShim    : false,\n    InputValidator: false,\n    instanceOf    : false,\n    Keyboard      : false,\n    Locale        : false,\n    Mask          : false,\n    MooTools      : false,\n    Native        : false,\n    Options       : false,\n    OverText      : false,\n    Request       : false,\n    Scroller      : false,\n    Slick         : false,\n    Slider        : false,\n    Sortables     : false,\n    Spinner       : false,\n    Swiff         : false,\n    Tips          : false,\n    Type          : false,\n    typeOf        : false,\n    URI           : false,\n    Window        : false\n};\n\nexports.prototypejs = {\n    \"$\"               : false,\n    \"$$\"              : false,\n    \"$A\"              : false,\n    \"$F\"              : false,\n    \"$H\"              : false,\n    \"$R\"              : false,\n    \"$break\"          : false,\n    \"$continue\"       : false,\n    \"$w\"              : false,\n    Abstract          : false,\n    Ajax              : false,\n    Class             : false,\n    Enumerable        : false,\n    Element           : false,\n    Event             : false,\n    Field             : false,\n    Form              : false,\n    Hash              : false,\n    Insertion         : false,\n    ObjectRange       : false,\n    PeriodicalExecuter: false,\n    Position          : false,\n    Prototype         : false,\n    Selector          : false,\n    Template          : false,\n    Toggle            : false,\n    Try               : false,\n    Autocompleter     : false,\n    Builder           : false,\n    Control           : false,\n    Draggable         : false,\n    Draggables        : false,\n    Droppables        : false,\n    Effect            : false,\n    Sortable          : false,\n    SortableObserver  : false,\n    Sound             : false,\n    Scriptaculous     : false\n};\n\nexports.yui = {\n    YUI       : false,\n    Y         : false,\n    YUI_config: false\n};\n\n\n})()\n},{}],4:[function(require,module,exports){\n/*\n * Regular expressions. Some of these are stupidly long.\n */\n\n/*jshint maxlen:1000 */\n\n\"use string\";\n\n// Unsafe comment or string (ax)\nexports.unsafeString =\n    /@cc|<\\/?|script|\\]\\s*\\]|<\\s*!|&lt/i;\n\n// Unsafe characters that are silently deleted by one or more browsers (cx)\nexports.unsafeChars =\n    /[\\u0000-\\u001f\\u007f-\\u009f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/;\n\n// Characters in strings that need escaping (nx and nxg)\nexports.needEsc =\n    /[\\u0000-\\u001f&<\"\\/\\\\\\u007f-\\u009f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/;\n\nexports.needEscGlobal =\n    /[\\u0000-\\u001f&<\"\\/\\\\\\u007f-\\u009f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g;\n\n// Star slash (lx)\nexports.starSlash = /\\*\\//;\n\n// Identifier (ix)\nexports.identifier = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/;\n\n// JavaScript URL (jx)\nexports.javascriptURL = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\\s*:/i;\n\n// Catches /* falls through */ comments (ft)\nexports.fallsThrough = /^\\s*\\/\\*\\s*falls?\\sthrough\\s*\\*\\/\\s*$/;\n\n},{}],5:[function(require,module,exports){\n(function(){\"use strict\";\n\nexports.register = function (linter) {\n    // Check for properties named __proto__. This special property was\n    // deprecated and then re-introduced for ES6.\n\n    linter.on(\"Identifier\", function style_scanProto(data) {\n        if (linter.getOption(\"proto\")) {\n            return;\n        }\n\n        if (data.name === \"__proto__\") {\n            linter.warn(\"W103\", {\n                line: data.line,\n                char: data.char,\n                data: [ data.name ]\n            });\n        }\n    });\n\n    // Check for properties named __iterator__. This is a special property\n    // available only in browsers with JavaScript 1.7 implementation.\n\n    linter.on(\"Identifier\", function style_scanIterator(data) {\n        if (linter.getOption(\"iterator\")) {\n            return;\n        }\n\n        if (data.name === \"__iterator__\") {\n            linter.warn(\"W104\", {\n                line: data.line,\n                char: data.char,\n                data: [ data.name ]\n            });\n        }\n    });\n\n    // Check for dangling underscores.\n\n    linter.on(\"Identifier\", function style_scanDangling(data) {\n        if (!linter.getOption(\"nomen\")) {\n            return;\n        }\n\n        // Underscore.js\n        if (data.name === \"_\") {\n            return;\n        }\n\n        // In Node, __dirname and __filename should be ignored.\n        if (linter.getOption(\"node\")) {\n            if (/^(__dirname|__filename)$/.test(data.name) && !data.isProperty) {\n                return;\n            }\n        }\n\n        if (/^(_+.*|.*_+)$/.test(data.name)) {\n            linter.warn(\"W105\", {\n                line: data.line,\n                char: data.from,\n                data: [ \"dangling '_'\", data.name ]\n            });\n        }\n    });\n\n    // Check that all identifiers are using camelCase notation.\n    // Exceptions: names like MY_VAR and _myVar.\n\n    linter.on(\"Identifier\", function style_scanCamelCase(data) {\n        if (!linter.getOption(\"camelcase\")) {\n            return;\n        }\n\n        if (data.name.replace(/^_+/, \"\").indexOf(\"_\") > -1 && !data.name.match(/^[A-Z0-9_]*$/)) {\n            linter.warn(\"W106\", {\n                line: data.line,\n                char: data.from,\n                data: [ data.name ]\n            });\n        }\n    });\n\n    // Enforce consistency in style of quoting.\n\n    linter.on(\"String\", function style_scanQuotes(data) {\n        var quotmark = linter.getOption(\"quotmark\");\n        var code;\n\n        if (!quotmark) {\n            return;\n        }\n\n        // If quotmark is set to 'single' warn about all double-quotes.\n\n        if (quotmark === \"single\" && data.quote !== \"'\") {\n            code = \"W109\";\n        }\n\n        // If quotmark is set to 'double' warn about all single-quotes.\n\n        if (quotmark === \"double\" && data.quote !== \"\\\"\") {\n            code = \"W108\";\n        }\n\n        // If quotmark is set to true, remember the first quotation style\n        // and then warn about all others.\n\n        if (quotmark === true) {\n            if (!linter.getCache(\"quotmark\")) {\n                linter.setCache(\"quotmark\", data.quote);\n            }\n\n            if (linter.getCache(\"quotmark\") !== data.quote) {\n                code = \"W110\";\n            }\n        }\n\n        if (code) {\n            linter.warn(code, {\n                line: data.line,\n                char: data.char,\n            });\n        }\n    });\n\n    linter.on(\"Number\", function style_scanNumbers(data) {\n        if (data.value.charAt(0) === \".\") {\n            // Warn about a leading decimal point.\n            linter.warn(\"W008\", {\n                line: data.line,\n                char: data.char,\n                data: [ data.value ]\n            });\n        }\n\n        if (data.value.substr(data.value.length - 1) === \".\") {\n            // Warn about a trailing decimal point.\n            linter.warn(\"W047\", {\n                line: data.line,\n                char: data.char,\n                data: [ data.value ]\n            });\n        }\n\n        if (/^00+/.test(data.value)) {\n            // Multiple leading zeroes.\n            linter.warn(\"W046\", {\n                line: data.line,\n                char: data.char,\n                data: [ data.value ]\n            });\n        }\n    });\n\n    // Warn about script URLs.\n\n    linter.on(\"String\", function style_scanJavaScriptURLs(data) {\n        var re = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\\s*:/i;\n\n        if (linter.getOption(\"scripturl\")) {\n            return;\n        }\n\n        if (re.test(data.value)) {\n            linter.warn(\"W107\", {\n                line: data.line,\n                char: data.char\n            });\n        }\n    });\n};\n})()\n},{}],6:[function(require,module,exports){\n\"use strict\";\n\nvar state = {\n    syntax: {},\n\n    reset: function () {\n        this.tokens = {\n            prev: null,\n            next: null,\n            curr: null\n        };\n\n        this.option = {};\n        this.ignored = {};\n        this.directive = {};\n        this.jsonMode = false;\n        this.jsonWarnings = [];\n        this.lines = [];\n        this.tab = \"\";\n        this.cache = {}; // Node.JS doesn't have Map. Sniff.\n    }\n};\n\nexports.state = state;\n\n},{}],\"jshint\":[function(require,module,exports){\nmodule.exports=require('E/GbHF');\n},{}],\"E/GbHF\":[function(require,module,exports){\n(function(){/*!\n * JSHint, by JSHint Community.\n *\n * This file (and this file only) is licensed under the same slightly modified\n * MIT license that JSLint is. It stops evil-doers everywhere:\n *\n *   Copyright (c) 2002 Douglas Crockford  (www.JSLint.com)\n *\n *   Permission is hereby granted, free of charge, to any person obtaining\n *   a copy of this software and associated documentation files (the \"Software\"),\n *   to deal in the Software without restriction, including without limitation\n *   the rights to use, copy, modify, merge, publish, distribute, sublicense,\n *   and/or sell copies of the Software, and to permit persons to whom\n *   the Software is furnished to do so, subject to the following conditions:\n *\n *   The above copyright notice and this permission notice shall be included\n *   in all copies or substantial portions of the Software.\n *\n *   The Software shall be used for Good, not Evil.\n *\n *   THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n *   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n *   DEALINGS IN THE SOFTWARE.\n *\n */\n\n/*jshint quotmark:double */\n/*global console:true */\n/*exported console */\n\nvar _        = require(\"underscore\");\nvar events   = require(\"events\");\nvar vars     = require(\"../shared/vars.js\");\nvar messages = require(\"../shared/messages.js\");\nvar Lexer    = require(\"./lex.js\").Lexer;\nvar reg      = require(\"./reg.js\");\nvar state    = require(\"./state.js\").state;\nvar style    = require(\"./style.js\");\n\n// We need this module here because environments such as IE and Rhino\n// don't necessarilly expose the 'console' API and browserify uses\n// it to log things. It's a sad state of affair, really.\nvar console = require(\"console-browserify\");\n\n// We build the application inside a function so that we produce only a singleton\n// variable. That function will be invoked immediately, and its return value is\n// the JSHINT function itself.\n\nvar JSHINT = (function () {\n    \"use strict\";\n\n    var anonname, // The guessed name for anonymous functions.\n        api, // Extension API\n\n        // These are operators that should not be used with the ! operator.\n        bang = {\n            \"<\"  : true,\n            \"<=\" : true,\n            \"==\" : true,\n            \"===\": true,\n            \"!==\": true,\n            \"!=\" : true,\n            \">\"  : true,\n            \">=\" : true,\n            \"+\"  : true,\n            \"-\"  : true,\n            \"*\"  : true,\n            \"/\"  : true,\n            \"%\"  : true\n        },\n\n        // These are the JSHint boolean options.\n        boolOptions = {\n            asi         : true, // if automatic semicolon insertion should be tolerated\n            bitwise     : true, // if bitwise operators should not be allowed\n            boss        : true, // if advanced usage of assignments should be allowed\n            browser     : true, // if the standard browser globals should be predefined\n            camelcase   : true, // if identifiers should be required in camel case\n            couch       : true, // if CouchDB globals should be predefined\n            curly       : true, // if curly braces around all blocks should be required\n            debug       : true, // if debugger statements should be allowed\n            devel       : true, // if logging globals should be predefined (console, alert, etc.)\n            dojo        : true, // if Dojo Toolkit globals should be predefined\n            eqeqeq      : true, // if === should be required\n            eqnull      : true, // if == null comparisons should be tolerated\n            es3         : true, // if ES3 syntax should be allowed\n            es5         : true, // if ES5 syntax should be allowed (is now set per default)\n            esnext      : true, // if es.next specific syntax should be allowed\n            moz         : true, // if mozilla specific syntax should be allowed\n            evil        : true, // if eval should be allowed\n            expr        : true, // if ExpressionStatement should be allowed as Programs\n            forin       : true, // if for in statements must filter\n            funcscope   : true, // if only function scope should be used for scope tests\n            gcl         : true, // if JSHint should be compatible with Google Closure Linter\n            globalstrict: true, // if global \"use strict\"; should be allowed (also enables 'strict')\n            immed       : true, // if immediate invocations must be wrapped in parens\n            iterator    : true, // if the `__iterator__` property should be allowed\n            jquery      : true, // if jQuery globals should be predefined\n            lastsemic   : true, // if semicolons may be ommitted for the trailing\n                                // statements inside of a one-line blocks.\n            laxbreak    : true, // if line breaks should not be checked\n            laxcomma    : true, // if line breaks should not be checked around commas\n            loopfunc    : true, // if functions should be allowed to be defined within\n                                // loops\n            mootools    : true, // if MooTools globals should be predefined\n            multistr    : true, // allow multiline strings\n            newcap      : true, // if constructor names must be capitalized\n            noarg       : true, // if arguments.caller and arguments.callee should be\n                                // disallowed\n            node        : true, // if the Node.js environment globals should be\n                                // predefined\n            noempty     : true, // if empty blocks should be disallowed\n            nonew       : true, // if using `new` for side-effects should be disallowed\n            nonstandard : true, // if non-standard (but widely adopted) globals should\n                                // be predefined\n            nomen       : true, // if names should be checked\n            onevar      : true, // if only one var statement per function should be\n                                // allowed\n            passfail    : true, // if the scan should stop on first error\n            phantom     : true, // if PhantomJS symbols should be allowed\n            plusplus    : true, // if increment/decrement should not be allowed\n            proto       : true, // if the `__proto__` property should be allowed\n            prototypejs : true, // if Prototype and Scriptaculous globals should be\n                                // predefined\n            rhino       : true, // if the Rhino environment globals should be predefined\n            shelljs     : true, // if ShellJS globals should be predefined\n            undef       : true, // if variables should be declared before used\n            scripturl   : true, // if script-targeted URLs should be tolerated\n            shadow      : true, // if variable shadowing should be tolerated\n            smarttabs   : true, // if smarttabs should be tolerated\n                                // (http://www.emacswiki.org/emacs/SmartTabs)\n            strict      : true, // require the \"use strict\"; pragma\n            sub         : true, // if all forms of subscript notation are tolerated\n            supernew    : true, // if `new function () { ... };` and `new Object;`\n                                // should be tolerated\n            trailing    : true, // if trailing whitespace rules apply\n            validthis   : true, // if 'this' inside a non-constructor function is valid.\n                                // This is a function scoped option only.\n            withstmt    : true, // if with statements should be allowed\n            white       : true, // if strict whitespace rules apply\n            worker      : true, // if Web Worker script symbols should be allowed\n            wsh         : true, // if the Windows Scripting Host environment globals\n                                // should be predefined\n            yui         : true, // YUI variables should be predefined\n\n            // Obsolete options\n            onecase     : true, // if one case switch statements should be allowed\n            regexp      : true, // if the . should not be allowed in regexp literals\n            regexdash   : true  // if unescaped first/last dash (-) inside brackets\n                                // should be tolerated\n        },\n\n        // These are the JSHint options that can take any value\n        // (we use this object to detect invalid options)\n        valOptions = {\n            maxlen       : false,\n            indent       : false,\n            maxerr       : false,\n            predef       : false,\n            quotmark     : false, //'single'|'double'|true\n            scope        : false,\n            maxstatements: false, // {int} max statements per function\n            maxdepth     : false, // {int} max nested block depth per function\n            maxparams    : false, // {int} max params per function\n            maxcomplexity: false, // {int} max cyclomatic complexity per function\n            unused       : true,  // warn if variables are unused. Available options:\n                                  //   false    - don't check for unused variables\n                                  //   true     - \"vars\" + check last function param\n                                  //   \"vars\"   - skip checking unused function params\n                                  //   \"strict\" - \"vars\" + check all function params\n            latedef      : false  // warn if the variable is used before its definition\n                                  //   false    - don't emit any warnings\n                                  //   true     - warn if any variable is used before its definition\n                                  //   \"nofunc\" - warn for any variable but function declarations\n        },\n\n        // These are JSHint boolean options which are shared with JSLint\n        // where the definition in JSHint is opposite JSLint\n        invertedOptions = {\n            bitwise : true,\n            forin   : true,\n            newcap  : true,\n            nomen   : true,\n            plusplus: true,\n            regexp  : true,\n            undef   : true,\n            white   : true,\n\n            // Inverted and renamed, use JSHint name here\n            eqeqeq  : true,\n            onevar  : true,\n            strict  : true\n        },\n\n        // These are JSHint boolean options which are shared with JSLint\n        // where the name has been changed but the effect is unchanged\n        renamedOptions = {\n            eqeq   : \"eqeqeq\",\n            vars   : \"onevar\",\n            windows: \"wsh\",\n            sloppy : \"strict\"\n        },\n\n        declared, // Globals that were declared using /*global ... */ syntax.\n        exported, // Variables that are used outside of the current file.\n\n        functionicity = [\n            \"closure\", \"exception\", \"global\", \"label\",\n            \"outer\", \"unused\", \"var\"\n        ],\n\n        funct, // The current function\n        functions, // All of the functions\n\n        global, // The global scope\n        implied, // Implied globals\n        inblock,\n        indent,\n        lookahead,\n        lex,\n        member,\n        membersOnly,\n        noreach,\n        predefined,     // Global variables defined by option\n\n        scope,  // The current scope\n        stack,\n        unuseds,\n        urls,\n        warnings,\n\n        extraModules = [],\n        emitter = new events.EventEmitter();\n\n    function checkOption(name, t) {\n        name = name.trim();\n\n        if (/^[+-]W\\d{3}$/g.test(name)) {\n            return true;\n        }\n\n        if (valOptions[name] === undefined && boolOptions[name] === undefined) {\n            if (t.type !== \"jslint\") {\n                error(\"E001\", t, name);\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    function isString(obj) {\n        return Object.prototype.toString.call(obj) === \"[object String]\";\n    }\n\n    function isIdentifier(tkn, value) {\n        if (!tkn)\n            return false;\n\n        if (!tkn.identifier || tkn.value !== value)\n            return false;\n\n        return true;\n    }\n\n    function isReserved(token) {\n        if (!token.reserved) {\n            return false;\n        }\n        var meta = token.meta;\n\n        if (meta && meta.isFutureReservedWord && state.option.inES5()) {\n            // ES3 FutureReservedWord in an ES5 environment.\n            if (!meta.es5) {\n                return false;\n            }\n\n            // Some ES5 FutureReservedWord identifiers are active only\n            // within a strict mode environment.\n            if (meta.strictOnly) {\n                if (!state.option.strict && !state.directive[\"use strict\"]) {\n                    return false;\n                }\n            }\n\n            if (token.isProperty) {\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    function supplant(str, data) {\n        return str.replace(/\\{([^{}]*)\\}/g, function (a, b) {\n            var r = data[b];\n            return typeof r === \"string\" || typeof r === \"number\" ? r : a;\n        });\n    }\n\n    function combine(t, o) {\n        var n;\n        for (n in o) {\n            if (_.has(o, n) && !_.has(JSHINT.blacklist, n)) {\n                t[n] = o[n];\n            }\n        }\n    }\n\n    function updatePredefined() {\n        Object.keys(JSHINT.blacklist).forEach(function (key) {\n            delete predefined[key];\n        });\n    }\n\n    function assume() {\n        if (state.option.es5) {\n            warning(\"I003\");\n        }\n        if (state.option.couch) {\n            combine(predefined, vars.couch);\n        }\n\n        if (state.option.rhino) {\n            combine(predefined, vars.rhino);\n        }\n\n        if (state.option.shelljs) {\n            combine(predefined, vars.shelljs);\n            combine(predefined, vars.node);\n        }\n\n        if (state.option.phantom) {\n            combine(predefined, vars.phantom);\n        }\n\n        if (state.option.prototypejs) {\n            combine(predefined, vars.prototypejs);\n        }\n\n        if (state.option.node) {\n            combine(predefined, vars.node);\n        }\n\n        if (state.option.devel) {\n            combine(predefined, vars.devel);\n        }\n\n        if (state.option.dojo) {\n            combine(predefined, vars.dojo);\n        }\n\n        if (state.option.browser) {\n            combine(predefined, vars.browser);\n        }\n\n        if (state.option.nonstandard) {\n            combine(predefined, vars.nonstandard);\n        }\n\n        if (state.option.jquery) {\n            combine(predefined, vars.jquery);\n        }\n\n        if (state.option.mootools) {\n            combine(predefined, vars.mootools);\n        }\n\n        if (state.option.worker) {\n            combine(predefined, vars.worker);\n        }\n\n        if (state.option.wsh) {\n            combine(predefined, vars.wsh);\n        }\n\n        if (state.option.globalstrict && state.option.strict !== false) {\n            state.option.strict = true;\n        }\n\n        if (state.option.yui) {\n            combine(predefined, vars.yui);\n        }\n\n        // Let's assume that chronologically ES3 < ES5 < ES6/ESNext < Moz\n\n        state.option.inMoz = function (strict) {\n            if (strict) {\n                return state.option.moz && !state.option.esnext;\n            }\n            return state.option.moz;\n        };\n\n        state.option.inESNext = function (strict) {\n            if (strict) {\n                return !state.option.moz && state.option.esnext;\n            }\n            return state.option.moz || state.option.esnext;\n        };\n\n        state.option.inES5 = function (/* strict */) {\n            return !state.option.es3;\n        };\n\n        state.option.inES3 = function (strict) {\n            if (strict) {\n                return !state.option.moz && !state.option.esnext && state.option.es3;\n            }\n            return state.option.es3;\n        };\n    }\n\n    // Produce an error warning.\n    function quit(code, line, chr) {\n        var percentage = Math.floor((line / state.lines.length) * 100);\n        var message = messages.errors[code].desc;\n\n        throw {\n            name: \"JSHintError\",\n            line: line,\n            character: chr,\n            message: message + \" (\" + percentage + \"% scanned).\",\n            raw: message,\n            code: code\n        };\n    }\n\n    function isundef(scope, code, token, a) {\n        return JSHINT.undefs.push([scope, code, token, a]);\n    }\n\n    function warning(code, t, a, b, c, d) {\n        var ch, l, w, msg;\n\n        if (/^W\\d{3}$/.test(code)) {\n            if (state.ignored[code])\n                return;\n\n            msg = messages.warnings[code];\n        } else if (/E\\d{3}/.test(code)) {\n            msg = messages.errors[code];\n        } else if (/I\\d{3}/.test(code)) {\n            msg = messages.info[code];\n        }\n\n        t = t || state.tokens.next;\n        if (t.id === \"(end)\") {  // `~\n            t = state.tokens.curr;\n        }\n\n        l = t.line || 0;\n        ch = t.from || 0;\n\n        w = {\n            id: \"(error)\",\n            raw: msg.desc,\n            code: msg.code,\n            evidence: state.lines[l - 1] || \"\",\n            line: l,\n            character: ch,\n            scope: JSHINT.scope,\n            a: a,\n            b: b,\n            c: c,\n            d: d\n        };\n\n        w.reason = supplant(msg.desc, w);\n        JSHINT.errors.push(w);\n\n        if (state.option.passfail) {\n            quit(\"E042\", l, ch);\n        }\n\n        warnings += 1;\n        if (warnings >= state.option.maxerr) {\n            quit(\"E043\", l, ch);\n        }\n\n        return w;\n    }\n\n    function warningAt(m, l, ch, a, b, c, d) {\n        return warning(m, {\n            line: l,\n            from: ch\n        }, a, b, c, d);\n    }\n\n    function error(m, t, a, b, c, d) {\n        warning(m, t, a, b, c, d);\n    }\n\n    function errorAt(m, l, ch, a, b, c, d) {\n        return error(m, {\n            line: l,\n            from: ch\n        }, a, b, c, d);\n    }\n\n    // Tracking of \"internal\" scripts, like eval containing a static string\n    function addInternalSrc(elem, src) {\n        var i;\n        i = {\n            id: \"(internal)\",\n            elem: elem,\n            value: src\n        };\n        JSHINT.internals.push(i);\n        return i;\n    }\n\n    function addlabel(t, type, tkn, islet) {\n        // Define t in the current function in the current scope.\n        if (type === \"exception\") {\n            if (_.has(funct[\"(context)\"], t)) {\n                if (funct[t] !== true && !state.option.node) {\n                    warning(\"W002\", state.tokens.next, t);\n                }\n            }\n        }\n\n        if (_.has(funct, t) && !funct[\"(global)\"]) {\n            if (funct[t] === true) {\n                if (state.option.latedef) {\n                    if ((state.option.latedef === true && _.contains([funct[t], type], \"unction\")) ||\n                            !_.contains([funct[t], type], \"unction\")) {\n                        warning(\"W003\", state.tokens.next, t);\n                    }\n                }\n            } else {\n                if (!state.option.shadow && type !== \"exception\" ||\n                            (funct[\"(blockscope)\"].getlabel(t))) {\n                    warning(\"W004\", state.tokens.next, t);\n                }\n            }\n        }\n\n        // a double definition of a let variable in same block throws a TypeError\n        if (funct[\"(blockscope)\"] && funct[\"(blockscope)\"].current.has(t)) {\n            error(\"E044\", state.tokens.next, t);\n        }\n\n        // if the identifier is from a let, adds it only to the current blockscope\n        if (islet) {\n            funct[\"(blockscope)\"].current.add(t, type, state.tokens.curr);\n        } else {\n\n            funct[t] = type;\n\n            if (tkn) {\n                funct[\"(tokens)\"][t] = tkn;\n            }\n\n            if (funct[\"(global)\"]) {\n                global[t] = funct;\n                if (_.has(implied, t)) {\n                    if (state.option.latedef) {\n                        if ((state.option.latedef === true && _.contains([funct[t], type], \"unction\")) ||\n                                !_.contains([funct[t], type], \"unction\")) {\n                            warning(\"W003\", state.tokens.next, t);\n                        }\n                    }\n\n                    delete implied[t];\n                }\n            } else {\n                scope[t] = funct;\n            }\n        }\n    }\n\n    function doOption() {\n        var nt = state.tokens.next;\n        var body = nt.body.split(\",\").map(function (s) { return s.trim(); });\n        var predef = {};\n\n        if (nt.type === \"globals\") {\n            body.forEach(function (g) {\n                g = g.split(\":\");\n                var key = g[0];\n                var val = g[1];\n\n                if (key.charAt(0) === \"-\") {\n                    key = key.slice(1);\n                    val = false;\n\n                    JSHINT.blacklist[key] = key;\n                    updatePredefined();\n                } else {\n                    predef[key] = (val === \"true\");\n                }\n            });\n\n            combine(predefined, predef);\n\n            for (var key in predef) {\n                if (_.has(predef, key)) {\n                    declared[key] = nt;\n                }\n            }\n        }\n\n        if (nt.type === \"exported\") {\n            body.forEach(function (e) {\n                exported[e] = true;\n            });\n        }\n\n        if (nt.type === \"members\") {\n            membersOnly = membersOnly || {};\n\n            body.forEach(function (m) {\n                var ch1 = m.charAt(0);\n                var ch2 = m.charAt(m.length - 1);\n\n                if (ch1 === ch2 && (ch1 === \"\\\"\" || ch1 === \"'\")) {\n                    m = m\n                        .substr(1, m.length - 2)\n                        .replace(\"\\\\b\", \"\\b\")\n                        .replace(\"\\\\t\", \"\\t\")\n                        .replace(\"\\\\n\", \"\\n\")\n                        .replace(\"\\\\v\", \"\\v\")\n                        .replace(\"\\\\f\", \"\\f\")\n                        .replace(\"\\\\r\", \"\\r\")\n                        .replace(\"\\\\\\\\\", \"\\\\\")\n                        .replace(\"\\\\\\\"\", \"\\\"\");\n                }\n\n                membersOnly[m] = false;\n            });\n        }\n\n        var numvals = [\n            \"maxstatements\",\n            \"maxparams\",\n            \"maxdepth\",\n            \"maxcomplexity\",\n            \"maxerr\",\n            \"maxlen\",\n            \"indent\"\n        ];\n\n        if (nt.type === \"jshint\" || nt.type === \"jslint\") {\n            body.forEach(function (g) {\n                g = g.split(\":\");\n                var key = (g[0] || \"\").trim();\n                var val = (g[1] || \"\").trim();\n\n                if (!checkOption(key, nt)) {\n                    return;\n                }\n\n                if (numvals.indexOf(key) >= 0) {\n\n                    // GH988 - numeric options can be disabled by setting them to `false`\n                    if (val !== \"false\") {\n                        val = +val;\n\n                        if (typeof val !== \"number\" || !isFinite(val) || val <= 0 || Math.floor(val) !== val) {\n                            error(\"E032\", nt, g[1].trim());\n                            return;\n                        }\n\n                        if (key === \"indent\") {\n                            state.option[\"(explicitIndent)\"] = true;\n                        }\n                        state.option[key] = val;\n                    } else {\n                        if (key === \"indent\") {\n                            state.option[\"(explicitIndent)\"] = false;\n                        } else {\n                            state.option[key] = false;\n                        }\n                    }\n\n                    return;\n                }\n\n                if (key === \"validthis\") {\n                    // `validthis` is valid only within a function scope.\n                    if (funct[\"(global)\"]) {\n                        error(\"E009\");\n                    } else {\n                        if (val === \"true\" || val === \"false\") {\n                            state.option.validthis = (val === \"true\");\n                        } else {\n                            error(\"E002\", nt);\n                        }\n                    }\n                    return;\n                }\n\n                if (key === \"quotmark\") {\n                    switch (val) {\n                    case \"true\":\n                    case \"false\":\n                        state.option.quotmark = (val === \"true\");\n                        break;\n                    case \"double\":\n                    case \"single\":\n                        state.option.quotmark = val;\n                        break;\n                    default:\n                        error(\"E002\", nt);\n                    }\n                    return;\n                }\n\n                if (key === \"unused\") {\n                    switch (val) {\n                    case \"true\":\n                        state.option.unused = true;\n                        break;\n                    case \"false\":\n                        state.option.unused = false;\n                        break;\n                    case \"vars\":\n                    case \"strict\":\n                        state.option.unused = val;\n                        break;\n                    default:\n                        error(\"E002\", nt);\n                    }\n                    return;\n                }\n\n                if (key === \"latedef\") {\n                    switch (val) {\n                    case \"true\":\n                        state.option.latedef = true;\n                        break;\n                    case \"false\":\n                        state.option.latedef = false;\n                        break;\n                    case \"nofunc\":\n                        state.option.latedef = \"nofunc\";\n                        break;\n                    default:\n                        error(\"E002\", nt);\n                    }\n                    return;\n                }\n\n                var match = /^([+-])(W\\d{3})$/g.exec(key);\n                if (match) {\n                    // ignore for -W..., unignore for +W...\n                    state.ignored[match[2]] = (match[1] === \"-\");\n                    return;\n                }\n\n                var tn;\n                if (val === \"true\" || val === \"false\") {\n                    if (nt.type === \"jslint\") {\n                        tn = renamedOptions[key] || key;\n                        state.option[tn] = (val === \"true\");\n\n                        if (invertedOptions[tn] !== undefined) {\n                            state.option[tn] = !state.option[tn];\n                        }\n                    } else {\n                        state.option[key] = (val === \"true\");\n                    }\n\n                    if (key === \"newcap\") {\n                        state.option[\"(explicitNewcap)\"] = true;\n                    }\n                    return;\n                }\n\n                error(\"E002\", nt);\n            });\n\n            assume();\n        }\n    }\n\n    // We need a peek function. If it has an argument, it peeks that much farther\n    // ahead. It is used to distinguish\n    //     for ( var i in ...\n    // from\n    //     for ( var i = ...\n\n    function peek(p) {\n        var i = p || 0, j = 0, t;\n\n        while (j <= i) {\n            t = lookahead[j];\n            if (!t) {\n                t = lookahead[j] = lex.token();\n            }\n            j += 1;\n        }\n        return t;\n    }\n\n    // Produce the next token. It looks for programming errors.\n\n    function advance(id, t) {\n        switch (state.tokens.curr.id) {\n        case \"(number)\":\n            if (state.tokens.next.id === \".\") {\n                warning(\"W005\", state.tokens.curr);\n            }\n            break;\n        case \"-\":\n            if (state.tokens.next.id === \"-\" || state.tokens.next.id === \"--\") {\n                warning(\"W006\");\n            }\n            break;\n        case \"+\":\n            if (state.tokens.next.id === \"+\" || state.tokens.next.id === \"++\") {\n                warning(\"W007\");\n            }\n            break;\n        }\n\n        if (state.tokens.curr.type === \"(string)\" || state.tokens.curr.identifier) {\n            anonname = state.tokens.curr.value;\n        }\n\n        if (id && state.tokens.next.id !== id) {\n            if (t) {\n                if (state.tokens.next.id === \"(end)\") {\n                    error(\"E019\", t, t.id);\n                } else {\n                    error(\"E020\", state.tokens.next, id, t.id, t.line, state.tokens.next.value);\n                }\n            } else if (state.tokens.next.type !== \"(identifier)\" || state.tokens.next.value !== id) {\n                warning(\"W116\", state.tokens.next, id, state.tokens.next.value);\n            }\n        }\n\n        state.tokens.prev = state.tokens.curr;\n        state.tokens.curr = state.tokens.next;\n        for (;;) {\n            state.tokens.next = lookahead.shift() || lex.token();\n\n            if (!state.tokens.next) { // No more tokens left, give up\n                quit(\"E041\", state.tokens.curr.line);\n            }\n\n            if (state.tokens.next.id === \"(end)\" || state.tokens.next.id === \"(error)\") {\n                return;\n            }\n\n            if (state.tokens.next.check) {\n                state.tokens.next.check();\n            }\n\n            if (state.tokens.next.isSpecial) {\n                doOption();\n            } else {\n                if (state.tokens.next.id !== \"(endline)\") {\n                    break;\n                }\n            }\n        }\n    }\n\n    function isInfix(token) {\n        return token.infix || (!token.identifier && !!token.led);\n    }\n\n    function isEndOfExpr() {\n        var curr = state.tokens.curr;\n        var next = state.tokens.next;\n        if (next.id === \";\" || next.id === \"}\" || next.id === \":\") {\n            return true;\n        }\n        if (isInfix(next) === isInfix(curr) || (curr.id === \"yield\" && state.option.inMoz(true))) {\n            return curr.line !== next.line;\n        }\n        return false;\n    }\n\n    // This is the heart of JSHINT, the Pratt parser. In addition to parsing, it\n    // is looking for ad hoc lint patterns. We add .fud to Pratt's model, which is\n    // like .nud except that it is only used on the first token of a statement.\n    // Having .fud makes it much easier to define statement-oriented languages like\n    // JavaScript. I retained Pratt's nomenclature.\n\n    // .nud  Null denotation\n    // .fud  First null denotation\n    // .led  Left denotation\n    //  lbp  Left binding power\n    //  rbp  Right binding power\n\n    // They are elements of the parsing method called Top Down Operator Precedence.\n\n    function expression(rbp, initial) {\n        var left, isArray = false, isObject = false, isLetExpr = false;\n\n        // if current expression is a let expression\n        if (!initial && state.tokens.next.value === \"let\" && peek(0).value === \"(\") {\n            if (!state.option.inMoz(true)) {\n                warning(\"W118\", state.tokens.next, \"let expressions\");\n            }\n            isLetExpr = true;\n            // create a new block scope we use only for the current expression\n            funct[\"(blockscope)\"].stack();\n            advance(\"let\");\n            advance(\"(\");\n            state.syntax[\"let\"].fud.call(state.syntax[\"let\"].fud, false);\n            advance(\")\");\n        }\n\n        if (state.tokens.next.id === \"(end)\")\n            error(\"E006\", state.tokens.curr);\n\n        advance();\n\n        if (initial) {\n            anonname = \"anonymous\";\n            funct[\"(verb)\"] = state.tokens.curr.value;\n        }\n\n        if (initial === true && state.tokens.curr.fud) {\n            left = state.tokens.curr.fud();\n        } else {\n            if (state.tokens.curr.nud) {\n                left = state.tokens.curr.nud();\n            } else {\n                error(\"E030\", state.tokens.curr, state.tokens.curr.id);\n            }\n\n            while (rbp < state.tokens.next.lbp && !isEndOfExpr()) {\n                isArray = state.tokens.curr.value === \"Array\";\n                isObject = state.tokens.curr.value === \"Object\";\n\n                // #527, new Foo.Array(), Foo.Array(), new Foo.Object(), Foo.Object()\n                // Line breaks in IfStatement heads exist to satisfy the checkJSHint\n                // \"Line too long.\" error.\n                if (left && (left.value || (left.first && left.first.value))) {\n                    // If the left.value is not \"new\", or the left.first.value is a \".\"\n                    // then safely assume that this is not \"new Array()\" and possibly\n                    // not \"new Object()\"...\n                    if (left.value !== \"new\" ||\n                      (left.first && left.first.value && left.first.value === \".\")) {\n                        isArray = false;\n                        // ...In the case of Object, if the left.value and state.tokens.curr.value\n                        // are not equal, then safely assume that this not \"new Object()\"\n                        if (left.value !== state.tokens.curr.value) {\n                            isObject = false;\n                        }\n                    }\n                }\n\n                advance();\n\n                if (isArray && state.tokens.curr.id === \"(\" && state.tokens.next.id === \")\") {\n                    warning(\"W009\", state.tokens.curr);\n                }\n\n                if (isObject && state.tokens.curr.id === \"(\" && state.tokens.next.id === \")\") {\n                    warning(\"W010\", state.tokens.curr);\n                }\n\n                if (left && state.tokens.curr.led) {\n                    left = state.tokens.curr.led(left);\n                } else {\n                    error(\"E033\", state.tokens.curr, state.tokens.curr.id);\n                }\n            }\n        }\n        if (isLetExpr) {\n            funct[\"(blockscope)\"].unstack();\n        }\n        return left;\n    }\n\n\n// Functions for conformance of style.\n\n    function adjacent(left, right) {\n        left = left || state.tokens.curr;\n        right = right || state.tokens.next;\n        if (state.option.white) {\n            if (left.character !== right.from && left.line === right.line) {\n                left.from += (left.character - left.from);\n                warning(\"W011\", left, left.value);\n            }\n        }\n    }\n\n    function nobreak(left, right) {\n        left = left || state.tokens.curr;\n        right = right || state.tokens.next;\n        if (state.option.white && (left.character !== right.from || left.line !== right.line)) {\n            warning(\"W012\", right, right.value);\n        }\n    }\n\n    function nospace(left, right) {\n        left = left || state.tokens.curr;\n        right = right || state.tokens.next;\n        if (state.option.white && !left.comment) {\n            if (left.line === right.line) {\n                adjacent(left, right);\n            }\n        }\n    }\n\n    function nonadjacent(left, right) {\n        if (state.option.white) {\n            left = left || state.tokens.curr;\n            right = right || state.tokens.next;\n\n            if (left.value === \";\" && right.value === \";\") {\n                return;\n            }\n\n            if (left.line === right.line && left.character === right.from) {\n                left.from += (left.character - left.from);\n                warning(\"W013\", left, left.value);\n            }\n        }\n    }\n\n    function nobreaknonadjacent(left, right) {\n        left = left || state.tokens.curr;\n        right = right || state.tokens.next;\n        if (!state.option.laxbreak && left.line !== right.line) {\n            warning(\"W014\", right, right.value);\n        } else if (state.option.white) {\n            left = left || state.tokens.curr;\n            right = right || state.tokens.next;\n            if (left.character === right.from) {\n                left.from += (left.character - left.from);\n                warning(\"W013\", left, left.value);\n            }\n        }\n    }\n\n    function indentation(bias) {\n        if (!state.option.white && !state.option[\"(explicitIndent)\"]) {\n            return;\n        }\n\n        if (state.tokens.next.id === \"(end)\") {\n            return;\n        }\n\n        var i = indent + (bias || 0);\n        if (state.tokens.next.from !== i) {\n            warning(\"W015\", state.tokens.next, state.tokens.next.value, i, state.tokens.next.from);\n        }\n    }\n\n    function nolinebreak(t) {\n        t = t || state.tokens.curr;\n        if (t.line !== state.tokens.next.line) {\n            warning(\"E022\", t, t.value);\n        }\n    }\n\n    function nobreakcomma(left, right) {\n        if (left.line !== right.line) {\n            if (!state.option.laxcomma) {\n                if (comma.first) {\n                    warning(\"I001\");\n                    comma.first = false;\n                }\n                warning(\"W014\", left, right.value);\n            }\n        } else if (!left.comment && left.character !== right.from && state.option.white) {\n            left.from += (left.character - left.from);\n            warning(\"W011\", left, left.value);\n        }\n    }\n\n    function comma(opts) {\n        opts = opts || {};\n\n        if (!opts.peek) {\n            nobreakcomma(state.tokens.curr, state.tokens.next);\n            advance(\",\");\n        } else {\n            nobreakcomma(state.tokens.prev, state.tokens.curr);\n        }\n\n        // TODO: This is a temporary solution to fight against false-positives in\n        // arrays and objects with trailing commas (see GH-363). The best solution\n        // would be to extract all whitespace rules out of parser.\n\n        if (state.tokens.next.value !== \"]\" && state.tokens.next.value !== \"}\") {\n            nonadjacent(state.tokens.curr, state.tokens.next);\n        }\n\n        if (state.tokens.next.identifier && !(opts.property && state.option.inES5())) {\n            // Keywords that cannot follow a comma operator.\n            switch (state.tokens.next.value) {\n            case \"break\":\n            case \"case\":\n            case \"catch\":\n            case \"continue\":\n            case \"default\":\n            case \"do\":\n            case \"else\":\n            case \"finally\":\n            case \"for\":\n            case \"if\":\n            case \"in\":\n            case \"instanceof\":\n            case \"return\":\n            case \"switch\":\n            case \"throw\":\n            case \"try\":\n            case \"var\":\n            case \"let\":\n            case \"while\":\n            case \"with\":\n                error(\"E024\", state.tokens.next, state.tokens.next.value);\n                return false;\n            }\n        }\n\n        if (state.tokens.next.type === \"(punctuator)\") {\n            switch (state.tokens.next.value) {\n            case \"}\":\n            case \"]\":\n            case \",\":\n                if (opts.allowTrailing) {\n                    return true;\n                }\n\n                /* falls through */\n            case \")\":\n                error(\"E024\", state.tokens.next, state.tokens.next.value);\n                return false;\n            }\n        }\n        return true;\n    }\n\n    // Functional constructors for making the symbols that will be inherited by\n    // tokens.\n\n    function symbol(s, p) {\n        var x = state.syntax[s];\n        if (!x || typeof x !== \"object\") {\n            state.syntax[s] = x = {\n                id: s,\n                lbp: p,\n                value: s\n            };\n        }\n        return x;\n    }\n\n    function delim(s) {\n        return symbol(s, 0);\n    }\n\n    function stmt(s, f) {\n        var x = delim(s);\n        x.identifier = x.reserved = true;\n        x.fud = f;\n        return x;\n    }\n\n    function blockstmt(s, f) {\n        var x = stmt(s, f);\n        x.block = true;\n        return x;\n    }\n\n    function reserveName(x) {\n        var c = x.id.charAt(0);\n        if ((c >= \"a\" && c <= \"z\") || (c >= \"A\" && c <= \"Z\")) {\n            x.identifier = x.reserved = true;\n        }\n        return x;\n    }\n\n    function prefix(s, f) {\n        var x = symbol(s, 150);\n        reserveName(x);\n        x.nud = (typeof f === \"function\") ? f : function () {\n            this.right = expression(150);\n            this.arity = \"unary\";\n            if (this.id === \"++\" || this.id === \"--\") {\n                if (state.option.plusplus) {\n                    warning(\"W016\", this, this.id);\n                } else if ((!this.right.identifier || isReserved(this.right)) &&\n                        this.right.id !== \".\" && this.right.id !== \"[\") {\n                    warning(\"W017\", this);\n                }\n            }\n            return this;\n        };\n        return x;\n    }\n\n    function type(s, f) {\n        var x = delim(s);\n        x.type = s;\n        x.nud = f;\n        return x;\n    }\n\n    function reserve(name, func) {\n        var x = type(name, func);\n        x.identifier = true;\n        x.reserved = true;\n        return x;\n    }\n\n    function FutureReservedWord(name, meta) {\n        var x = type(name, (meta && meta.nud) || function () {\n            return this;\n        });\n\n        meta = meta || {};\n        meta.isFutureReservedWord = true;\n\n        x.value = name;\n        x.identifier = true;\n        x.reserved = true;\n        x.meta = meta;\n\n        return x;\n    }\n\n    function reservevar(s, v) {\n        return reserve(s, function () {\n            if (typeof v === \"function\") {\n                v(this);\n            }\n            return this;\n        });\n    }\n\n    function infix(s, f, p, w) {\n        var x = symbol(s, p);\n        reserveName(x);\n        x.infix = true;\n        x.led = function (left) {\n            if (!w) {\n                nobreaknonadjacent(state.tokens.prev, state.tokens.curr);\n                nonadjacent(state.tokens.curr, state.tokens.next);\n            }\n            if (s === \"in\" && left.id === \"!\") {\n                warning(\"W018\", left, \"!\");\n            }\n            if (typeof f === \"function\") {\n                return f(left, this);\n            } else {\n                this.left = left;\n                this.right = expression(p);\n                return this;\n            }\n        };\n        return x;\n    }\n\n\n    function application(s) {\n        var x = symbol(s, 42);\n\n        x.led = function (left) {\n            if (!state.option.inESNext()) {\n                warning(\"W104\", state.tokens.curr, \"arrow function syntax (=>)\");\n            }\n\n            nobreaknonadjacent(state.tokens.prev, state.tokens.curr);\n            nonadjacent(state.tokens.curr, state.tokens.next);\n\n            this.left = left;\n            this.right = doFunction(undefined, undefined, false, left);\n            return this;\n        };\n        return x;\n    }\n\n    function relation(s, f) {\n        var x = symbol(s, 100);\n\n        x.led = function (left) {\n            nobreaknonadjacent(state.tokens.prev, state.tokens.curr);\n            nonadjacent(state.tokens.curr, state.tokens.next);\n            var right = expression(100);\n\n            if (isIdentifier(left, \"NaN\") || isIdentifier(right, \"NaN\")) {\n                warning(\"W019\", this);\n            } else if (f) {\n                f.apply(this, [left, right]);\n            }\n\n            if (!left || !right) {\n                quit(\"E041\", state.tokens.curr.line);\n            }\n\n            if (left.id === \"!\") {\n                warning(\"W018\", left, \"!\");\n            }\n\n            if (right.id === \"!\") {\n                warning(\"W018\", right, \"!\");\n            }\n\n            this.left = left;\n            this.right = right;\n            return this;\n        };\n        return x;\n    }\n\n    function isPoorRelation(node) {\n        return node &&\n              ((node.type === \"(number)\" && +node.value === 0) ||\n               (node.type === \"(string)\" && node.value === \"\") ||\n               (node.type === \"null\" && !state.option.eqnull) ||\n                node.type === \"true\" ||\n                node.type === \"false\" ||\n                node.type === \"undefined\");\n    }\n\n    function assignop(s, f, p) {\n        var x = infix(s, typeof f === \"function\" ? f : function (left, that) {\n            that.left = left;\n\n            if (left) {\n                if (predefined[left.value] === false &&\n                        scope[left.value][\"(global)\"] === true) {\n                    warning(\"W020\", left);\n                } else if (left[\"function\"]) {\n                    warning(\"W021\", left, left.value);\n                }\n\n                if (funct[left.value] === \"const\") {\n                    error(\"E013\", left, left.value);\n                }\n\n                if (left.id === \".\") {\n                    if (!left.left) {\n                        warning(\"E031\", that);\n                    } else if (left.left.value === \"arguments\" && !state.directive[\"use strict\"]) {\n                        warning(\"E031\", that);\n                    }\n\n                    that.right = expression(10);\n                    return that;\n                } else if (left.id === \"[\") {\n                    if (state.tokens.curr.left.first) {\n                        state.tokens.curr.left.first.forEach(function (t) {\n                            if (funct[t.value] === \"const\") {\n                                error(\"E013\", t, t.value);\n                            }\n                        });\n                    } else if (!left.left) {\n                        warning(\"E031\", that);\n                    } else if (left.left.value === \"arguments\" && !state.directive[\"use strict\"]) {\n                        warning(\"E031\", that);\n                    }\n                    that.right = expression(10);\n                    return that;\n                } else if (left.identifier && !isReserved(left)) {\n                    if (funct[left.value] === \"exception\") {\n                        warning(\"W022\", left);\n                    }\n                    that.right = expression(10);\n                    return that;\n                }\n\n                if (left === state.syntax[\"function\"]) {\n                    warning(\"W023\", state.tokens.curr);\n                }\n            }\n\n            error(\"E031\", that);\n        }, p);\n\n        x.exps = true;\n        x.assign = true;\n        return x;\n    }\n\n\n    function bitwise(s, f, p) {\n        var x = symbol(s, p);\n        reserveName(x);\n        x.led = (typeof f === \"function\") ? f : function (left) {\n            if (state.option.bitwise) {\n                warning(\"W016\", this, this.id);\n            }\n            this.left = left;\n            this.right = expression(p);\n            return this;\n        };\n        return x;\n    }\n\n\n    function bitwiseassignop(s) {\n        return assignop(s, function (left, that) {\n            if (state.option.bitwise) {\n                warning(\"W016\", that, that.id);\n            }\n            nonadjacent(state.tokens.prev, state.tokens.curr);\n            nonadjacent(state.tokens.curr, state.tokens.next);\n            if (left) {\n                if (left.id === \".\" || left.id === \"[\" ||\n                        (left.identifier && !isReserved(left))) {\n                    expression(10);\n                    return that;\n                }\n                if (left === state.syntax[\"function\"]) {\n                    warning(\"W023\", state.tokens.curr);\n                }\n                return that;\n            }\n            error(\"E031\", that);\n        }, 20);\n    }\n\n\n    function suffix(s) {\n        var x = symbol(s, 150);\n\n        x.led = function (left) {\n            if (state.option.plusplus) {\n                warning(\"W016\", this, this.id);\n            } else if ((!left.identifier || isReserved(left)) && left.id !== \".\" && left.id !== \"[\") {\n                warning(\"W017\", this);\n            }\n\n            this.left = left;\n            return this;\n        };\n        return x;\n    }\n\n    // fnparam means that this identifier is being defined as a function\n    // argument (see identifier())\n    // prop means that this identifier is that of an object property\n\n    function optionalidentifier(fnparam, prop) {\n        if (!state.tokens.next.identifier) {\n            return;\n        }\n\n        advance();\n\n        var curr = state.tokens.curr;\n        var val  = state.tokens.curr.value;\n\n        if (!isReserved(curr)) {\n            return val;\n        }\n\n        if (prop) {\n            if (state.option.inES5()) {\n                return val;\n            }\n        }\n\n        if (fnparam && val === \"undefined\") {\n            return val;\n        }\n\n        // Display an info message about reserved words as properties\n        // and ES5 but do it only once.\n        if (prop && !api.getCache(\"displayed:I002\")) {\n            api.setCache(\"displayed:I002\", true);\n            warning(\"I002\");\n        }\n\n        warning(\"W024\", state.tokens.curr, state.tokens.curr.id);\n        return val;\n    }\n\n    // fnparam means that this identifier is being defined as a function\n    // argument\n    // prop means that this identifier is that of an object property\n    function identifier(fnparam, prop) {\n        var i = optionalidentifier(fnparam, prop);\n        if (i) {\n            return i;\n        }\n        if (state.tokens.curr.id === \"function\" && state.tokens.next.id === \"(\") {\n            warning(\"W025\");\n        } else {\n            error(\"E030\", state.tokens.next, state.tokens.next.value);\n        }\n    }\n\n\n    function reachable(s) {\n        var i = 0, t;\n        if (state.tokens.next.id !== \";\" || noreach) {\n            return;\n        }\n        for (;;) {\n            t = peek(i);\n            if (t.reach) {\n                return;\n            }\n            if (t.id !== \"(endline)\") {\n                if (t.id === \"function\") {\n                    if (!state.option.latedef) {\n                        break;\n                    }\n\n                    warning(\"W026\", t);\n                    break;\n                }\n\n                warning(\"W027\", t, t.value, s);\n                break;\n            }\n            i += 1;\n        }\n    }\n\n\n    function statement(noindent) {\n        var values;\n        var i = indent, r, s = scope, t = state.tokens.next;\n\n        if (t.id === \";\") {\n            advance(\";\");\n            return;\n        }\n\n        // Is this a labelled statement?\n        var res = isReserved(t);\n\n        // We're being more tolerant here: if someone uses\n        // a FutureReservedWord as a label, we warn but proceed\n        // anyway.\n\n        if (res && t.meta && t.meta.isFutureReservedWord && peek().id === \":\") {\n            warning(\"W024\", t, t.id);\n            res = false;\n        }\n\n        // detect a destructuring assignment\n        if (_.has([\"[\", \"{\"], t.value)) {\n            if (lookupBlockType().isDestAssign) {\n                if (!state.option.inESNext()) {\n                    warning(\"W104\", state.tokens.curr, \"destructuring expression\");\n                }\n                values = destructuringExpression();\n                values.forEach(function (tok) {\n                    isundef(funct, \"W117\", tok.token, tok.id);\n                });\n                advance(\"=\");\n                destructuringExpressionMatch(values, expression(10, true));\n                advance(\";\");\n                return;\n            }\n        }\n        if (t.identifier && !res && peek().id === \":\") {\n            advance();\n            advance(\":\");\n            scope = Object.create(s);\n            addlabel(t.value, \"label\");\n\n            if (!state.tokens.next.labelled && state.tokens.next.value !== \"{\") {\n                warning(\"W028\", state.tokens.next, t.value, state.tokens.next.value);\n            }\n\n            state.tokens.next.label = t.value;\n            t = state.tokens.next;\n        }\n\n        // Is it a lonely block?\n\n        if (t.id === \"{\") {\n            block(true, true);\n            return;\n        }\n\n        // Parse the statement.\n\n        if (!noindent) {\n            indentation();\n        }\n        r = expression(0, true);\n\n        // Look for the final semicolon.\n\n        if (!t.block) {\n            if (!state.option.expr && (!r || !r.exps)) {\n                warning(\"W030\", state.tokens.curr);\n            } else if (state.option.nonew && r && r.left && r.id === \"(\" && r.left.id === \"new\") {\n                warning(\"W031\", t);\n            }\n\n            if (state.tokens.next.id !== \";\") {\n                if (!state.option.asi) {\n                    // If this is the last statement in a block that ends on\n                    // the same line *and* option lastsemic is on, ignore the warning.\n                    // Otherwise, complain about missing semicolon.\n                    if (!state.option.lastsemic || state.tokens.next.id !== \"}\" ||\n                        state.tokens.next.line !== state.tokens.curr.line) {\n                        warningAt(\"W033\", state.tokens.curr.line, state.tokens.curr.character);\n                    }\n                }\n            } else {\n                adjacent(state.tokens.curr, state.tokens.next);\n                advance(\";\");\n                nonadjacent(state.tokens.curr, state.tokens.next);\n            }\n        }\n\n        // Restore the indentation.\n\n        indent = i;\n        scope = s;\n        return r;\n    }\n\n\n    function statements(startLine) {\n        var a = [], p;\n\n        while (!state.tokens.next.reach && state.tokens.next.id !== \"(end)\") {\n            if (state.tokens.next.id === \";\") {\n                p = peek();\n\n                if (!p || (p.id !== \"(\" && p.id !== \"[\")) {\n                    warning(\"W032\");\n                }\n\n                advance(\";\");\n            } else {\n                a.push(statement(startLine === state.tokens.next.line));\n            }\n        }\n        return a;\n    }\n\n\n    /*\n     * read all directives\n     * recognizes a simple form of asi, but always\n     * warns, if it is used\n     */\n    function directives() {\n        var i, p, pn;\n\n        for (;;) {\n            if (state.tokens.next.id === \"(string)\") {\n                p = peek(0);\n                if (p.id === \"(endline)\") {\n                    i = 1;\n                    do {\n                        pn = peek(i);\n                        i = i + 1;\n                    } while (pn.id === \"(endline)\");\n\n                    if (pn.id !== \";\") {\n                        if (pn.id !== \"(string)\" && pn.id !== \"(number)\" &&\n                            pn.id !== \"(regexp)\" && pn.identifier !== true &&\n                            pn.id !== \"}\") {\n                            break;\n                        }\n                        warning(\"W033\", state.tokens.next);\n                    } else {\n                        p = pn;\n                    }\n                } else if (p.id === \"}\") {\n                    // Directive with no other statements, warn about missing semicolon\n                    warning(\"W033\", p);\n                } else if (p.id !== \";\") {\n                    break;\n                }\n\n                indentation();\n                advance();\n                if (state.directive[state.tokens.curr.value]) {\n                    warning(\"W034\", state.tokens.curr, state.tokens.curr.value);\n                }\n\n                if (state.tokens.curr.value === \"use strict\") {\n                    if (!state.option[\"(explicitNewcap)\"])\n                        state.option.newcap = true;\n                    state.option.undef = true;\n                }\n\n                // there's no directive negation, so always set to true\n                state.directive[state.tokens.curr.value] = true;\n\n                if (p.id === \";\") {\n                    advance(\";\");\n                }\n                continue;\n            }\n            break;\n        }\n    }\n\n\n    /*\n     * Parses a single block. A block is a sequence of statements wrapped in\n     * braces.\n     *\n     * ordinary - true for everything but function bodies and try blocks.\n     * stmt     - true if block can be a single statement (e.g. in if/for/while).\n     * isfunc   - true if block is a function body\n     */\n    function block(ordinary, stmt, isfunc, isfatarrow) {\n        var a,\n            b = inblock,\n            old_indent = indent,\n            m,\n            s = scope,\n            t,\n            line,\n            d;\n\n        inblock = ordinary;\n\n        if (!ordinary || !state.option.funcscope)\n            scope = Object.create(scope);\n\n        nonadjacent(state.tokens.curr, state.tokens.next);\n        t = state.tokens.next;\n\n        var metrics = funct[\"(metrics)\"];\n        metrics.nestedBlockDepth += 1;\n        metrics.verifyMaxNestedBlockDepthPerFunction();\n\n        if (state.tokens.next.id === \"{\") {\n            advance(\"{\");\n\n            // create a new block scope\n            funct[\"(blockscope)\"].stack();\n\n            line = state.tokens.curr.line;\n            if (state.tokens.next.id !== \"}\") {\n                indent += state.option.indent;\n                while (!ordinary && state.tokens.next.from > indent) {\n                    indent += state.option.indent;\n                }\n\n                if (isfunc) {\n                    m = {};\n                    for (d in state.directive) {\n                        if (_.has(state.directive, d)) {\n                            m[d] = state.directive[d];\n                        }\n                    }\n                    directives();\n\n                    if (state.option.strict && funct[\"(context)\"][\"(global)\"]) {\n                        if (!m[\"use strict\"] && !state.directive[\"use strict\"]) {\n                            warning(\"E007\");\n                        }\n                    }\n                }\n\n                a = statements(line);\n\n                metrics.statementCount += a.length;\n\n                if (isfunc) {\n                    state.directive = m;\n                }\n\n                indent -= state.option.indent;\n                if (line !== state.tokens.next.line) {\n                    indentation();\n                }\n            } else if (line !== state.tokens.next.line) {\n                indentation();\n            }\n            advance(\"}\", t);\n\n            funct[\"(blockscope)\"].unstack();\n\n            indent = old_indent;\n        } else if (!ordinary) {\n            if (isfunc) {\n                m = {};\n                if (stmt && !isfatarrow && !state.option.inMoz(true)) {\n                    error(\"W118\", state.tokens.curr, \"function closure expressions\");\n                }\n\n                if (!stmt) {\n                    for (d in state.directive) {\n                        if (_.has(state.directive, d)) {\n                            m[d] = state.directive[d];\n                        }\n                    }\n                }\n                expression(10);\n\n                if (state.option.strict && funct[\"(context)\"][\"(global)\"]) {\n                    if (!m[\"use strict\"] && !state.directive[\"use strict\"]) {\n                        warning(\"E007\");\n                    }\n                }\n            } else {\n                error(\"E021\", state.tokens.next, \"{\", state.tokens.next.value);\n            }\n        } else {\n\n            // check to avoid let declaration not within a block\n            funct[\"(nolet)\"] = true;\n\n            if (!stmt || state.option.curly) {\n                warning(\"W116\", state.tokens.next, \"{\", state.tokens.next.value);\n            }\n\n            noreach = true;\n            indent += state.option.indent;\n            // test indentation only if statement is in new line\n            a = [statement(state.tokens.next.line === state.tokens.curr.line)];\n            indent -= state.option.indent;\n            noreach = false;\n\n            delete funct[\"(nolet)\"];\n        }\n        funct[\"(verb)\"] = null;\n        if (!ordinary || !state.option.funcscope) scope = s;\n        inblock = b;\n        if (ordinary && state.option.noempty && (!a || a.length === 0)) {\n            warning(\"W035\");\n        }\n        metrics.nestedBlockDepth -= 1;\n        return a;\n    }\n\n\n    function countMember(m) {\n        if (membersOnly && typeof membersOnly[m] !== \"boolean\") {\n            warning(\"W036\", state.tokens.curr, m);\n        }\n        if (typeof member[m] === \"number\") {\n            member[m] += 1;\n        } else {\n            member[m] = 1;\n        }\n    }\n\n\n    function note_implied(tkn) {\n        var name = tkn.value, line = tkn.line, a = implied[name];\n        if (typeof a === \"function\") {\n            a = false;\n        }\n\n        if (!a) {\n            a = [line];\n            implied[name] = a;\n        } else if (a[a.length - 1] !== line) {\n            a.push(line);\n        }\n    }\n\n\n    // Build the syntax table by declaring the syntactic elements of the language.\n\n    type(\"(number)\", function () {\n        return this;\n    });\n\n    type(\"(string)\", function () {\n        return this;\n    });\n\n    state.syntax[\"(identifier)\"] = {\n        type: \"(identifier)\",\n        lbp: 0,\n        identifier: true,\n        nud: function () {\n            var v = this.value,\n                s = scope[v],\n                f;\n\n            if (typeof s === \"function\") {\n                // Protection against accidental inheritance.\n                s = undefined;\n            } else if (typeof s === \"boolean\") {\n                f = funct;\n                funct = functions[0];\n                addlabel(v, \"var\");\n                s = funct;\n                funct = f;\n            }\n            var block;\n            if (_.has(funct, \"(blockscope)\")) {\n                block = funct[\"(blockscope)\"].getlabel(v);\n            }\n\n            // The name is in scope and defined in the current function.\n            if (funct === s || block) {\n                // Change 'unused' to 'var', and reject labels.\n                // the name is in a block scope\n                switch (block ? block[v][\"(type)\"] : funct[v]) {\n                case \"unused\":\n                    if (block) block[v][\"(type)\"] = \"var\";\n                    else funct[v] = \"var\";\n                    break;\n                case \"unction\":\n                    if (block) block[v][\"(type)\"] = \"function\";\n                    else funct[v] = \"function\";\n                    this[\"function\"] = true;\n                    break;\n                case \"function\":\n                    this[\"function\"] = true;\n                    break;\n                case \"label\":\n                    warning(\"W037\", state.tokens.curr, v);\n                    break;\n                }\n            } else if (funct[\"(global)\"]) {\n                // The name is not defined in the function.  If we are in the global\n                // scope, then we have an undefined variable.\n                //\n                // Operators typeof and delete do not raise runtime errors even if\n                // the base object of a reference is null so no need to display warning\n                // if we're inside of typeof or delete.\n\n                if (typeof predefined[v] !== \"boolean\") {\n                    // Attempting to subscript a null reference will throw an\n                    // error, even within the typeof and delete operators\n                    if (!(anonname === \"typeof\" || anonname === \"delete\") ||\n                        (state.tokens.next && (state.tokens.next.value === \".\" ||\n                            state.tokens.next.value === \"[\"))) {\n\n                        // if we're in a list comprehension, variables are declared\n                        // locally and used before being defined. So we check\n                        // the presence of the given variable in the comp array\n                        // before declaring it undefined.\n\n                        if (!funct[\"(comparray)\"].check(v)) {\n                            isundef(funct, \"W117\", state.tokens.curr, v);\n                        }\n                    }\n                }\n\n                note_implied(state.tokens.curr);\n            } else {\n                // If the name is already defined in the current\n                // function, but not as outer, then there is a scope error.\n\n                switch (funct[v]) {\n                case \"closure\":\n                case \"function\":\n                case \"var\":\n                case \"unused\":\n                    warning(\"W038\", state.tokens.curr, v);\n                    break;\n                case \"label\":\n                    warning(\"W037\", state.tokens.curr, v);\n                    break;\n                case \"outer\":\n                case \"global\":\n                    break;\n                default:\n                    // If the name is defined in an outer function, make an outer entry,\n                    // and if it was unused, make it var.\n                    if (s === true) {\n                        funct[v] = true;\n                    } else if (s === null) {\n                        warning(\"W039\", state.tokens.curr, v);\n                        note_implied(state.tokens.curr);\n                    } else if (typeof s !== \"object\") {\n                        // Operators typeof and delete do not raise runtime errors even\n                        // if the base object of a reference is null so no need to\n                        //\n                        // display warning if we're inside of typeof or delete.\n                        // Attempting to subscript a null reference will throw an\n                        // error, even within the typeof and delete operators\n                        if (!(anonname === \"typeof\" || anonname === \"delete\") ||\n                            (state.tokens.next &&\n                                (state.tokens.next.value === \".\" || state.tokens.next.value === \"[\"))) {\n\n                            isundef(funct, \"W117\", state.tokens.curr, v);\n                        }\n                        funct[v] = true;\n                        note_implied(state.tokens.curr);\n                    } else {\n                        switch (s[v]) {\n                        case \"function\":\n                        case \"unction\":\n                            this[\"function\"] = true;\n                            s[v] = \"closure\";\n                            funct[v] = s[\"(global)\"] ? \"global\" : \"outer\";\n                            break;\n                        case \"var\":\n                        case \"unused\":\n                            s[v] = \"closure\";\n                            funct[v] = s[\"(global)\"] ? \"global\" : \"outer\";\n                            break;\n                        case \"closure\":\n                            funct[v] = s[\"(global)\"] ? \"global\" : \"outer\";\n                            break;\n                        case \"label\":\n                            warning(\"W037\", state.tokens.curr, v);\n                        }\n                    }\n                }\n            }\n            return this;\n        },\n        led: function () {\n            error(\"E033\", state.tokens.next, state.tokens.next.value);\n        }\n    };\n\n    type(\"(regexp)\", function () {\n        return this;\n    });\n\n    // ECMAScript parser\n\n    delim(\"(endline)\");\n    delim(\"(begin)\");\n    delim(\"(end)\").reach = true;\n    delim(\"(error)\").reach = true;\n    delim(\"}\").reach = true;\n    delim(\")\");\n    delim(\"]\");\n    delim(\"\\\"\").reach = true;\n    delim(\"'\").reach = true;\n    delim(\";\");\n    delim(\":\").reach = true;\n    delim(\"#\");\n\n    reserve(\"else\");\n    reserve(\"case\").reach = true;\n    reserve(\"catch\");\n    reserve(\"default\").reach = true;\n    reserve(\"finally\");\n    reservevar(\"arguments\", function (x) {\n        if (state.directive[\"use strict\"] && funct[\"(global)\"]) {\n            warning(\"E008\", x);\n        }\n    });\n    reservevar(\"eval\");\n    reservevar(\"false\");\n    reservevar(\"Infinity\");\n    reservevar(\"null\");\n    reservevar(\"this\", function (x) {\n        if (state.directive[\"use strict\"] && !state.option.validthis && ((funct[\"(statement)\"] &&\n                funct[\"(name)\"].charAt(0) > \"Z\") || funct[\"(global)\"])) {\n            warning(\"W040\", x);\n        }\n    });\n    reservevar(\"true\");\n    reservevar(\"undefined\");\n\n    assignop(\"=\", \"assign\", 20);\n    assignop(\"+=\", \"assignadd\", 20);\n    assignop(\"-=\", \"assignsub\", 20);\n    assignop(\"*=\", \"assignmult\", 20);\n    assignop(\"/=\", \"assigndiv\", 20).nud = function () {\n        error(\"E014\");\n    };\n    assignop(\"%=\", \"assignmod\", 20);\n\n    bitwiseassignop(\"&=\", \"assignbitand\", 20);\n    bitwiseassignop(\"|=\", \"assignbitor\", 20);\n    bitwiseassignop(\"^=\", \"assignbitxor\", 20);\n    bitwiseassignop(\"<<=\", \"assignshiftleft\", 20);\n    bitwiseassignop(\">>=\", \"assignshiftright\", 20);\n    bitwiseassignop(\">>>=\", \"assignshiftrightunsigned\", 20);\n    infix(\",\", function (left, that) {\n        var expr;\n        that.exprs = [left];\n        if (!comma({peek: true})) {\n            return that;\n        }\n        while (true) {\n            if (!(expr = expression(10)))  {\n                break;\n            }\n            that.exprs.push(expr);\n            if (state.tokens.next.value !== \",\" || !comma()) {\n                break;\n            }\n        }\n        return that;\n    }, 10, true);\n\n    infix(\"?\", function (left, that) {\n        increaseComplexityCount();\n        that.left = left;\n        that.right = expression(10);\n        advance(\":\");\n        that[\"else\"] = expression(10);\n        return that;\n    }, 30);\n\n    var orPrecendence = 40;\n    infix(\"||\", function (left, that) {\n        increaseComplexityCount();\n        that.left = left;\n        that.right = expression(orPrecendence);\n        return that;\n    }, orPrecendence);\n    infix(\"&&\", \"and\", 50);\n    bitwise(\"|\", \"bitor\", 70);\n    bitwise(\"^\", \"bitxor\", 80);\n    bitwise(\"&\", \"bitand\", 90);\n    relation(\"==\", function (left, right) {\n        var eqnull = state.option.eqnull && (left.value === \"null\" || right.value === \"null\");\n\n        if (!eqnull && state.option.eqeqeq)\n            warning(\"W116\", this, \"===\", \"==\");\n        else if (isPoorRelation(left))\n            warning(\"W041\", this, \"===\", left.value);\n        else if (isPoorRelation(right))\n            warning(\"W041\", this, \"===\", right.value);\n\n        return this;\n    });\n    relation(\"===\");\n    relation(\"!=\", function (left, right) {\n        var eqnull = state.option.eqnull &&\n                (left.value === \"null\" || right.value === \"null\");\n\n        if (!eqnull && state.option.eqeqeq) {\n            warning(\"W116\", this, \"!==\", \"!=\");\n        } else if (isPoorRelation(left)) {\n            warning(\"W041\", this, \"!==\", left.value);\n        } else if (isPoorRelation(right)) {\n            warning(\"W041\", this, \"!==\", right.value);\n        }\n        return this;\n    });\n    relation(\"!==\");\n    relation(\"<\");\n    relation(\">\");\n    relation(\"<=\");\n    relation(\">=\");\n    bitwise(\"<<\", \"shiftleft\", 120);\n    bitwise(\">>\", \"shiftright\", 120);\n    bitwise(\">>>\", \"shiftrightunsigned\", 120);\n    infix(\"in\", \"in\", 120);\n    infix(\"instanceof\", \"instanceof\", 120);\n    infix(\"+\", function (left, that) {\n        var right = expression(130);\n        if (left && right && left.id === \"(string)\" && right.id === \"(string)\") {\n            left.value += right.value;\n            left.character = right.character;\n            if (!state.option.scripturl && reg.javascriptURL.test(left.value)) {\n                warning(\"W050\", left);\n            }\n            return left;\n        }\n        that.left = left;\n        that.right = right;\n        return that;\n    }, 130);\n    prefix(\"+\", \"num\");\n    prefix(\"+++\", function () {\n        warning(\"W007\");\n        this.right = expression(150);\n        this.arity = \"unary\";\n        return this;\n    });\n    infix(\"+++\", function (left) {\n        warning(\"W007\");\n        this.left = left;\n        this.right = expression(130);\n        return this;\n    }, 130);\n    infix(\"-\", \"sub\", 130);\n    prefix(\"-\", \"neg\");\n    prefix(\"---\", function () {\n        warning(\"W006\");\n        this.right = expression(150);\n        this.arity = \"unary\";\n        return this;\n    });\n    infix(\"---\", function (left) {\n        warning(\"W006\");\n        this.left = left;\n        this.right = expression(130);\n        return this;\n    }, 130);\n    infix(\"*\", \"mult\", 140);\n    infix(\"/\", \"div\", 140);\n    infix(\"%\", \"mod\", 140);\n\n    suffix(\"++\", \"postinc\");\n    prefix(\"++\", \"preinc\");\n    state.syntax[\"++\"].exps = true;\n\n    suffix(\"--\", \"postdec\");\n    prefix(\"--\", \"predec\");\n    state.syntax[\"--\"].exps = true;\n    prefix(\"delete\", function () {\n        var p = expression(10);\n        if (!p || (p.id !== \".\" && p.id !== \"[\")) {\n            warning(\"W051\");\n        }\n        this.first = p;\n        return this;\n    }).exps = true;\n\n    prefix(\"~\", function () {\n        if (state.option.bitwise) {\n            warning(\"W052\", this, \"~\");\n        }\n        expression(150);\n        return this;\n    });\n\n    prefix(\"...\", function () {\n        if (!state.option.inESNext()) {\n            warning(\"W104\", this, \"spread/rest operator\");\n        }\n        if (!state.tokens.next.identifier) {\n            error(\"E030\", state.tokens.next, state.tokens.next.value);\n        }\n        expression(150);\n        return this;\n    });\n\n    prefix(\"!\", function () {\n        this.right = expression(150);\n        this.arity = \"unary\";\n\n        if (!this.right) { // '!' followed by nothing? Give up.\n            quit(\"E041\", this.line || 0);\n        }\n\n        if (bang[this.right.id] === true) {\n            warning(\"W018\", this, \"!\");\n        }\n        return this;\n    });\n\n    prefix(\"typeof\", \"typeof\");\n    prefix(\"new\", function () {\n        var c = expression(155), i;\n        if (c && c.id !== \"function\") {\n            if (c.identifier) {\n                c[\"new\"] = true;\n                switch (c.value) {\n                case \"Number\":\n                case \"String\":\n                case \"Boolean\":\n                case \"Math\":\n                case \"JSON\":\n                    warning(\"W053\", state.tokens.prev, c.value);\n                    break;\n                case \"Function\":\n                    if (!state.option.evil) {\n                        warning(\"W054\");\n                    }\n                    break;\n                case \"Date\":\n                case \"RegExp\":\n                    break;\n                default:\n                    if (c.id !== \"function\") {\n                        i = c.value.substr(0, 1);\n                        if (state.option.newcap && (i < \"A\" || i > \"Z\") && !_.has(global, c.value)) {\n                            warning(\"W055\", state.tokens.curr);\n                        }\n                    }\n                }\n            } else {\n                if (c.id !== \".\" && c.id !== \"[\" && c.id !== \"(\") {\n                    warning(\"W056\", state.tokens.curr);\n                }\n            }\n        } else {\n            if (!state.option.supernew)\n                warning(\"W057\", this);\n        }\n        adjacent(state.tokens.curr, state.tokens.next);\n        if (state.tokens.next.id !== \"(\" && !state.option.supernew) {\n            warning(\"W058\", state.tokens.curr, state.tokens.curr.value);\n        }\n        this.first = c;\n        return this;\n    });\n    state.syntax[\"new\"].exps = true;\n\n    prefix(\"void\").exps = true;\n\n    infix(\".\", function (left, that) {\n        adjacent(state.tokens.prev, state.tokens.curr);\n        nobreak();\n        var m = identifier(false, true);\n\n        if (typeof m === \"string\") {\n            countMember(m);\n        }\n\n        that.left = left;\n        that.right = m;\n\n        if (m && m === \"hasOwnProperty\" && state.tokens.next.value === \"=\") {\n            warning(\"W001\");\n        }\n\n        if (left && left.value === \"arguments\" && (m === \"callee\" || m === \"caller\")) {\n            if (state.option.noarg)\n                warning(\"W059\", left, m);\n            else if (state.directive[\"use strict\"])\n                error(\"E008\");\n        } else if (!state.option.evil && left && left.value === \"document\" &&\n                (m === \"write\" || m === \"writeln\")) {\n            warning(\"W060\", left);\n        }\n\n        if (!state.option.evil && (m === \"eval\" || m === \"execScript\")) {\n            warning(\"W061\");\n        }\n\n        return that;\n    }, 160, true);\n\n    infix(\"(\", function (left, that) {\n        if (state.tokens.prev.id !== \"}\" && state.tokens.prev.id !== \")\") {\n            nobreak(state.tokens.prev, state.tokens.curr);\n        }\n\n        nospace();\n        if (state.option.immed && left && !left.immed && left.id === \"function\") {\n            warning(\"W062\");\n        }\n\n        var n = 0;\n        var p = [];\n\n        if (left) {\n            if (left.type === \"(identifier)\") {\n                if (left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) {\n                    if (\"Number String Boolean Date Object\".indexOf(left.value) === -1) {\n                        if (left.value === \"Math\") {\n                            warning(\"W063\", left);\n                        } else if (state.option.newcap) {\n                            warning(\"W064\", left);\n                        }\n                    }\n                }\n            }\n        }\n\n        if (state.tokens.next.id !== \")\") {\n            for (;;) {\n                p[p.length] = expression(10);\n                n += 1;\n                if (state.tokens.next.id !== \",\") {\n                    break;\n                }\n                comma();\n            }\n        }\n\n        advance(\")\");\n        nospace(state.tokens.prev, state.tokens.curr);\n\n        if (typeof left === \"object\") {\n            if (left.value === \"parseInt\" && n === 1) {\n                warning(\"W065\", state.tokens.curr);\n            }\n            if (!state.option.evil) {\n                if (left.value === \"eval\" || left.value === \"Function\" ||\n                        left.value === \"execScript\") {\n                    warning(\"W061\", left);\n\n                    if (p[0] && [0].id === \"(string)\") {\n                        addInternalSrc(left, p[0].value);\n                    }\n                } else if (p[0] && p[0].id === \"(string)\" &&\n                       (left.value === \"setTimeout\" ||\n                        left.value === \"setInterval\")) {\n                    warning(\"W066\", left);\n                    addInternalSrc(left, p[0].value);\n\n                // window.setTimeout/setInterval\n                } else if (p[0] && p[0].id === \"(string)\" &&\n                       left.value === \".\" &&\n                       left.left.value === \"window\" &&\n                       (left.right === \"setTimeout\" ||\n                        left.right === \"setInterval\")) {\n                    warning(\"W066\", left);\n                    addInternalSrc(left, p[0].value);\n                }\n            }\n            if (!left.identifier && left.id !== \".\" && left.id !== \"[\" &&\n                    left.id !== \"(\" && left.id !== \"&&\" && left.id !== \"||\" &&\n                    left.id !== \"?\") {\n                warning(\"W067\", left);\n            }\n        }\n\n        that.left = left;\n        return that;\n    }, 155, true).exps = true;\n\n    prefix(\"(\", function () {\n        nospace();\n        var bracket, brackets = [];\n        var pn, pn1, i = 0;\n        var ret;\n\n        do {\n            pn = peek(i);\n            i += 1;\n            pn1 = peek(i);\n            i += 1;\n        } while (pn.value !== \")\" && pn1.value !== \"=>\" && pn1.value !== \";\" && pn1.type !== \"(end)\");\n\n        if (state.tokens.next.id === \"function\") {\n            state.tokens.next.immed = true;\n        }\n\n        var exprs = [];\n\n        if (state.tokens.next.id !== \")\") {\n            for (;;) {\n                if (pn1.value === \"=>\" && state.tokens.next.value === \"{\") {\n                    bracket = state.tokens.next;\n                    bracket.left = destructuringExpression();\n                    brackets.push(bracket);\n                    for (var t in bracket.left) {\n                        exprs.push(bracket.left[t].token);\n                    }\n                } else {\n                    exprs.push(expression(10));\n                }\n                if (state.tokens.next.id !== \",\") {\n                    break;\n                }\n                comma();\n            }\n        }\n\n        advance(\")\", this);\n        nospace(state.tokens.prev, state.tokens.curr);\n        if (state.option.immed && exprs[0] && exprs[0].id === \"function\") {\n            if (state.tokens.next.id !== \"(\" &&\n              (state.tokens.next.id !== \".\" || (peek().value !== \"call\" && peek().value !== \"apply\"))) {\n                warning(\"W068\", this);\n            }\n        }\n\n        if (state.tokens.next.value === \"=>\") {\n            return exprs;\n        }\n        if (!exprs.length) {\n            return;\n        }\n        if (exprs.length > 1) {\n            ret = Object.create(state.syntax[\",\"]);\n            ret.exprs = exprs;\n        } else {\n            ret = exprs[0];\n        }\n        if (ret) {\n            ret.paren = true;\n        }\n        return ret;\n    });\n\n    application(\"=>\");\n\n    infix(\"[\", function (left, that) {\n        nobreak(state.tokens.prev, state.tokens.curr);\n        nospace();\n        var e = expression(10), s;\n        if (e && e.type === \"(string)\") {\n            if (!state.option.evil && (e.value === \"eval\" || e.value === \"execScript\")) {\n                warning(\"W061\", that);\n            }\n\n            countMember(e.value);\n            if (!state.option.sub && reg.identifier.test(e.value)) {\n                s = state.syntax[e.value];\n                if (!s || !isReserved(s)) {\n                    warning(\"W069\", state.tokens.prev, e.value);\n                }\n            }\n        }\n        advance(\"]\", that);\n\n        if (e && e.value === \"hasOwnProperty\" && state.tokens.next.value === \"=\") {\n            warning(\"W001\");\n        }\n\n        nospace(state.tokens.prev, state.tokens.curr);\n        that.left = left;\n        that.right = e;\n        return that;\n    }, 160, true);\n\n    function comprehensiveArrayExpression() {\n        var res = {};\n        res.exps = true;\n        funct[\"(comparray)\"].stack();\n\n        res.right = expression(10);\n        advance(\"for\");\n        if (state.tokens.next.value === \"each\") {\n            advance(\"each\");\n            if (!state.option.inMoz(true)) {\n                warning(\"W118\", state.tokens.curr, \"for each\");\n            }\n        }\n        advance(\"(\");\n        funct[\"(comparray)\"].setState(\"define\");\n        res.left = expression(10);\n        advance(\")\");\n        if (state.tokens.next.value === \"if\") {\n            advance(\"if\");\n            advance(\"(\");\n            funct[\"(comparray)\"].setState(\"filter\");\n            res.filter = expression(10);\n            advance(\")\");\n        }\n        advance(\"]\");\n        funct[\"(comparray)\"].unstack();\n        return res;\n    }\n\n    prefix(\"[\", function () {\n        var blocktype = lookupBlockType(true);\n        if (blocktype.isCompArray) {\n            if (!state.option.inMoz(true)) {\n                warning(\"W118\", state.tokens.curr, \"array comprehension\");\n            }\n            return comprehensiveArrayExpression();\n        } else if (blocktype.isDestAssign && !state.option.inESNext()) {\n            warning(\"W104\", state.tokens.curr, \"destructuring assignment\");\n        }\n        var b = state.tokens.curr.line !== state.tokens.next.line;\n        this.first = [];\n        if (b) {\n            indent += state.option.indent;\n            if (state.tokens.next.from === indent + state.option.indent) {\n                indent += state.option.indent;\n            }\n        }\n        while (state.tokens.next.id !== \"(end)\") {\n            while (state.tokens.next.id === \",\") {\n                if (!state.option.inES5())\n                    warning(\"W070\");\n                advance(\",\");\n            }\n            if (state.tokens.next.id === \"]\") {\n                break;\n            }\n            if (b && state.tokens.curr.line !== state.tokens.next.line) {\n                indentation();\n            }\n            this.first.push(expression(10));\n            if (state.tokens.next.id === \",\") {\n                comma({ allowTrailing: true });\n                if (state.tokens.next.id === \"]\" && !state.option.inES5(true)) {\n                    warning(\"W070\", state.tokens.curr);\n                    break;\n                }\n            } else {\n                break;\n            }\n        }\n        if (b) {\n            indent -= state.option.indent;\n            indentation();\n        }\n        advance(\"]\", this);\n        return this;\n    }, 160);\n\n\n    function property_name() {\n        var id = optionalidentifier(false, true);\n\n        if (!id) {\n            if (state.tokens.next.id === \"(string)\") {\n                id = state.tokens.next.value;\n                advance();\n            } else if (state.tokens.next.id === \"(number)\") {\n                id = state.tokens.next.value.toString();\n                advance();\n            }\n        }\n\n        if (id === \"hasOwnProperty\") {\n            warning(\"W001\");\n        }\n\n        return id;\n    }\n\n\n    function functionparams(parsed) {\n        var curr, next;\n        var params = [];\n        var ident;\n        var tokens = [];\n        var t;\n        var pastDefault = false;\n\n        if (parsed) {\n            if (parsed instanceof Array) {\n                for (var i in parsed) {\n                    curr = parsed[i];\n                    if (_.contains([\"{\", \"[\"], curr.id)) {\n                        for (t in curr.left) {\n                            t = tokens[t];\n                            if (t.id) {\n                                params.push(t.id);\n                                addlabel(t.id, \"unused\", t.token);\n                            }\n                        }\n                    } else if (curr.value === \"...\") {\n                        if (!state.option.inESNext()) {\n                            warning(\"W104\", curr, \"spread/rest operator\");\n                        }\n                        continue;\n                    } else {\n                        addlabel(curr.value, \"unused\", curr);\n                    }\n                }\n                return params;\n            } else {\n                if (parsed.identifier === true) {\n                    addlabel(parsed.value, \"unused\", parsed);\n                    return [parsed];\n                }\n            }\n        }\n\n        next = state.tokens.next;\n\n        advance(\"(\");\n        nospace();\n\n        if (state.tokens.next.id === \")\") {\n            advance(\")\");\n            return;\n        }\n\n        for (;;) {\n            if (_.contains([\"{\", \"[\"], state.tokens.next.id)) {\n                tokens = destructuringExpression();\n                for (t in tokens) {\n                    t = tokens[t];\n                    if (t.id) {\n                        params.push(t.id);\n                        addlabel(t.id, \"unused\", t.token);\n                    }\n                }\n            } else if (state.tokens.next.value === \"...\") {\n                if (!state.option.inESNext()) {\n                    warning(\"W104\", state.tokens.next, \"spread/rest operator\");\n                }\n                advance(\"...\");\n                nospace();\n                ident = identifier(true);\n                params.push(ident);\n                addlabel(ident, \"unused\", state.tokens.curr);\n            } else {\n                ident = identifier(true);\n                params.push(ident);\n                addlabel(ident, \"unused\", state.tokens.curr);\n            }\n\n            // it is a syntax error to have a regular argument after a default argument\n            if (pastDefault) {\n                if (state.tokens.next.id !== \"=\") {\n                    error(\"E051\", state.tokens.current);\n                }\n            }\n            if (state.tokens.next.id === \"=\") {\n                if (!state.option.inESNext()) {\n                    warning(\"W119\", state.tokens.next, \"default parameters\");\n                }\n                advance(\"=\");\n                pastDefault = true;\n                expression(10);\n            }\n            if (state.tokens.next.id === \",\") {\n                comma();\n            } else {\n                advance(\")\", next);\n                nospace(state.tokens.prev, state.tokens.curr);\n                return params;\n            }\n        }\n    }\n\n\n    function doFunction(name, statement, generator, fatarrowparams) {\n        var f;\n        var oldOption = state.option;\n        var oldIgnored = state.ignored;\n        var oldScope  = scope;\n\n        state.option = Object.create(state.option);\n        state.ignored = Object.create(state.ignored);\n        scope  = Object.create(scope);\n\n        funct = {\n            \"(name)\"      : name || \"\\\"\" + anonname + \"\\\"\",\n            \"(line)\"      : state.tokens.next.line,\n            \"(character)\" : state.tokens.next.character,\n            \"(context)\"   : funct,\n            \"(breakage)\"  : 0,\n            \"(loopage)\"   : 0,\n            \"(metrics)\"   : createMetrics(state.tokens.next),\n            \"(scope)\"     : scope,\n            \"(statement)\" : statement,\n            \"(tokens)\"    : {},\n            \"(blockscope)\": funct[\"(blockscope)\"],\n            \"(comparray)\" : funct[\"(comparray)\"]\n        };\n\n        if (generator) {\n            funct[\"(generator)\"] = true;\n        }\n\n        f = funct;\n        state.tokens.curr.funct = funct;\n\n        functions.push(funct);\n\n        if (name) {\n            addlabel(name, \"function\");\n        }\n\n        funct[\"(params)\"] = functionparams(fatarrowparams);\n\n        funct[\"(metrics)\"].verifyMaxParametersPerFunction(funct[\"(params)\"]);\n\n        block(false, true, true, fatarrowparams ? true:false);\n\n        if (generator && funct[\"(generator)\"] !== \"yielded\") {\n            error(\"E047\", state.tokens.curr);\n        }\n\n        funct[\"(metrics)\"].verifyMaxStatementsPerFunction();\n        funct[\"(metrics)\"].verifyMaxComplexityPerFunction();\n        funct[\"(unusedOption)\"] = state.option.unused;\n\n        scope = oldScope;\n        state.option = oldOption;\n        state.ignored = oldIgnored;\n        funct[\"(last)\"] = state.tokens.curr.line;\n        funct[\"(lastcharacter)\"] = state.tokens.curr.character;\n        funct = funct[\"(context)\"];\n\n        return f;\n    }\n\n    function createMetrics(functionStartToken) {\n        return {\n            statementCount: 0,\n            nestedBlockDepth: -1,\n            ComplexityCount: 1,\n            verifyMaxStatementsPerFunction: function () {\n                if (state.option.maxstatements &&\n                    this.statementCount > state.option.maxstatements) {\n                    warning(\"W071\", functionStartToken, this.statementCount);\n                }\n            },\n\n            verifyMaxParametersPerFunction: function (params) {\n                params = params || [];\n\n                if (state.option.maxparams && params.length > state.option.maxparams) {\n                    warning(\"W072\", functionStartToken, params.length);\n                }\n            },\n\n            verifyMaxNestedBlockDepthPerFunction: function () {\n                if (state.option.maxdepth &&\n                    this.nestedBlockDepth > 0 &&\n                    this.nestedBlockDepth === state.option.maxdepth + 1) {\n                    warning(\"W073\", null, this.nestedBlockDepth);\n                }\n            },\n\n            verifyMaxComplexityPerFunction: function () {\n                var max = state.option.maxcomplexity;\n                var cc = this.ComplexityCount;\n                if (max && cc > max) {\n                    warning(\"W074\", functionStartToken, cc);\n                }\n            }\n        };\n    }\n\n    function increaseComplexityCount() {\n        funct[\"(metrics)\"].ComplexityCount += 1;\n    }\n\n    // Parse assignments that were found instead of conditionals.\n    // For example: if (a = 1) { ... }\n\n    function checkCondAssignment(expr) {\n        var id, paren;\n        if (expr) {\n            id = expr.id;\n            paren = expr.paren;\n            if (id === \",\" && (expr = expr.exprs[expr.exprs.length - 1])) {\n                id = expr.id;\n                paren = paren || expr.paren;\n            }\n        }\n        switch (id) {\n        case \"=\":\n        case \"+=\":\n        case \"-=\":\n        case \"*=\":\n        case \"%=\":\n        case \"&=\":\n        case \"|=\":\n        case \"^=\":\n        case \"/=\":\n            if (!paren && !state.option.boss) {\n                warning(\"W084\");\n            }\n        }\n    }\n\n\n    (function (x) {\n        x.nud = function (isclassdef) {\n            var b, f, i, p, t, g;\n            var props = {}; // All properties, including accessors\n            var tag = \"\";\n\n            function saveProperty(name, tkn) {\n                if (props[name] && _.has(props, name))\n                    warning(\"W075\", state.tokens.next, i);\n                else\n                    props[name] = {};\n\n                props[name].basic = true;\n                props[name].basictkn = tkn;\n            }\n\n            function saveSetter(name, tkn) {\n                if (props[name] && _.has(props, name)) {\n                    if (props[name].basic || props[name].setter)\n                        warning(\"W075\", state.tokens.next, i);\n                } else {\n                    props[name] = {};\n                }\n\n                props[name].setter = true;\n                props[name].setterToken = tkn;\n            }\n\n            function saveGetter(name) {\n                if (props[name] && _.has(props, name)) {\n                    if (props[name].basic || props[name].getter)\n                        warning(\"W075\", state.tokens.next, i);\n                } else {\n                    props[name] = {};\n                }\n\n                props[name].getter = true;\n                props[name].getterToken = state.tokens.curr;\n            }\n\n            b = state.tokens.curr.line !== state.tokens.next.line;\n            if (b) {\n                indent += state.option.indent;\n                if (state.tokens.next.from === indent + state.option.indent) {\n                    indent += state.option.indent;\n                }\n            }\n\n            for (;;) {\n                if (state.tokens.next.id === \"}\") {\n                    break;\n                }\n\n                if (b) {\n                    indentation();\n                }\n\n                if (isclassdef && state.tokens.next.value === \"static\") {\n                    advance(\"static\");\n                    tag = \"static \";\n                }\n\n                if (state.tokens.next.value === \"get\" && peek().id !== \":\") {\n                    advance(\"get\");\n\n                    if (!state.option.inES5(!isclassdef)) {\n                        error(\"E034\");\n                    }\n\n                    i = property_name();\n                    if (!i) {\n                        error(\"E035\");\n                    }\n\n                    // It is a Syntax Error if PropName of MethodDefinition is\n                    // \"constructor\" and SpecialMethod of MethodDefinition is true.\n                    if (isclassdef && i === \"constructor\") {\n                        error(\"E049\", state.tokens.next, \"class getter method\", i);\n                    }\n\n                    saveGetter(tag + i);\n                    t = state.tokens.next;\n                    adjacent(state.tokens.curr, state.tokens.next);\n                    f = doFunction();\n                    p = f[\"(params)\"];\n\n                    if (p) {\n                        warning(\"W076\", t, p[0], i);\n                    }\n\n                    adjacent(state.tokens.curr, state.tokens.next);\n                } else if (state.tokens.next.value === \"set\" && peek().id !== \":\") {\n                    advance(\"set\");\n\n                    if (!state.option.inES5(!isclassdef)) {\n                        error(\"E034\");\n                    }\n\n                    i = property_name();\n                    if (!i) {\n                        error(\"E035\");\n                    }\n\n                    // It is a Syntax Error if PropName of MethodDefinition is\n                    // \"constructor\" and SpecialMethod of MethodDefinition is true.\n                    if (isclassdef && i === \"constructor\") {\n                        error(\"E049\", state.tokens.next, \"class setter method\", i);\n                    }\n\n                    saveSetter(tag + i, state.tokens.next);\n                    t = state.tokens.next;\n                    adjacent(state.tokens.curr, state.tokens.next);\n                    f = doFunction();\n                    p = f[\"(params)\"];\n\n                    if (!p || p.length !== 1) {\n                        warning(\"W077\", t, i);\n                    }\n                } else {\n                    g = false;\n                    if (state.tokens.next.value === \"*\" && state.tokens.next.type === \"(punctuator)\") {\n                        if (!state.option.inESNext()) {\n                            warning(\"W104\", state.tokens.next, \"generator functions\");\n                        }\n                        advance(\"*\");\n                        g = true;\n                    }\n                    i = property_name();\n                    saveProperty(tag + i, state.tokens.next);\n\n                    if (typeof i !== \"string\") {\n                        break;\n                    }\n\n                    if (state.tokens.next.value === \"(\") {\n                        if (!state.option.inESNext()) {\n                            warning(\"W104\", state.tokens.curr, \"concise methods\");\n                        }\n                        doFunction(i, undefined, g);\n                    } else if (!isclassdef) {\n                        advance(\":\");\n                        nonadjacent(state.tokens.curr, state.tokens.next);\n                        expression(10);\n                    }\n                }\n                // It is a Syntax Error if PropName of MethodDefinition is \"prototype\".\n                if (isclassdef && i === \"prototype\") {\n                    error(\"E049\", state.tokens.next, \"class method\", i);\n                }\n\n                countMember(i);\n                if (isclassdef) {\n                    tag = \"\";\n                    continue;\n                }\n                if (state.tokens.next.id === \",\") {\n                    comma({ allowTrailing: true, property: true });\n                    if (state.tokens.next.id === \",\") {\n                        warning(\"W070\", state.tokens.curr);\n                    } else if (state.tokens.next.id === \"}\" && !state.option.inES5(true)) {\n                        warning(\"W070\", state.tokens.curr);\n                    }\n                } else {\n                    break;\n                }\n            }\n            if (b) {\n                indent -= state.option.indent;\n                indentation();\n            }\n            advance(\"}\", this);\n\n            // Check for lonely setters if in the ES5 mode.\n            if (state.option.inES5()) {\n                for (var name in props) {\n                    if (_.has(props, name) && props[name].setter && !props[name].getter) {\n                        warning(\"W078\", props[name].setterToken);\n                    }\n                }\n            }\n            return this;\n        };\n        x.fud = function () {\n            error(\"E036\", state.tokens.curr);\n        };\n    }(delim(\"{\")));\n\n    function destructuringExpression() {\n        var id, ids;\n        var identifiers = [];\n        if (!state.option.inESNext()) {\n            warning(\"W104\", state.tokens.curr, \"destructuring expression\");\n        }\n        var nextInnerDE = function () {\n            var ident;\n            if (_.contains([\"[\", \"{\"], state.tokens.next.value)) {\n                ids = destructuringExpression();\n                for (var id in ids) {\n                    id = ids[id];\n                    identifiers.push({ id: id.id, token: id.token });\n                }\n            } else if (state.tokens.next.value === \",\") {\n                identifiers.push({ id: null, token: state.tokens.curr });\n            } else {\n                ident = identifier();\n                if (ident)\n                    identifiers.push({ id: ident, token: state.tokens.curr });\n            }\n        };\n        if (state.tokens.next.value === \"[\") {\n            advance(\"[\");\n            nextInnerDE();\n            while (state.tokens.next.value !== \"]\") {\n                advance(\",\");\n                nextInnerDE();\n            }\n            advance(\"]\");\n        } else if (state.tokens.next.value === \"{\") {\n            advance(\"{\");\n            id = identifier();\n            if (state.tokens.next.value === \":\") {\n                advance(\":\");\n                nextInnerDE();\n            } else {\n                identifiers.push({ id: id, token: state.tokens.curr });\n            }\n            while (state.tokens.next.value !== \"}\") {\n                advance(\",\");\n                id = identifier();\n                if (state.tokens.next.value === \":\") {\n                    advance(\":\");\n                    nextInnerDE();\n                } else {\n                    identifiers.push({ id: id, token: state.tokens.curr });\n                }\n            }\n            advance(\"}\");\n        }\n        return identifiers;\n    }\n    function destructuringExpressionMatch(tokens, value) {\n        if (value.first) {\n            _.zip(tokens, value.first).forEach(function (val) {\n                var token = val[0];\n                var value = val[1];\n                if (token && value) {\n                    token.first = value;\n                } else if (token && token.first && !value) {\n                    warning(\"W080\", token.first, token.first.value);\n                } /* else {\n                    XXX value is discarded: wouldn't it need a warning ?\n                } */\n            });\n        }\n    }\n\n    var conststatement = stmt(\"const\", function (prefix) {\n        var tokens, value;\n        // state variable to know if it is a lone identifier, or a destructuring statement.\n        var lone;\n\n        if (!state.option.inESNext()) {\n            warning(\"W104\", state.tokens.curr, \"const\");\n        }\n\n        this.first = [];\n        for (;;) {\n            var names = [];\n            nonadjacent(state.tokens.curr, state.tokens.next);\n            if (_.contains([\"{\", \"[\"], state.tokens.next.value)) {\n                tokens = destructuringExpression();\n                lone = false;\n            } else {\n                tokens = [ { id: identifier(), token: state.tokens.curr } ];\n                lone = true;\n            }\n            for (var t in tokens) {\n                t = tokens[t];\n                if (funct[t.id] === \"const\") {\n                    warning(\"E011\", null, t.id);\n                }\n                if (funct[\"(global)\"] && predefined[t.id] === false) {\n                    warning(\"W079\", t.token, t.id);\n                }\n                if (t.id) {\n                    addlabel(t.id, \"const\");\n                    names.push(t.token);\n                }\n            }\n            if (prefix) {\n                break;\n            }\n\n            this.first = this.first.concat(names);\n\n            if (state.tokens.next.id !== \"=\") {\n                warning(\"E012\", state.tokens.curr, state.tokens.curr.value);\n            }\n\n            if (state.tokens.next.id === \"=\") {\n                nonadjacent(state.tokens.curr, state.tokens.next);\n                advance(\"=\");\n                nonadjacent(state.tokens.curr, state.tokens.next);\n                if (state.tokens.next.id === \"undefined\") {\n                    warning(\"W080\", state.tokens.prev, state.tokens.prev.value);\n                }\n                if (peek(0).id === \"=\" && state.tokens.next.identifier) {\n                    warning(\"W120\", state.tokens.next, state.tokens.next.value);\n                }\n                value = expression(10);\n                if (lone) {\n                    tokens[0].first = value;\n                } else {\n                    destructuringExpressionMatch(names, value);\n                }\n            }\n\n            if (state.tokens.next.id !== \",\") {\n                break;\n            }\n            comma();\n        }\n        return this;\n    });\n    conststatement.exps = true;\n    var varstatement = stmt(\"var\", function (prefix) {\n        // JavaScript does not have block scope. It only has function scope. So,\n        // declaring a variable in a block can have unexpected consequences.\n        var tokens, lone, value;\n\n        if (funct[\"(onevar)\"] && state.option.onevar) {\n            warning(\"W081\");\n        } else if (!funct[\"(global)\"]) {\n            funct[\"(onevar)\"] = true;\n        }\n\n        this.first = [];\n        for (;;) {\n            var names = [];\n            nonadjacent(state.tokens.curr, state.tokens.next);\n            if (_.contains([\"{\", \"[\"], state.tokens.next.value)) {\n                tokens = destructuringExpression();\n                lone = false;\n            } else {\n                tokens = [ { id: identifier(), token: state.tokens.curr } ];\n                lone = true;\n            }\n            for (var t in tokens) {\n                t = tokens[t];\n                if (state.option.inESNext() && funct[t.id] === \"const\") {\n                    warning(\"E011\", null, t.id);\n                }\n                if (funct[\"(global)\"] && predefined[t.id] === false) {\n                    warning(\"W079\", t.token, t.id);\n                }\n                if (t.id) {\n                    addlabel(t.id, \"unused\", t.token);\n                    names.push(t.token);\n                }\n            }\n            if (prefix) {\n                break;\n            }\n\n            this.first = this.first.concat(names);\n\n            if (state.tokens.next.id === \"=\") {\n                nonadjacent(state.tokens.curr, state.tokens.next);\n                advance(\"=\");\n                nonadjacent(state.tokens.curr, state.tokens.next);\n                if (state.tokens.next.id === \"undefined\") {\n                    warning(\"W080\", state.tokens.prev, state.tokens.prev.value);\n                }\n                if (peek(0).id === \"=\" && state.tokens.next.identifier) {\n                    warning(\"W120\", state.tokens.next, state.tokens.next.value);\n                }\n                value = expression(10);\n                if (lone) {\n                    tokens[0].first = value;\n                } else {\n                    destructuringExpressionMatch(names, value);\n                }\n            }\n\n            if (state.tokens.next.id !== \",\") {\n                break;\n            }\n            comma();\n        }\n        return this;\n    });\n    varstatement.exps = true;\n    var letstatement = stmt(\"let\", function (prefix) {\n        var tokens, lone, value, letblock;\n\n        if (!state.option.inESNext()) {\n            warning(\"W104\", state.tokens.curr, \"let\");\n        }\n\n        if (state.tokens.next.value === \"(\") {\n            if (!state.option.inMoz(true)) {\n                warning(\"W118\", state.tokens.next, \"let block\");\n            }\n            advance(\"(\");\n            funct[\"(blockscope)\"].stack();\n            letblock = true;\n        } else if (funct[\"(nolet)\"]) {\n            error(\"E048\", state.tokens.curr);\n        }\n\n        if (funct[\"(onevar)\"] && state.option.onevar) {\n            warning(\"W081\");\n        } else if (!funct[\"(global)\"]) {\n            funct[\"(onevar)\"] = true;\n        }\n\n        this.first = [];\n        for (;;) {\n            var names = [];\n            nonadjacent(state.tokens.curr, state.tokens.next);\n            if (_.contains([\"{\", \"[\"], state.tokens.next.value)) {\n                tokens = destructuringExpression();\n                lone = false;\n            } else {\n                tokens = [ { id: identifier(), token: state.tokens.curr.value } ];\n                lone = true;\n            }\n            for (var t in tokens) {\n                t = tokens[t];\n                if (state.option.inESNext() && funct[t.id] === \"const\") {\n                    warning(\"E011\", null, t.id);\n                }\n                if (funct[\"(global)\"] && predefined[t.id] === false) {\n                    warning(\"W079\", t.token, t.id);\n                }\n                if (t.id && !funct[\"(nolet)\"]) {\n                    addlabel(t.id, \"unused\", t.token, true);\n                    names.push(t.token);\n                }\n            }\n            if (prefix) {\n                break;\n            }\n\n            this.first = this.first.concat(names);\n\n            if (state.tokens.next.id === \"=\") {\n                nonadjacent(state.tokens.curr, state.tokens.next);\n                advance(\"=\");\n                nonadjacent(state.tokens.curr, state.tokens.next);\n                if (state.tokens.next.id === \"undefined\") {\n                    warning(\"W080\", state.tokens.prev, state.tokens.prev.value);\n                }\n                if (peek(0).id === \"=\" && state.tokens.next.identifier) {\n                    warning(\"W120\", state.tokens.next, state.tokens.next.value);\n                }\n                value = expression(10);\n                if (lone) {\n                    tokens[0].first = value;\n                } else {\n                    destructuringExpressionMatch(names, value);\n                }\n            }\n\n            if (state.tokens.next.id !== \",\") {\n                break;\n            }\n            comma();\n        }\n        if (letblock) {\n            advance(\")\");\n            block(true, true);\n            this.block = true;\n            funct[\"(blockscope)\"].unstack();\n        }\n\n        return this;\n    });\n    letstatement.exps = true;\n\n    blockstmt(\"class\", function () {\n        return classdef.call(this, true);\n    });\n\n    function classdef(stmt) {\n        /*jshint validthis:true */\n        if (!state.option.inESNext()) {\n            warning(\"W104\", state.tokens.curr, \"class\");\n        }\n        if (stmt) {\n            // BindingIdentifier\n            this.name = identifier();\n            addlabel(this.name, \"unused\", state.tokens.curr);\n        } else if (state.tokens.next.identifier && state.tokens.next.value !== \"extends\") {\n            // BindingIdentifier(opt)\n            this.name = identifier();\n        }\n        classtail(this);\n        return this;\n    }\n\n    function classtail(c) {\n        var strictness = state.directive[\"use strict\"];\n\n        // ClassHeritage(opt)\n        if (state.tokens.next.value === \"extends\") {\n            advance(\"extends\");\n            c.heritage = expression(10);\n        }\n\n        // A ClassBody is always strict code.\n        state.directive[\"use strict\"] = true;\n        advance(\"{\");\n        // ClassBody(opt)\n        c.body = state.syntax[\"{\"].nud(true);\n        state.directive[\"use strict\"] = strictness;\n    }\n\n    blockstmt(\"function\", function () {\n        var generator = false;\n        if (state.tokens.next.value === \"*\") {\n            advance(\"*\");\n            if (state.option.inESNext(true)) {\n                generator = true;\n            } else {\n                warning(\"W119\", state.tokens.curr, \"function*\");\n            }\n        }\n        if (inblock) {\n            warning(\"W082\", state.tokens.curr);\n\n        }\n        var i = identifier();\n        if (funct[i] === \"const\") {\n            warning(\"E011\", null, i);\n        }\n        adjacent(state.tokens.curr, state.tokens.next);\n        addlabel(i, \"unction\", state.tokens.curr);\n\n        doFunction(i, { statement: true }, generator);\n        if (state.tokens.next.id === \"(\" && state.tokens.next.line === state.tokens.curr.line) {\n            error(\"E039\");\n        }\n        return this;\n    });\n\n    prefix(\"function\", function () {\n        var generator = false;\n        if (state.tokens.next.value === \"*\") {\n            if (!state.option.inESNext()) {\n                warning(\"W119\", state.tokens.curr, \"function*\");\n            }\n            advance(\"*\");\n            generator = true;\n        }\n        var i = optionalidentifier();\n        if (i || state.option.gcl) {\n            adjacent(state.tokens.curr, state.tokens.next);\n        } else {\n            nonadjacent(state.tokens.curr, state.tokens.next);\n        }\n        doFunction(i, undefined, generator);\n        if (!state.option.loopfunc && funct[\"(loopage)\"]) {\n            warning(\"W083\");\n        }\n        return this;\n    });\n\n    blockstmt(\"if\", function () {\n        var t = state.tokens.next;\n        increaseComplexityCount();\n        state.condition = true;\n        advance(\"(\");\n        nonadjacent(this, t);\n        nospace();\n        checkCondAssignment(expression(0));\n        advance(\")\", t);\n        state.condition = false;\n        nospace(state.tokens.prev, state.tokens.curr);\n        block(true, true);\n        if (state.tokens.next.id === \"else\") {\n            nonadjacent(state.tokens.curr, state.tokens.next);\n            advance(\"else\");\n            if (state.tokens.next.id === \"if\" || state.tokens.next.id === \"switch\") {\n                statement(true);\n            } else {\n                block(true, true);\n            }\n        }\n        return this;\n    });\n\n    blockstmt(\"try\", function () {\n        var b;\n\n        function doCatch() {\n            var oldScope = scope;\n            var e;\n\n            advance(\"catch\");\n            nonadjacent(state.tokens.curr, state.tokens.next);\n            advance(\"(\");\n\n            scope = Object.create(oldScope);\n\n            e = state.tokens.next.value;\n            if (state.tokens.next.type !== \"(identifier)\") {\n                e = null;\n                warning(\"E030\", state.tokens.next, e);\n            }\n\n            advance();\n\n            funct = {\n                \"(name)\"     : \"(catch)\",\n                \"(line)\"     : state.tokens.next.line,\n                \"(character)\": state.tokens.next.character,\n                \"(context)\"  : funct,\n                \"(breakage)\" : funct[\"(breakage)\"],\n                \"(loopage)\"  : funct[\"(loopage)\"],\n                \"(scope)\"    : scope,\n                \"(statement)\": false,\n                \"(metrics)\"  : createMetrics(state.tokens.next),\n                \"(catch)\"    : true,\n                \"(tokens)\"   : {},\n                \"(blockscope)\": funct[\"(blockscope)\"],\n                \"(comparray)\": funct[\"(comparray)\"]\n            };\n\n            if (e) {\n                addlabel(e, \"exception\");\n            }\n\n            if (state.tokens.next.value === \"if\") {\n                if (!state.option.inMoz(true)) {\n                    warning(\"W118\", state.tokens.curr, \"catch filter\");\n                }\n                advance(\"if\");\n                expression(0);\n            }\n\n            advance(\")\");\n\n            state.tokens.curr.funct = funct;\n            functions.push(funct);\n\n            block(false);\n\n            scope = oldScope;\n\n            funct[\"(last)\"] = state.tokens.curr.line;\n            funct[\"(lastcharacter)\"] = state.tokens.curr.character;\n            funct = funct[\"(context)\"];\n        }\n\n        block(false);\n\n        while (state.tokens.next.id === \"catch\") {\n            increaseComplexityCount();\n            if (b && (!state.option.inMoz(true))) {\n                warning(\"W118\", state.tokens.next, \"multiple catch blocks\");\n            }\n            doCatch();\n            b = true;\n        }\n\n        if (state.tokens.next.id === \"finally\") {\n            advance(\"finally\");\n            block(false);\n            return;\n        }\n\n        if (!b) {\n            error(\"E021\", state.tokens.next, \"catch\", state.tokens.next.value);\n        }\n\n        return this;\n    });\n\n    blockstmt(\"while\", function () {\n        var t = state.tokens.next;\n        funct[\"(breakage)\"] += 1;\n        funct[\"(loopage)\"] += 1;\n        increaseComplexityCount();\n        advance(\"(\");\n        nonadjacent(this, t);\n        nospace();\n        checkCondAssignment(expression(0));\n        advance(\")\", t);\n        nospace(state.tokens.prev, state.tokens.curr);\n        block(true, true);\n        funct[\"(breakage)\"] -= 1;\n        funct[\"(loopage)\"] -= 1;\n        return this;\n    }).labelled = true;\n\n    blockstmt(\"with\", function () {\n        var t = state.tokens.next;\n        if (state.directive[\"use strict\"]) {\n            error(\"E010\", state.tokens.curr);\n        } else if (!state.option.withstmt) {\n            warning(\"W085\", state.tokens.curr);\n        }\n\n        advance(\"(\");\n        nonadjacent(this, t);\n        nospace();\n        expression(0);\n        advance(\")\", t);\n        nospace(state.tokens.prev, state.tokens.curr);\n        block(true, true);\n\n        return this;\n    });\n\n    blockstmt(\"switch\", function () {\n        var t = state.tokens.next,\n            g = false;\n        funct[\"(breakage)\"] += 1;\n        advance(\"(\");\n        nonadjacent(this, t);\n        nospace();\n        checkCondAssignment(expression(0));\n        advance(\")\", t);\n        nospace(state.tokens.prev, state.tokens.curr);\n        nonadjacent(state.tokens.curr, state.tokens.next);\n        t = state.tokens.next;\n        advance(\"{\");\n        nonadjacent(state.tokens.curr, state.tokens.next);\n        indent += state.option.indent;\n        this.cases = [];\n\n        for (;;) {\n            switch (state.tokens.next.id) {\n            case \"case\":\n                switch (funct[\"(verb)\"]) {\n                case \"yield\":\n                case \"break\":\n                case \"case\":\n                case \"continue\":\n                case \"return\":\n                case \"switch\":\n                case \"throw\":\n                    break;\n                default:\n                    // You can tell JSHint that you don't use break intentionally by\n                    // adding a comment /* falls through */ on a line just before\n                    // the next `case`.\n                    if (!reg.fallsThrough.test(state.lines[state.tokens.next.line - 2])) {\n                        warning(\"W086\", state.tokens.curr, \"case\");\n                    }\n                }\n                indentation(-state.option.indent);\n                advance(\"case\");\n                this.cases.push(expression(20));\n                increaseComplexityCount();\n                g = true;\n                advance(\":\");\n                funct[\"(verb)\"] = \"case\";\n                break;\n            case \"default\":\n                switch (funct[\"(verb)\"]) {\n                case \"yield\":\n                case \"break\":\n                case \"continue\":\n                case \"return\":\n                case \"throw\":\n                    break;\n                default:\n                    // Do not display a warning if 'default' is the first statement or if\n                    // there is a special /* falls through */ comment.\n                    if (this.cases.length) {\n                        if (!reg.fallsThrough.test(state.lines[state.tokens.next.line - 2])) {\n                            warning(\"W086\", state.tokens.curr, \"default\");\n                        }\n                    }\n                }\n                indentation(-state.option.indent);\n                advance(\"default\");\n                g = true;\n                advance(\":\");\n                break;\n            case \"}\":\n                indent -= state.option.indent;\n                indentation();\n                advance(\"}\", t);\n                funct[\"(breakage)\"] -= 1;\n                funct[\"(verb)\"] = undefined;\n                return;\n            case \"(end)\":\n                error(\"E023\", state.tokens.next, \"}\");\n                return;\n            default:\n                if (g) {\n                    switch (state.tokens.curr.id) {\n                    case \",\":\n                        error(\"E040\");\n                        return;\n                    case \":\":\n                        g = false;\n                        statements();\n                        break;\n                    default:\n                        error(\"E025\", state.tokens.curr);\n                        return;\n                    }\n                } else {\n                    if (state.tokens.curr.id === \":\") {\n                        advance(\":\");\n                        error(\"E024\", state.tokens.curr, \":\");\n                        statements();\n                    } else {\n                        error(\"E021\", state.tokens.next, \"case\", state.tokens.next.value);\n                        return;\n                    }\n                }\n            }\n        }\n    }).labelled = true;\n\n    stmt(\"debugger\", function () {\n        if (!state.option.debug) {\n            warning(\"W087\");\n        }\n        return this;\n    }).exps = true;\n\n    (function () {\n        var x = stmt(\"do\", function () {\n            funct[\"(breakage)\"] += 1;\n            funct[\"(loopage)\"] += 1;\n            increaseComplexityCount();\n\n            this.first = block(true, true);\n            advance(\"while\");\n            var t = state.tokens.next;\n            nonadjacent(state.tokens.curr, t);\n            advance(\"(\");\n            nospace();\n            checkCondAssignment(expression(0));\n            advance(\")\", t);\n            nospace(state.tokens.prev, state.tokens.curr);\n            funct[\"(breakage)\"] -= 1;\n            funct[\"(loopage)\"] -= 1;\n            return this;\n        });\n        x.labelled = true;\n        x.exps = true;\n    }());\n\n    blockstmt(\"for\", function () {\n        var s, t = state.tokens.next;\n        var letscope = false;\n        var foreachtok = null;\n\n        if (t.value === \"each\") {\n            foreachtok = t;\n            advance(\"each\");\n            if (!state.option.inMoz(true)) {\n                warning(\"W118\", state.tokens.curr, \"for each\");\n            }\n        }\n\n        funct[\"(breakage)\"] += 1;\n        funct[\"(loopage)\"] += 1;\n        increaseComplexityCount();\n        advance(\"(\");\n        nonadjacent(this, t);\n        nospace();\n\n        // what kind of for(â€¦) statement it is? for(â€¦ofâ€¦)? for(â€¦inâ€¦)? for(â€¦;â€¦;â€¦)?\n        var nextop; // contains the token of the \"in\" or \"of\" operator\n        var i = 0;\n        var inof = [\"in\", \"of\"];\n        do {\n            nextop = peek(i);\n            ++i;\n        } while (!_.contains(inof, nextop.value) && nextop.value !== \";\" &&\n                    nextop.type !== \"(end)\");\n\n        // if we're in a for (â€¦ in|of â€¦) statement\n        if (_.contains(inof, nextop.value)) {\n            if (!state.option.inESNext() && nextop.value === \"of\") {\n                error(\"W104\", nextop, \"for of\");\n            }\n            if (state.tokens.next.id === \"var\") {\n                advance(\"var\");\n                state.syntax[\"var\"].fud.call(state.syntax[\"var\"].fud, true);\n            } else if (state.tokens.next.id === \"let\") {\n                advance(\"let\");\n                // create a new block scope\n                letscope = true;\n                funct[\"(blockscope)\"].stack();\n                state.syntax[\"let\"].fud.call(state.syntax[\"let\"].fud, true);\n            } else {\n                switch (funct[state.tokens.next.value]) {\n                case \"unused\":\n                    funct[state.tokens.next.value] = \"var\";\n                    break;\n                case \"var\":\n                    break;\n                default:\n                    if (!funct[\"(blockscope)\"].getlabel(state.tokens.next.value))\n                        warning(\"W088\", state.tokens.next, state.tokens.next.value);\n                }\n                advance();\n            }\n            advance(nextop.value);\n            expression(20);\n            advance(\")\", t);\n            s = block(true, true);\n            if (state.option.forin && s && (s.length > 1 || typeof s[0] !== \"object\" ||\n                    s[0].value !== \"if\")) {\n                warning(\"W089\", this);\n            }\n            funct[\"(breakage)\"] -= 1;\n            funct[\"(loopage)\"] -= 1;\n        } else {\n            if (foreachtok) {\n                error(\"E045\", foreachtok);\n            }\n            if (state.tokens.next.id !== \";\") {\n                if (state.tokens.next.id === \"var\") {\n                    advance(\"var\");\n                    state.syntax[\"var\"].fud.call(state.syntax[\"var\"].fud);\n                } else if (state.tokens.next.id === \"let\") {\n                    advance(\"let\");\n                    // create a new block scope\n                    letscope = true;\n                    funct[\"(blockscope)\"].stack();\n                    state.syntax[\"let\"].fud.call(state.syntax[\"let\"].fud);\n                } else {\n                    for (;;) {\n                        expression(0, \"for\");\n                        if (state.tokens.next.id !== \",\") {\n                            break;\n                        }\n                        comma();\n                    }\n                }\n            }\n            nolinebreak(state.tokens.curr);\n            advance(\";\");\n            if (state.tokens.next.id !== \";\") {\n                checkCondAssignment(expression(0));\n            }\n            nolinebreak(state.tokens.curr);\n            advance(\";\");\n            if (state.tokens.next.id === \";\") {\n                error(\"E021\", state.tokens.next, \")\", \";\");\n            }\n            if (state.tokens.next.id !== \")\") {\n                for (;;) {\n                    expression(0, \"for\");\n                    if (state.tokens.next.id !== \",\") {\n                        break;\n                    }\n                    comma();\n                }\n            }\n            advance(\")\", t);\n            nospace(state.tokens.prev, state.tokens.curr);\n            block(true, true);\n            funct[\"(breakage)\"] -= 1;\n            funct[\"(loopage)\"] -= 1;\n\n        }\n        // unstack loop blockscope\n        if (letscope) {\n            funct[\"(blockscope)\"].unstack();\n        }\n        return this;\n    }).labelled = true;\n\n\n    stmt(\"break\", function () {\n        var v = state.tokens.next.value;\n\n        if (funct[\"(breakage)\"] === 0)\n            warning(\"W052\", state.tokens.next, this.value);\n\n        if (!state.option.asi)\n            nolinebreak(this);\n\n        if (state.tokens.next.id !== \";\" && !state.tokens.next.reach) {\n            if (state.tokens.curr.line === state.tokens.next.line) {\n                if (funct[v] !== \"label\") {\n                    warning(\"W090\", state.tokens.next, v);\n                } else if (scope[v] !== funct) {\n                    warning(\"W091\", state.tokens.next, v);\n                }\n                this.first = state.tokens.next;\n                advance();\n            }\n        }\n        reachable(\"break\");\n        return this;\n    }).exps = true;\n\n\n    stmt(\"continue\", function () {\n        var v = state.tokens.next.value;\n\n        if (funct[\"(breakage)\"] === 0)\n            warning(\"W052\", state.tokens.next, this.value);\n\n        if (!state.option.asi)\n            nolinebreak(this);\n\n        if (state.tokens.next.id !== \";\" && !state.tokens.next.reach) {\n            if (state.tokens.curr.line === state.tokens.next.line) {\n                if (funct[v] !== \"label\") {\n                    warning(\"W090\", state.tokens.next, v);\n                } else if (scope[v] !== funct) {\n                    warning(\"W091\", state.tokens.next, v);\n                }\n                this.first = state.tokens.next;\n                advance();\n            }\n        } else if (!funct[\"(loopage)\"]) {\n            warning(\"W052\", state.tokens.next, this.value);\n        }\n        reachable(\"continue\");\n        return this;\n    }).exps = true;\n\n\n    stmt(\"return\", function () {\n        if (this.line === state.tokens.next.line) {\n            if (state.tokens.next.id === \"(regexp)\")\n                warning(\"W092\");\n\n            if (state.tokens.next.id !== \";\" && !state.tokens.next.reach) {\n                nonadjacent(state.tokens.curr, state.tokens.next);\n                this.first = expression(0);\n\n                if (this.first &&\n                        this.first.type === \"(punctuator)\" && this.first.value === \"=\" && !state.option.boss) {\n                    warningAt(\"W093\", this.first.line, this.first.character);\n                }\n            }\n        } else {\n            if (state.tokens.next.type === \"(punctuator)\" &&\n                [\"[\", \"{\", \"+\", \"-\"].indexOf(state.tokens.next.value) > -1) {\n                nolinebreak(this); // always warn (Line breaking error)\n            }\n        }\n        reachable(\"return\");\n        return this;\n    }).exps = true;\n\n    (function (x) {\n        x.exps = true;\n        x.lbp = 25;\n    }(prefix(\"yield\", function () {\n        var prev = state.tokens.prev;\n        if (state.option.inESNext(true) && !funct[\"(generator)\"]) {\n            error(\"E046\", state.tokens.curr, \"yield\");\n        } else if (!state.option.inESNext()) {\n            warning(\"W104\", state.tokens.curr, \"yield\");\n        }\n        funct[\"(generator)\"] = \"yielded\";\n        if (this.line === state.tokens.next.line || !state.option.inMoz(true)) {\n            if (state.tokens.next.id === \"(regexp)\")\n                warning(\"W092\");\n\n            if (state.tokens.next.id !== \";\" && !state.tokens.next.reach && state.tokens.next.nud) {\n                nobreaknonadjacent(state.tokens.curr, state.tokens.next);\n                this.first = expression(10);\n\n                if (this.first.type === \"(punctuator)\" && this.first.value === \"=\" && !state.option.boss) {\n                    warningAt(\"W093\", this.first.line, this.first.character);\n                }\n            }\n\n            if (state.option.inMoz(true) && state.tokens.next.id !== \")\" &&\n                    (prev.lbp > 30 || (!prev.assign && !isEndOfExpr()) || prev.id === \"yield\")) {\n                error(\"E050\", this);\n            }\n        } else if (!state.option.asi) {\n            nolinebreak(this); // always warn (Line breaking error)\n        }\n        return this;\n    })));\n\n\n    stmt(\"throw\", function () {\n        nolinebreak(this);\n        nonadjacent(state.tokens.curr, state.tokens.next);\n        this.first = expression(20);\n        reachable(\"throw\");\n        return this;\n    }).exps = true;\n\n    stmt(\"import\", function () {\n        if (!state.option.inESNext()) {\n            warning(\"W119\", state.tokens.curr, \"import\");\n        }\n\n        if (state.tokens.next.identifier) {\n            this.name = identifier();\n            addlabel(this.name, \"unused\", state.tokens.curr);\n        } else {\n            advance(\"{\");\n            for (;;) {\n                var importName;\n                if (state.tokens.next.type === \"default\") {\n                    importName = \"default\";\n                    advance(\"default\");\n                } else {\n                    importName = identifier();\n                }\n                if (state.tokens.next.value === \"as\") {\n                    advance(\"as\");\n                    importName = identifier();\n                }\n                addlabel(importName, \"unused\", state.tokens.curr);\n\n                if (state.tokens.next.value === \",\") {\n                    advance(\",\");\n                } else if (state.tokens.next.value === \"}\") {\n                    advance(\"}\");\n                    break;\n                } else {\n                    error(\"E024\", state.tokens.next, state.tokens.next.value);\n                    break;\n                }\n            }\n        }\n\n        advance(\"from\");\n        advance(\"(string)\");\n        return this;\n    }).exps = true;\n\n    stmt(\"export\", function () {\n        if (!state.option.inESNext()) {\n            warning(\"W119\", state.tokens.curr, \"export\");\n        }\n\n        if (state.tokens.next.type === \"default\") {\n            advance(\"default\");\n            if (state.tokens.next.id === \"function\" || state.tokens.next.id === \"class\") {\n                this.block = true;\n            }\n            this.exportee = expression(10);\n\n            return this;\n        }\n\n        if (state.tokens.next.value === \"{\") {\n            advance(\"{\");\n            for (;;) {\n                identifier();\n\n                if (state.tokens.next.value === \",\") {\n                    advance(\",\");\n                } else if (state.tokens.next.value === \"}\") {\n                    advance(\"}\");\n                    break;\n                } else {\n                    error(\"E024\", state.tokens.next, state.tokens.next.value);\n                    break;\n                }\n            }\n            return this;\n        }\n\n        if (state.tokens.next.id === \"var\") {\n            advance(\"var\");\n            state.syntax[\"var\"].fud.call(state.syntax[\"var\"].fud);\n        } else if (state.tokens.next.id === \"let\") {\n            advance(\"let\");\n            state.syntax[\"let\"].fud.call(state.syntax[\"let\"].fud);\n        } else if (state.tokens.next.id === \"const\") {\n            advance(\"const\");\n            state.syntax[\"const\"].fud.call(state.syntax[\"const\"].fud);\n        } else if (state.tokens.next.id === \"function\") {\n            this.block = true;\n            advance(\"function\");\n            state.syntax[\"function\"].fud();\n        } else if (state.tokens.next.id === \"class\") {\n            this.block = true;\n            advance(\"class\");\n            state.syntax[\"class\"].fud();\n        } else {\n            error(\"E024\", state.tokens.next, state.tokens.next.value);\n        }\n\n        return this;\n    }).exps = true;\n\n    // Future Reserved Words\n\n    FutureReservedWord(\"abstract\");\n    FutureReservedWord(\"boolean\");\n    FutureReservedWord(\"byte\");\n    FutureReservedWord(\"char\");\n    FutureReservedWord(\"class\", { es5: true, nud: classdef });\n    FutureReservedWord(\"double\");\n    FutureReservedWord(\"enum\", { es5: true });\n    FutureReservedWord(\"export\", { es5: true });\n    FutureReservedWord(\"extends\", { es5: true });\n    FutureReservedWord(\"final\");\n    FutureReservedWord(\"float\");\n    FutureReservedWord(\"goto\");\n    FutureReservedWord(\"implements\", { es5: true, strictOnly: true });\n    FutureReservedWord(\"import\", { es5: true });\n    FutureReservedWord(\"int\");\n    FutureReservedWord(\"interface\", { es5: true, strictOnly: true });\n    FutureReservedWord(\"long\");\n    FutureReservedWord(\"native\");\n    FutureReservedWord(\"package\", { es5: true, strictOnly: true });\n    FutureReservedWord(\"private\", { es5: true, strictOnly: true });\n    FutureReservedWord(\"protected\", { es5: true, strictOnly: true });\n    FutureReservedWord(\"public\", { es5: true, strictOnly: true });\n    FutureReservedWord(\"short\");\n    FutureReservedWord(\"static\", { es5: true, strictOnly: true });\n    FutureReservedWord(\"super\", { es5: true });\n    FutureReservedWord(\"synchronized\");\n    FutureReservedWord(\"throws\");\n    FutureReservedWord(\"transient\");\n    FutureReservedWord(\"volatile\");\n\n    // this function is used to determine wether a squarebracket or a curlybracket\n    // expression is a comprehension array, destructuring assignment or a json value.\n\n    var lookupBlockType = function () {\n        var pn, pn1;\n        var i = 0;\n        var bracketStack = 0;\n        var ret = {};\n        if (_.contains([\"[\", \"{\"], state.tokens.curr.value))\n            bracketStack += 1;\n        if (_.contains([\"[\", \"{\"], state.tokens.next.value))\n            bracketStack += 1;\n        if (_.contains([\"]\", \"}\"], state.tokens.next.value))\n            bracketStack -= 1;\n        do {\n            pn = peek(i);\n            pn1 = peek(i + 1);\n            i = i + 1;\n            if (_.contains([\"[\", \"{\"], pn.value)) {\n                bracketStack += 1;\n            } else if (_.contains([\"]\", \"}\"], pn.value)) {\n                bracketStack -= 1;\n            }\n            if (pn.identifier && pn.value === \"for\" && bracketStack === 1) {\n                ret.isCompArray = true;\n                ret.notJson = true;\n                break;\n            }\n            if (_.contains([\"}\", \"]\"], pn.value) && pn1.value === \"=\") {\n                ret.isDestAssign = true;\n                ret.notJson = true;\n                break;\n            }\n            if (pn.value === \";\") {\n                ret.isBlock = true;\n                ret.notJson = true;\n            }\n        } while (bracketStack > 0 && pn.id !== \"(end)\" && i < 15);\n        return ret;\n    };\n\n    // Check whether this function has been reached for a destructuring assign with undeclared values\n    function destructuringAssignOrJsonValue() {\n        // lookup for the assignment (esnext only)\n        // if it has semicolons, it is a block, so go parse it as a block\n        // or it's not a block, but there are assignments, check for undeclared variables\n\n        var block = lookupBlockType();\n        if (block.notJson) {\n            if (!state.option.inESNext() && block.isDestAssign) {\n                warning(\"W104\", state.tokens.curr, \"destructuring assignment\");\n            }\n            statements();\n        // otherwise parse json value\n        } else {\n            state.option.laxbreak = true;\n            state.jsonMode = true;\n            jsonValue();\n        }\n    }\n\n    // array comprehension parsing function\n    // parses and defines the three states of the list comprehension in order\n    // to avoid defining global variables, but keeping them to the list comprehension scope\n    // only. The order of the states are as follows:\n    //  * \"use\" which will be the returned iterative part of the list comprehension\n    //  * \"define\" which will define the variables local to the list comprehension\n    //  * \"filter\" which will help filter out values\n\n    var arrayComprehension = function () {\n        var CompArray = function () {\n            this.mode = \"use\";\n            this.variables = [];\n        };\n        var _carrays = [];\n        var _current;\n        function declare(v) {\n            var l = _current.variables.filter(function (elt) {\n                // if it has, change its undef state\n                if (elt.value === v) {\n                    elt.undef = false;\n                    return v;\n                }\n            }).length;\n            return l !== 0;\n        }\n        function use(v) {\n            var l = _current.variables.filter(function (elt) {\n                // and if it has been defined\n                if (elt.value === v && !elt.undef) {\n                    if (elt.unused === true) {\n                        elt.unused = false;\n                    }\n                    return v;\n                }\n            }).length;\n            // otherwise we warn about it\n            return (l === 0);\n        }\n        return {stack: function () {\n                    _current = new CompArray();\n                    _carrays.push(_current);\n                },\n                unstack: function () {\n                    _current.variables.filter(function (v) {\n                        if (v.unused)\n                            warning(\"W098\", v.token, v.value);\n                        if (v.undef)\n                            isundef(v.funct, \"W117\", v.token, v.value);\n                    });\n                    _carrays.splice(_carrays[_carrays.length - 1], 1);\n                    _current = _carrays[_carrays.length - 1];\n                },\n                setState: function (s) {\n                    if (_.contains([\"use\", \"define\", \"filter\"], s))\n                        _current.mode = s;\n                },\n                check: function (v) {\n                    // When we are in \"use\" state of the list comp, we enqueue that var\n                    if (_current && _current.mode === \"use\") {\n                        _current.variables.push({funct: funct,\n                                                    token: state.tokens.curr,\n                                                    value: v,\n                                                    undef: true,\n                                                    unused: false});\n                        return true;\n                    // When we are in \"define\" state of the list comp,\n                    } else if (_current && _current.mode === \"define\") {\n                        // check if the variable has been used previously\n                        if (!declare(v)) {\n                            _current.variables.push({funct: funct,\n                                                        token: state.tokens.curr,\n                                                        value: v,\n                                                        undef: false,\n                                                        unused: true});\n                        }\n                        return true;\n                    // When we are in \"filter\" state,\n                    } else if (_current && _current.mode === \"filter\") {\n                        // we check whether current variable has been declared\n                        if (use(v)) {\n                            // if not we warn about it\n                            isundef(funct, \"W117\", state.tokens.curr, v);\n                        }\n                        return true;\n                    }\n                    return false;\n                }\n                };\n    };\n\n\n    // Parse JSON\n\n    function jsonValue() {\n\n        function jsonObject() {\n            var o = {}, t = state.tokens.next;\n            advance(\"{\");\n            if (state.tokens.next.id !== \"}\") {\n                for (;;) {\n                    if (state.tokens.next.id === \"(end)\") {\n                        error(\"E026\", state.tokens.next, t.line);\n                    } else if (state.tokens.next.id === \"}\") {\n                        warning(\"W094\", state.tokens.curr);\n                        break;\n                    } else if (state.tokens.next.id === \",\") {\n                        error(\"E028\", state.tokens.next);\n                    } else if (state.tokens.next.id !== \"(string)\") {\n                        warning(\"W095\", state.tokens.next, state.tokens.next.value);\n                    }\n                    if (o[state.tokens.next.value] === true) {\n                        warning(\"W075\", state.tokens.next, state.tokens.next.value);\n                    } else if ((state.tokens.next.value === \"__proto__\" &&\n                        !state.option.proto) || (state.tokens.next.value === \"__iterator__\" &&\n                        !state.option.iterator)) {\n                        warning(\"W096\", state.tokens.next, state.tokens.next.value);\n                    } else {\n                        o[state.tokens.next.value] = true;\n                    }\n                    advance();\n                    advance(\":\");\n                    jsonValue();\n                    if (state.tokens.next.id !== \",\") {\n                        break;\n                    }\n                    advance(\",\");\n                }\n            }\n            advance(\"}\");\n        }\n\n        function jsonArray() {\n            var t = state.tokens.next;\n            advance(\"[\");\n            if (state.tokens.next.id !== \"]\") {\n                for (;;) {\n                    if (state.tokens.next.id === \"(end)\") {\n                        error(\"E027\", state.tokens.next, t.line);\n                    } else if (state.tokens.next.id === \"]\") {\n                        warning(\"W094\", state.tokens.curr);\n                        break;\n                    } else if (state.tokens.next.id === \",\") {\n                        error(\"E028\", state.tokens.next);\n                    }\n                    jsonValue();\n                    if (state.tokens.next.id !== \",\") {\n                        break;\n                    }\n                    advance(\",\");\n                }\n            }\n            advance(\"]\");\n        }\n\n        switch (state.tokens.next.id) {\n        case \"{\":\n            jsonObject();\n            break;\n        case \"[\":\n            jsonArray();\n            break;\n        case \"true\":\n        case \"false\":\n        case \"null\":\n        case \"(number)\":\n        case \"(string)\":\n            advance();\n            break;\n        case \"-\":\n            advance(\"-\");\n            if (state.tokens.curr.character !== state.tokens.next.from) {\n                warning(\"W011\", state.tokens.curr);\n            }\n            adjacent(state.tokens.curr, state.tokens.next);\n            advance(\"(number)\");\n            break;\n        default:\n            error(\"E003\", state.tokens.next);\n        }\n    }\n\n    var blockScope = function () {\n        var _current = {};\n        var _variables = [_current];\n\n        function _checkBlockLabels() {\n            for (var t in _current) {\n                if (_current[t][\"(type)\"] === \"unused\") {\n                    if (state.option.unused) {\n                        var tkn = _current[t][\"(token)\"];\n                        var line = tkn.line;\n                        var chr  = tkn.character;\n                        warningAt(\"W098\", line, chr, t);\n                    }\n                }\n            }\n        }\n\n        return {\n            stack: function () {\n                _current = {};\n                _variables.push(_current);\n            },\n\n            unstack: function () {\n                _checkBlockLabels();\n                _variables.splice(_variables.length - 1, 1);\n                _current = _.last(_variables);\n            },\n\n            getlabel: function (l) {\n                for (var i = _variables.length - 1 ; i >= 0; --i) {\n                    if (_.has(_variables[i], l)) {\n                        return _variables[i];\n                    }\n                }\n            },\n\n            current: {\n                has: function (t) {\n                    return _.has(_current, t);\n                },\n                add: function (t, type, tok) {\n                    _current[t] = { \"(type)\" : type,\n                                    \"(token)\": tok };\n                }\n            }\n        };\n    };\n\n    // The actual JSHINT function itself.\n    var itself = function (s, o, g) {\n        var i, k, x;\n        var optionKeys;\n        var newOptionObj = {};\n        var newIgnoredObj = {};\n\n        state.reset();\n\n        if (o && o.scope) {\n            JSHINT.scope = o.scope;\n        } else {\n            JSHINT.errors = [];\n            JSHINT.undefs = [];\n            JSHINT.internals = [];\n            JSHINT.blacklist = {};\n            JSHINT.scope = \"(main)\";\n        }\n\n        predefined = Object.create(null);\n        combine(predefined, vars.ecmaIdentifiers);\n        combine(predefined, vars.reservedVars);\n\n        combine(predefined, g || {});\n\n        declared = Object.create(null);\n        exported = Object.create(null);\n\n        function each(obj, cb) {\n            if (!obj)\n                return;\n\n            if (!Array.isArray(obj) && typeof obj === \"object\")\n                obj = Object.keys(obj);\n\n            obj.forEach(cb);\n        }\n\n        if (o) {\n            each(o.predef || null, function (item) {\n                var slice, prop;\n\n                if (item[0] === \"-\") {\n                    slice = item.slice(1);\n                    JSHINT.blacklist[slice] = slice;\n                } else {\n                    prop = Object.getOwnPropertyDescriptor(o.predef, item);\n                    predefined[item] = prop ? prop.value : false;\n                }\n            });\n\n            each(o.exported || null, function (item) {\n                exported[item] = true;\n            });\n\n            delete o.predef;\n            delete o.exported;\n\n            optionKeys = Object.keys(o);\n            for (x = 0; x < optionKeys.length; x++) {\n                if (/^-W\\d{3}$/g.test(optionKeys[x])) {\n                    newIgnoredObj[optionKeys[x].slice(1)] = true;\n                } else {\n                    newOptionObj[optionKeys[x]] = o[optionKeys[x]];\n\n                    if (optionKeys[x] === \"newcap\" && o[optionKeys[x]] === false)\n                        newOptionObj[\"(explicitNewcap)\"] = true;\n\n                    if (optionKeys[x] === \"indent\")\n                        newOptionObj[\"(explicitIndent)\"] = o[optionKeys[x]] === false ? false : true;\n                }\n            }\n        }\n\n        state.option = newOptionObj;\n        state.ignored = newIgnoredObj;\n\n        state.option.indent = state.option.indent || 4;\n        state.option.maxerr = state.option.maxerr || 50;\n\n        indent = 1;\n        global = Object.create(predefined);\n        scope = global;\n        funct = {\n            \"(global)\":   true,\n            \"(name)\":     \"(global)\",\n            \"(scope)\":    scope,\n            \"(breakage)\": 0,\n            \"(loopage)\":  0,\n            \"(tokens)\":   {},\n            \"(metrics)\":   createMetrics(state.tokens.next),\n            \"(blockscope)\": blockScope(),\n            \"(comparray)\": arrayComprehension()\n        };\n        functions = [funct];\n        urls = [];\n        stack = null;\n        member = {};\n        membersOnly = null;\n        implied = {};\n        inblock = false;\n        lookahead = [];\n        warnings = 0;\n        unuseds = [];\n\n        if (!isString(s) && !Array.isArray(s)) {\n            errorAt(\"E004\", 0);\n            return false;\n        }\n\n        api = {\n            get isJSON() {\n                return state.jsonMode;\n            },\n\n            getOption: function (name) {\n                return state.option[name] || null;\n            },\n\n            getCache: function (name) {\n                return state.cache[name];\n            },\n\n            setCache: function (name, value) {\n                state.cache[name] = value;\n            },\n\n            warn: function (code, data) {\n                warningAt.apply(null, [ code, data.line, data.char ].concat(data.data));\n            },\n\n            on: function (names, listener) {\n                names.split(\" \").forEach(function (name) {\n                    emitter.on(name, listener);\n                }.bind(this));\n            }\n        };\n\n        emitter.removeAllListeners();\n        (extraModules || []).forEach(function (func) {\n            func(api);\n        });\n\n        state.tokens.prev = state.tokens.curr = state.tokens.next = state.syntax[\"(begin)\"];\n\n        lex = new Lexer(s);\n\n        lex.on(\"warning\", function (ev) {\n            warningAt.apply(null, [ ev.code, ev.line, ev.character].concat(ev.data));\n        });\n\n        lex.on(\"error\", function (ev) {\n            errorAt.apply(null, [ ev.code, ev.line, ev.character ].concat(ev.data));\n        });\n\n        lex.on(\"fatal\", function (ev) {\n            quit(\"E041\", ev.line, ev.from);\n        });\n\n        lex.on(\"Identifier\", function (ev) {\n            emitter.emit(\"Identifier\", ev);\n        });\n\n        lex.on(\"String\", function (ev) {\n            emitter.emit(\"String\", ev);\n        });\n\n        lex.on(\"Number\", function (ev) {\n            emitter.emit(\"Number\", ev);\n        });\n\n        lex.start();\n\n        // Check options\n        for (var name in o) {\n            if (_.has(o, name)) {\n                checkOption(name, state.tokens.curr);\n            }\n        }\n\n        assume();\n\n        // combine the passed globals after we've assumed all our options\n        combine(predefined, g || {});\n\n        //reset values\n        comma.first = true;\n\n        try {\n            advance();\n            switch (state.tokens.next.id) {\n            case \"{\":\n            case \"[\":\n                destructuringAssignOrJsonValue();\n                break;\n            default:\n                directives();\n\n                if (state.directive[\"use strict\"]) {\n                    if (!state.option.globalstrict && !state.option.node) {\n                        warning(\"W097\", state.tokens.prev);\n                    }\n                }\n\n                statements();\n            }\n            advance((state.tokens.next && state.tokens.next.value !== \".\")  ? \"(end)\" : undefined);\n            funct[\"(blockscope)\"].unstack();\n\n            var markDefined = function (name, context) {\n                do {\n                    if (typeof context[name] === \"string\") {\n                        // JSHINT marks unused variables as 'unused' and\n                        // unused function declaration as 'unction'. This\n                        // code changes such instances back 'var' and\n                        // 'closure' so that the code in JSHINT.data()\n                        // doesn't think they're unused.\n\n                        if (context[name] === \"unused\")\n                            context[name] = \"var\";\n                        else if (context[name] === \"unction\")\n                            context[name] = \"closure\";\n\n                        return true;\n                    }\n\n                    context = context[\"(context)\"];\n                } while (context);\n\n                return false;\n            };\n\n            var clearImplied = function (name, line) {\n                if (!implied[name])\n                    return;\n\n                var newImplied = [];\n                for (var i = 0; i < implied[name].length; i += 1) {\n                    if (implied[name][i] !== line)\n                        newImplied.push(implied[name][i]);\n                }\n\n                if (newImplied.length === 0)\n                    delete implied[name];\n                else\n                    implied[name] = newImplied;\n            };\n\n            var warnUnused = function (name, tkn, type, unused_opt) {\n                var line = tkn.line;\n                var chr  = tkn.character;\n\n                if (unused_opt === undefined) {\n                    unused_opt = state.option.unused;\n                }\n\n                if (unused_opt === true) {\n                    unused_opt = \"last-param\";\n                }\n\n                var warnable_types = {\n                    \"vars\": [\"var\"],\n                    \"last-param\": [\"var\", \"param\"],\n                    \"strict\": [\"var\", \"param\", \"last-param\"]\n                };\n\n                if (unused_opt) {\n                    if (warnable_types[unused_opt] && warnable_types[unused_opt].indexOf(type) !== -1) {\n                        warningAt(\"W098\", line, chr, name);\n                    }\n                }\n\n                unuseds.push({\n                    name: name,\n                    line: line,\n                    character: chr\n                });\n            };\n\n            var checkUnused = function (func, key) {\n                var type = func[key];\n                var tkn = func[\"(tokens)\"][key];\n\n                if (key.charAt(0) === \"(\")\n                    return;\n\n                if (type !== \"unused\" && type !== \"unction\")\n                    return;\n\n                // Params are checked separately from other variables.\n                if (func[\"(params)\"] && func[\"(params)\"].indexOf(key) !== -1)\n                    return;\n\n                // Variable is in global scope and defined as exported.\n                if (func[\"(global)\"] && _.has(exported, key)) {\n                    return;\n                }\n\n                warnUnused(key, tkn, \"var\");\n            };\n\n            // Check queued 'x is not defined' instances to see if they're still undefined.\n            for (i = 0; i < JSHINT.undefs.length; i += 1) {\n                k = JSHINT.undefs[i].slice(0);\n\n                if (markDefined(k[2].value, k[0])) {\n                    clearImplied(k[2].value, k[2].line);\n                } else if (state.option.undef) {\n                    warning.apply(warning, k.slice(1));\n                }\n            }\n\n            functions.forEach(function (func) {\n                if (func[\"(unusedOption)\"] === false) {\n                    return;\n                }\n\n                for (var key in func) {\n                    if (_.has(func, key)) {\n                        checkUnused(func, key);\n                    }\n                }\n\n                if (!func[\"(params)\"])\n                    return;\n\n                var params = func[\"(params)\"].slice();\n                var param  = params.pop();\n                var type, unused_opt;\n\n                while (param) {\n                    type = func[param];\n                    unused_opt = func[\"(unusedOption)\"] || state.option.unused;\n                    unused_opt = unused_opt === true ? \"last-param\" : unused_opt;\n\n                    // 'undefined' is a special case for (function (window, undefined) { ... })();\n                    // patterns.\n\n                    if (param === \"undefined\")\n                        return;\n\n                    if (type === \"unused\" || type === \"unction\") {\n                        warnUnused(param, func[\"(tokens)\"][param], \"param\", func[\"(unusedOption)\"]);\n                    } else if (unused_opt === \"last-param\") {\n                        return;\n                    }\n\n                    param = params.pop();\n                }\n            });\n\n            for (var key in declared) {\n                if (_.has(declared, key) && !_.has(global, key)) {\n                    warnUnused(key, declared[key], \"var\");\n                }\n            }\n\n        } catch (err) {\n            if (err && err.name === \"JSHintError\") {\n                var nt = state.tokens.next || {};\n                JSHINT.errors.push({\n                    scope     : \"(main)\",\n                    raw       : err.raw,\n                    code      : err.code,\n                    reason    : err.message,\n                    line      : err.line || nt.line,\n                    character : err.character || nt.from\n                }, null);\n            } else {\n                throw err;\n            }\n        }\n\n        // Loop over the listed \"internals\", and check them as well.\n\n        if (JSHINT.scope === \"(main)\") {\n            o = o || {};\n\n            for (i = 0; i < JSHINT.internals.length; i += 1) {\n                k = JSHINT.internals[i];\n                o.scope = k.elem;\n                itself(k.value, o, g);\n            }\n        }\n\n        return JSHINT.errors.length === 0;\n    };\n\n    // Modules.\n    itself.addModule = function (func) {\n        extraModules.push(func);\n    };\n\n    itself.addModule(style.register);\n\n    // Data summary.\n    itself.data = function () {\n        var data = {\n            functions: [],\n            options: state.option\n        };\n        var implieds = [];\n        var members = [];\n        var fu, f, i, j, n, globals;\n\n        if (itself.errors.length) {\n            data.errors = itself.errors;\n        }\n\n        if (state.jsonMode) {\n            data.json = true;\n        }\n\n        for (n in implied) {\n            if (_.has(implied, n)) {\n                implieds.push({\n                    name: n,\n                    line: implied[n]\n                });\n            }\n        }\n\n        if (implieds.length > 0) {\n            data.implieds = implieds;\n        }\n\n        if (urls.length > 0) {\n            data.urls = urls;\n        }\n\n        globals = Object.keys(scope);\n        if (globals.length > 0) {\n            data.globals = globals;\n        }\n\n        for (i = 1; i < functions.length; i += 1) {\n            f = functions[i];\n            fu = {};\n\n            for (j = 0; j < functionicity.length; j += 1) {\n                fu[functionicity[j]] = [];\n            }\n\n            for (j = 0; j < functionicity.length; j += 1) {\n                if (fu[functionicity[j]].length === 0) {\n                    delete fu[functionicity[j]];\n                }\n            }\n\n            fu.name = f[\"(name)\"];\n            fu.param = f[\"(params)\"];\n            fu.line = f[\"(line)\"];\n            fu.character = f[\"(character)\"];\n            fu.last = f[\"(last)\"];\n            fu.lastcharacter = f[\"(lastcharacter)\"];\n            data.functions.push(fu);\n        }\n\n        if (unuseds.length > 0) {\n            data.unused = unuseds;\n        }\n\n        members = [];\n        for (n in member) {\n            if (typeof member[n] === \"number\") {\n                data.member = member;\n                break;\n            }\n        }\n\n        return data;\n    };\n\n    itself.jshint = itself;\n\n    return itself;\n}());\n\n// Make JSHINT a Node module, if possible.\nif (typeof exports === \"object\" && exports) {\n    exports.JSHINT = JSHINT;\n}\n\n})()\n},{\"events\":2,\"../shared/vars.js\":3,\"../shared/messages.js\":7,\"./reg.js\":4,\"./state.js\":6,\"./style.js\":5,\"./lex.js\":8,\"console-browserify\":9,\"underscore\":10}],7:[function(require,module,exports){\n(function(){\"use strict\";\n\nvar _ = require(\"underscore\");\n\nvar errors = {\n    // JSHint options\n    E001: \"Bad option: '{a}'.\",\n    E002: \"Bad option value.\",\n\n    // JSHint input\n    E003: \"Expected a JSON value.\",\n    E004: \"Input is neither a string nor an array of strings.\",\n    E005: \"Input is empty.\",\n    E006: \"Unexpected early end of program.\",\n\n    // Strict mode\n    E007: \"Missing \\\"use strict\\\" statement.\",\n    E008: \"Strict violation.\",\n    E009: \"Option 'validthis' can't be used in a global scope.\",\n    E010: \"'with' is not allowed in strict mode.\",\n\n    // Constants\n    E011: \"const '{a}' has already been declared.\",\n    E012: \"const '{a}' is initialized to 'undefined'.\",\n    E013: \"Attempting to override '{a}' which is a constant.\",\n\n    // Regular expressions\n    E014: \"A regular expression literal can be confused with '/='.\",\n    E015: \"Unclosed regular expression.\",\n    E016: \"Invalid regular expression.\",\n\n    // Tokens\n    E017: \"Unclosed comment.\",\n    E018: \"Unbegun comment.\",\n    E019: \"Unmatched '{a}'.\",\n    E020: \"Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.\",\n    E021: \"Expected '{a}' and instead saw '{b}'.\",\n    E022: \"Line breaking error '{a}'.\",\n    E023: \"Missing '{a}'.\",\n    E024: \"Unexpected '{a}'.\",\n    E025: \"Missing ':' on a case clause.\",\n    E026: \"Missing '}' to match '{' from line {a}.\",\n    E027: \"Missing ']' to match '[' form line {a}.\",\n    E028: \"Illegal comma.\",\n    E029: \"Unclosed string.\",\n\n    // Everything else\n    E030: \"Expected an identifier and instead saw '{a}'.\",\n    E031: \"Bad assignment.\", // FIXME: Rephrase\n    E032: \"Expected a small integer or 'false' and instead saw '{a}'.\",\n    E033: \"Expected an operator and instead saw '{a}'.\",\n    E034: \"get/set are ES5 features.\",\n    E035: \"Missing property name.\",\n    E036: \"Expected to see a statement and instead saw a block.\",\n    E037: null, // Vacant\n    E038: null, // Vacant\n    E039: \"Function declarations are not invocable. Wrap the whole function invocation in parens.\",\n    E040: \"Each value should have its own case label.\",\n    E041: \"Unrecoverable syntax error.\",\n    E042: \"Stopping.\",\n    E043: \"Too many errors.\",\n    E044: \"'{a}' is already defined and can't be redefined.\",\n    E045: \"Invalid for each loop.\",\n    E046: \"A yield statement shall be within a generator function (with syntax: `function*`)\",\n    E047: \"A generator function shall contain a yield statement.\",\n    E048: \"Let declaration not directly within block.\",\n    E049: \"A {a} cannot be named '{b}'.\",\n    E050: \"Mozilla requires the yield expression to be parenthesized here.\",\n    E051: \"Regular parameters cannot come after default parameters.\"\n};\n\nvar warnings = {\n    W001: \"'hasOwnProperty' is a really bad name.\",\n    W002: \"Value of '{a}' may be overwritten in IE 8 and earlier.\",\n    W003: \"'{a}' was used before it was defined.\",\n    W004: \"'{a}' is already defined.\",\n    W005: \"A dot following a number can be confused with a decimal point.\",\n    W006: \"Confusing minuses.\",\n    W007: \"Confusing pluses.\",\n    W008: \"A leading decimal point can be confused with a dot: '{a}'.\",\n    W009: \"The array literal notation [] is preferrable.\",\n    W010: \"The object literal notation {} is preferrable.\",\n    W011: \"Unexpected space after '{a}'.\",\n    W012: \"Unexpected space before '{a}'.\",\n    W013: \"Missing space after '{a}'.\",\n    W014: \"Bad line breaking before '{a}'.\",\n    W015: \"Expected '{a}' to have an indentation at {b} instead at {c}.\",\n    W016: \"Unexpected use of '{a}'.\",\n    W017: \"Bad operand.\",\n    W018: \"Confusing use of '{a}'.\",\n    W019: \"Use the isNaN function to compare with NaN.\",\n    W020: \"Read only.\",\n    W021: \"'{a}' is a function.\",\n    W022: \"Do not assign to the exception parameter.\",\n    W023: \"Expected an identifier in an assignment and instead saw a function invocation.\",\n    W024: \"Expected an identifier and instead saw '{a}' (a reserved word).\",\n    W025: \"Missing name in function declaration.\",\n    W026: \"Inner functions should be listed at the top of the outer function.\",\n    W027: \"Unreachable '{a}' after '{b}'.\",\n    W028: \"Label '{a}' on {b} statement.\",\n    W030: \"Expected an assignment or function call and instead saw an expression.\",\n    W031: \"Do not use 'new' for side effects.\",\n    W032: \"Unnecessary semicolon.\",\n    W033: \"Missing semicolon.\",\n    W034: \"Unnecessary directive \\\"{a}\\\".\",\n    W035: \"Empty block.\",\n    W036: \"Unexpected /*member '{a}'.\",\n    W037: \"'{a}' is a statement label.\",\n    W038: \"'{a}' used out of scope.\",\n    W039: \"'{a}' is not allowed.\",\n    W040: \"Possible strict violation.\",\n    W041: \"Use '{a}' to compare with '{b}'.\",\n    W042: \"Avoid EOL escaping.\",\n    W043: \"Bad escaping of EOL. Use option multistr if needed.\",\n    W044: \"Bad or unnecessary escaping.\",\n    W045: \"Bad number '{a}'.\",\n    W046: \"Don't use extra leading zeros '{a}'.\",\n    W047: \"A trailing decimal point can be confused with a dot: '{a}'.\",\n    W048: \"Unexpected control character in regular expression.\",\n    W049: \"Unexpected escaped character '{a}' in regular expression.\",\n    W050: \"JavaScript URL.\",\n    W051: \"Variables should not be deleted.\",\n    W052: \"Unexpected '{a}'.\",\n    W053: \"Do not use {a} as a constructor.\",\n    W054: \"The Function constructor is a form of eval.\",\n    W055: \"A constructor name should start with an uppercase letter.\",\n    W056: \"Bad constructor.\",\n    W057: \"Weird construction. Is 'new' unnecessary?\",\n    W058: \"Missing '()' invoking a constructor.\",\n    W059: \"Avoid arguments.{a}.\",\n    W060: \"document.write can be a form of eval.\",\n    W061: \"eval can be harmful.\",\n    W062: \"Wrap an immediate function invocation in parens \" +\n        \"to assist the reader in understanding that the expression \" +\n        \"is the result of a function, and not the function itself.\",\n    W063: \"Math is not a function.\",\n    W064: \"Missing 'new' prefix when invoking a constructor.\",\n    W065: \"Missing radix parameter.\",\n    W066: \"Implied eval. Consider passing a function instead of a string.\",\n    W067: \"Bad invocation.\",\n    W068: \"Wrapping non-IIFE function literals in parens is unnecessary.\",\n    W069: \"['{a}'] is better written in dot notation.\",\n    W070: \"Extra comma. (it breaks older versions of IE)\",\n    W071: \"This function has too many statements. ({a})\",\n    W072: \"This function has too many parameters. ({a})\",\n    W073: \"Blocks are nested too deeply. ({a})\",\n    W074: \"This function's cyclomatic complexity is too high. ({a})\",\n    W075: \"Duplicate key '{a}'.\",\n    W076: \"Unexpected parameter '{a}' in get {b} function.\",\n    W077: \"Expected a single parameter in set {a} function.\",\n    W078: \"Setter is defined without getter.\",\n    W079: \"Redefinition of '{a}'.\",\n    W080: \"It's not necessary to initialize '{a}' to 'undefined'.\",\n    W081: \"Too many var statements.\",\n    W082: \"Function declarations should not be placed in blocks. \" +\n        \"Use a function expression or move the statement to the top of \" +\n        \"the outer function.\",\n    W083: \"Don't make functions within a loop.\",\n    W084: \"Expected a conditional expression and instead saw an assignment.\",\n    W085: \"Don't use 'with'.\",\n    W086: \"Expected a 'break' statement before '{a}'.\",\n    W087: \"Forgotten 'debugger' statement?\",\n    W088: \"Creating global 'for' variable. Should be 'for (var {a} ...'.\",\n    W089: \"The body of a for in should be wrapped in an if statement to filter \" +\n        \"unwanted properties from the prototype.\",\n    W090: \"'{a}' is not a statement label.\",\n    W091: \"'{a}' is out of scope.\",\n    W092: \"Wrap the /regexp/ literal in parens to disambiguate the slash operator.\",\n    W093: \"Did you mean to return a conditional instead of an assignment?\",\n    W094: \"Unexpected comma.\",\n    W095: \"Expected a string and instead saw {a}.\",\n    W096: \"The '{a}' key may produce unexpected results.\",\n    W097: \"Use the function form of \\\"use strict\\\".\",\n    W098: \"'{a}' is defined but never used.\",\n    W099: \"Mixed spaces and tabs.\",\n    W100: \"This character may get silently deleted by one or more browsers.\",\n    W101: \"Line is too long.\",\n    W102: \"Trailing whitespace.\",\n    W103: \"The '{a}' property is deprecated.\",\n    W104: \"'{a}' is only available in JavaScript 1.7.\",\n    W105: \"Unexpected {a} in '{b}'.\",\n    W106: \"Identifier '{a}' is not in camel case.\",\n    W107: \"Script URL.\",\n    W108: \"Strings must use doublequote.\",\n    W109: \"Strings must use singlequote.\",\n    W110: \"Mixed double and single quotes.\",\n    W112: \"Unclosed string.\",\n    W113: \"Control character in string: {a}.\",\n    W114: \"Avoid {a}.\",\n    W115: \"Octal literals are not allowed in strict mode.\",\n    W116: \"Expected '{a}' and instead saw '{b}'.\",\n    W117: \"'{a}' is not defined.\",\n    W118: \"'{a}' is only available in Mozilla JavaScript extensions (use moz option).\",\n    W119: \"'{a}' is only available in ES6 (use esnext option).\",\n    W120: \"You might be leaking a variable ({a}) here.\"\n};\n\nvar info = {\n    I001: \"Comma warnings can be turned off with 'laxcomma'.\",\n    I002: \"Reserved words as properties can be used under the 'es5' option.\",\n    I003: \"ES5 option is now set per default\"\n};\n\nexports.errors = {};\nexports.warnings = {};\nexports.info = {};\n\n_.each(errors, function (desc, code) {\n    exports.errors[code] = { code: code, desc: desc };\n});\n\n_.each(warnings, function (desc, code) {\n    exports.warnings[code] = { code: code, desc: desc };\n});\n\n_.each(info, function (desc, code) {\n    exports.info[code] = { code: code, desc: desc };\n});\n\n})()\n},{\"underscore\":10}],8:[function(require,module,exports){\n(function(){/*\n * Lexical analysis and token construction.\n */\n\n\"use strict\";\n\nvar _      = require(\"underscore\");\nvar events = require(\"events\");\nvar reg    = require(\"./reg.js\");\nvar state  = require(\"./state.js\").state;\n\n// Some of these token types are from JavaScript Parser API\n// while others are specific to JSHint parser.\n// JS Parser API: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API\n\nvar Token = {\n    Identifier: 1,\n    Punctuator: 2,\n    NumericLiteral: 3,\n    StringLiteral: 4,\n    Comment: 5,\n    Keyword: 6,\n    NullLiteral: 7,\n    BooleanLiteral: 8,\n    RegExp: 9\n};\n\n// This is auto generated from the unicode tables.\n// The tables are at:\n// http://www.fileformat.info/info/unicode/category/Lu/list.htm\n// http://www.fileformat.info/info/unicode/category/Ll/list.htm\n// http://www.fileformat.info/info/unicode/category/Lt/list.htm\n// http://www.fileformat.info/info/unicode/category/Lm/list.htm\n// http://www.fileformat.info/info/unicode/category/Lo/list.htm\n// http://www.fileformat.info/info/unicode/category/Nl/list.htm\n\nvar unicodeLetterTable = [\n    170, 170, 181, 181, 186, 186, 192, 214,\n    216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750,\n    880, 884, 886, 887, 890, 893, 902, 902, 904, 906, 908, 908,\n    910, 929, 931, 1013, 1015, 1153, 1162, 1319, 1329, 1366,\n    1369, 1369, 1377, 1415, 1488, 1514, 1520, 1522, 1568, 1610,\n    1646, 1647, 1649, 1747, 1749, 1749, 1765, 1766, 1774, 1775,\n    1786, 1788, 1791, 1791, 1808, 1808, 1810, 1839, 1869, 1957,\n    1969, 1969, 1994, 2026, 2036, 2037, 2042, 2042, 2048, 2069,\n    2074, 2074, 2084, 2084, 2088, 2088, 2112, 2136, 2308, 2361,\n    2365, 2365, 2384, 2384, 2392, 2401, 2417, 2423, 2425, 2431,\n    2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482,\n    2486, 2489, 2493, 2493, 2510, 2510, 2524, 2525, 2527, 2529,\n    2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608,\n    2610, 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654,\n    2674, 2676, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736,\n    2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2785,\n    2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867,\n    2869, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2929, 2929,\n    2947, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970,\n    2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001,\n    3024, 3024, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123,\n    3125, 3129, 3133, 3133, 3160, 3161, 3168, 3169, 3205, 3212,\n    3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3261, 3261,\n    3294, 3294, 3296, 3297, 3313, 3314, 3333, 3340, 3342, 3344,\n    3346, 3386, 3389, 3389, 3406, 3406, 3424, 3425, 3450, 3455,\n    3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526,\n    3585, 3632, 3634, 3635, 3648, 3654, 3713, 3714, 3716, 3716,\n    3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743,\n    3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3760,\n    3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3805,\n    3840, 3840, 3904, 3911, 3913, 3948, 3976, 3980, 4096, 4138,\n    4159, 4159, 4176, 4181, 4186, 4189, 4193, 4193, 4197, 4198,\n    4206, 4208, 4213, 4225, 4238, 4238, 4256, 4293, 4304, 4346,\n    4348, 4348, 4352, 4680, 4682, 4685, 4688, 4694, 4696, 4696,\n    4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789,\n    4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880,\n    4882, 4885, 4888, 4954, 4992, 5007, 5024, 5108, 5121, 5740,\n    5743, 5759, 5761, 5786, 5792, 5866, 5870, 5872, 5888, 5900,\n    5902, 5905, 5920, 5937, 5952, 5969, 5984, 5996, 5998, 6000,\n    6016, 6067, 6103, 6103, 6108, 6108, 6176, 6263, 6272, 6312,\n    6314, 6314, 6320, 6389, 6400, 6428, 6480, 6509, 6512, 6516,\n    6528, 6571, 6593, 6599, 6656, 6678, 6688, 6740, 6823, 6823,\n    6917, 6963, 6981, 6987, 7043, 7072, 7086, 7087, 7104, 7141,\n    7168, 7203, 7245, 7247, 7258, 7293, 7401, 7404, 7406, 7409,\n    7424, 7615, 7680, 7957, 7960, 7965, 7968, 8005, 8008, 8013,\n    8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061,\n    8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140,\n    8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188,\n    8305, 8305, 8319, 8319, 8336, 8348, 8450, 8450, 8455, 8455,\n    8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486,\n    8488, 8488, 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521,\n    8526, 8526, 8544, 8584, 11264, 11310, 11312, 11358,\n    11360, 11492, 11499, 11502, 11520, 11557, 11568, 11621,\n    11631, 11631, 11648, 11670, 11680, 11686, 11688, 11694,\n    11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726,\n    11728, 11734, 11736, 11742, 11823, 11823, 12293, 12295,\n    12321, 12329, 12337, 12341, 12344, 12348, 12353, 12438,\n    12445, 12447, 12449, 12538, 12540, 12543, 12549, 12589,\n    12593, 12686, 12704, 12730, 12784, 12799, 13312, 13312,\n    19893, 19893, 19968, 19968, 40907, 40907, 40960, 42124,\n    42192, 42237, 42240, 42508, 42512, 42527, 42538, 42539,\n    42560, 42606, 42623, 42647, 42656, 42735, 42775, 42783,\n    42786, 42888, 42891, 42894, 42896, 42897, 42912, 42921,\n    43002, 43009, 43011, 43013, 43015, 43018, 43020, 43042,\n    43072, 43123, 43138, 43187, 43250, 43255, 43259, 43259,\n    43274, 43301, 43312, 43334, 43360, 43388, 43396, 43442,\n    43471, 43471, 43520, 43560, 43584, 43586, 43588, 43595,\n    43616, 43638, 43642, 43642, 43648, 43695, 43697, 43697,\n    43701, 43702, 43705, 43709, 43712, 43712, 43714, 43714,\n    43739, 43741, 43777, 43782, 43785, 43790, 43793, 43798,\n    43808, 43814, 43816, 43822, 43968, 44002, 44032, 44032,\n    55203, 55203, 55216, 55238, 55243, 55291, 63744, 64045,\n    64048, 64109, 64112, 64217, 64256, 64262, 64275, 64279,\n    64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316,\n    64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433,\n    64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019,\n    65136, 65140, 65142, 65276, 65313, 65338, 65345, 65370,\n    65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495,\n    65498, 65500, 65536, 65547, 65549, 65574, 65576, 65594,\n    65596, 65597, 65599, 65613, 65616, 65629, 65664, 65786,\n    65856, 65908, 66176, 66204, 66208, 66256, 66304, 66334,\n    66352, 66378, 66432, 66461, 66464, 66499, 66504, 66511,\n    66513, 66517, 66560, 66717, 67584, 67589, 67592, 67592,\n    67594, 67637, 67639, 67640, 67644, 67644, 67647, 67669,\n    67840, 67861, 67872, 67897, 68096, 68096, 68112, 68115,\n    68117, 68119, 68121, 68147, 68192, 68220, 68352, 68405,\n    68416, 68437, 68448, 68466, 68608, 68680, 69635, 69687,\n    69763, 69807, 73728, 74606, 74752, 74850, 77824, 78894,\n    92160, 92728, 110592, 110593, 119808, 119892, 119894, 119964,\n    119966, 119967, 119970, 119970, 119973, 119974, 119977, 119980,\n    119982, 119993, 119995, 119995, 119997, 120003, 120005, 120069,\n    120071, 120074, 120077, 120084, 120086, 120092, 120094, 120121,\n    120123, 120126, 120128, 120132, 120134, 120134, 120138, 120144,\n    120146, 120485, 120488, 120512, 120514, 120538, 120540, 120570,\n    120572, 120596, 120598, 120628, 120630, 120654, 120656, 120686,\n    120688, 120712, 120714, 120744, 120746, 120770, 120772, 120779,\n    131072, 131072, 173782, 173782, 173824, 173824, 177972, 177972,\n    177984, 177984, 178205, 178205, 194560, 195101\n];\n\nvar identifierStartTable = [];\n\nfor (var i = 0; i < 128; i++) {\n    identifierStartTable[i] =\n        i === 36 ||           // $\n        i >= 65 && i <= 90 || // A-Z\n        i === 95 ||           // _\n        i >= 97 && i <= 122;  // a-z\n}\n\nvar identifierPartTable = [];\n\nfor (var i = 0; i < 128; i++) {\n    identifierPartTable[i] =\n        identifierStartTable[i] || // $, _, A-Z, a-z\n        i >= 48 && i <= 57;        // 0-9\n}\n\n// Object that handles postponed lexing verifications that checks the parsed\n// environment state.\n\nfunction asyncTrigger() {\n    var _checks = [];\n\n    return {\n        push: function (fn) {\n            _checks.push(fn);\n        },\n\n        check: function () {\n            for (var check = 0; check < _checks.length; ++check) {\n                _checks[check]();\n            }\n\n            _checks.splice(0, _checks.length);\n        }\n    };\n}\n\n/*\n * Lexer for JSHint.\n *\n * This object does a char-by-char scan of the provided source code\n * and produces a sequence of tokens.\n *\n *   var lex = new Lexer(\"var i = 0;\");\n *   lex.start();\n *   lex.token(); // returns the next token\n *\n * You have to use the token() method to move the lexer forward\n * but you don't have to use its return value to get tokens. In addition\n * to token() method returning the next token, the Lexer object also\n * emits events.\n *\n *   lex.on(\"Identifier\", function (data) {\n *     if (data.name.indexOf(\"_\") >= 0) {\n *       // Produce a warning.\n *     }\n *   });\n *\n * Note that the token() method returns tokens in a JSLint-compatible\n * format while the event emitter uses a slightly modified version of\n * Mozilla's JavaScript Parser API. Eventually, we will move away from\n * JSLint format.\n */\nfunction Lexer(source) {\n    var lines = source;\n\n    if (typeof lines === \"string\") {\n        lines = lines\n            .replace(/\\r\\n/g, \"\\n\")\n            .replace(/\\r/g, \"\\n\")\n            .split(\"\\n\");\n    }\n\n    // If the first line is a shebang (#!), make it a blank and move on.\n    // Shebangs are used by Node scripts.\n\n    if (lines[0] && lines[0].substr(0, 2) === \"#!\") {\n        lines[0] = \"\";\n    }\n\n    this.emitter = new events.EventEmitter();\n    this.source = source;\n    this.setLines(lines);\n    this.prereg = true;\n\n    this.line = 0;\n    this.char = 1;\n    this.from = 1;\n    this.input = \"\";\n\n    for (var i = 0; i < state.option.indent; i += 1) {\n        state.tab += \" \";\n    }\n}\n\nLexer.prototype = {\n    _lines: [],\n\n    getLines: function () {\n        this._lines = state.lines;\n        return this._lines;\n    },\n\n    setLines: function (val) {\n        this._lines = val;\n        state.lines = this._lines;\n    },\n\n    /*\n     * Return the next i character without actually moving the\n     * char pointer.\n     */\n    peek: function (i) {\n        return this.input.charAt(i || 0);\n    },\n\n    /*\n     * Move the char pointer forward i times.\n     */\n    skip: function (i) {\n        i = i || 1;\n        this.char += i;\n        this.input = this.input.slice(i);\n    },\n\n    /*\n     * Subscribe to a token event. The API for this method is similar\n     * Underscore.js i.e. you can subscribe to multiple events with\n     * one call:\n     *\n     *   lex.on(\"Identifier Number\", function (data) {\n     *     // ...\n     *   });\n     */\n    on: function (names, listener) {\n        names.split(\" \").forEach(function (name) {\n            this.emitter.on(name, listener);\n        }.bind(this));\n    },\n\n    /*\n     * Trigger a token event. All arguments will be passed to each\n     * listener.\n     */\n    trigger: function () {\n        this.emitter.emit.apply(this.emitter, Array.prototype.slice.call(arguments));\n    },\n\n    /*\n     * Postpone a token event. the checking condition is set as\n     * last parameter, and the trigger function is called in a\n     * stored callback. To be later called using the check() function\n     * by the parser. This avoids parser's peek() to give the lexer\n     * a false context.\n     */\n    triggerAsync: function (type, args, checks, fn) {\n        checks.push(function () {\n            if (fn()) {\n                this.trigger(type, args);\n            }\n        }.bind(this));\n    },\n\n    /*\n     * Extract a punctuator out of the next sequence of characters\n     * or return 'null' if its not possible.\n     *\n     * This method's implementation was heavily influenced by the\n     * scanPunctuator function in the Esprima parser's source code.\n     */\n    scanPunctuator: function () {\n        var ch1 = this.peek();\n        var ch2, ch3, ch4;\n\n        switch (ch1) {\n        // Most common single-character punctuators\n        case \".\":\n            if ((/^[0-9]$/).test(this.peek(1))) {\n                return null;\n            }\n            if (this.peek(1) === \".\" && this.peek(2) === \".\") {\n                return {\n                    type: Token.Punctuator,\n                    value: \"...\"\n                };\n            }\n            /* falls through */\n        case \"(\":\n        case \")\":\n        case \";\":\n        case \",\":\n        case \"{\":\n        case \"}\":\n        case \"[\":\n        case \"]\":\n        case \":\":\n        case \"~\":\n        case \"?\":\n            return {\n                type: Token.Punctuator,\n                value: ch1\n            };\n\n        // A pound sign (for Node shebangs)\n        case \"#\":\n            return {\n                type: Token.Punctuator,\n                value: ch1\n            };\n\n        // We're at the end of input\n        case \"\":\n            return null;\n        }\n\n        // Peek more characters\n\n        ch2 = this.peek(1);\n        ch3 = this.peek(2);\n        ch4 = this.peek(3);\n\n        // 4-character punctuator: >>>=\n\n        if (ch1 === \">\" && ch2 === \">\" && ch3 === \">\" && ch4 === \"=\") {\n            return {\n                type: Token.Punctuator,\n                value: \">>>=\"\n            };\n        }\n\n        // 3-character punctuators: === !== >>> <<= >>=\n\n        if (ch1 === \"=\" && ch2 === \"=\" && ch3 === \"=\") {\n            return {\n                type: Token.Punctuator,\n                value: \"===\"\n            };\n        }\n\n        if (ch1 === \"!\" && ch2 === \"=\" && ch3 === \"=\") {\n            return {\n                type: Token.Punctuator,\n                value: \"!==\"\n            };\n        }\n\n        if (ch1 === \">\" && ch2 === \">\" && ch3 === \">\") {\n            return {\n                type: Token.Punctuator,\n                value: \">>>\"\n            };\n        }\n\n        if (ch1 === \"<\" && ch2 === \"<\" && ch3 === \"=\") {\n            return {\n                type: Token.Punctuator,\n                value: \"<<=\"\n            };\n        }\n\n        if (ch1 === \">\" && ch2 === \">\" && ch3 === \"=\") {\n            return {\n                type: Token.Punctuator,\n                value: \">>=\"\n            };\n        }\n\n        // Fat arrow punctuator\n        if (ch1 === \"=\" && ch2 === \">\") {\n            return {\n                type: Token.Punctuator,\n                value: ch1 + ch2\n            };\n        }\n\n        // 2-character punctuators: <= >= == != ++ -- << >> && ||\n        // += -= *= %= &= |= ^= (but not /=, see below)\n        if (ch1 === ch2 && (\"+-<>&|\".indexOf(ch1) >= 0)) {\n            return {\n                type: Token.Punctuator,\n                value: ch1 + ch2\n            };\n        }\n\n        if (\"<>=!+-*%&|^\".indexOf(ch1) >= 0) {\n            if (ch2 === \"=\") {\n                return {\n                    type: Token.Punctuator,\n                    value: ch1 + ch2\n                };\n            }\n\n            return {\n                type: Token.Punctuator,\n                value: ch1\n            };\n        }\n\n        // Special case: /=. We need to make sure that this is an\n        // operator and not a regular expression.\n\n        if (ch1 === \"/\") {\n            if (ch2 === \"=\" && /\\/=(?!(\\S*\\/[gim]?))/.test(this.input)) {\n                // /= is not a part of a regular expression, return it as a\n                // punctuator.\n                return {\n                    type: Token.Punctuator,\n                    value: \"/=\"\n                };\n            }\n\n            return {\n                type: Token.Punctuator,\n                value: \"/\"\n            };\n        }\n\n        return null;\n    },\n\n    /*\n     * Extract a comment out of the next sequence of characters and/or\n     * lines or return 'null' if its not possible. Since comments can\n     * span across multiple lines this method has to move the char\n     * pointer.\n     *\n     * In addition to normal JavaScript comments (// and /*) this method\n     * also recognizes JSHint- and JSLint-specific comments such as\n     * /*jshint, /*jslint, /*globals and so on.\n     */\n    scanComments: function () {\n        var ch1 = this.peek();\n        var ch2 = this.peek(1);\n        var rest = this.input.substr(2);\n        var startLine = this.line;\n        var startChar = this.char;\n\n        // Create a comment token object and make sure it\n        // has all the data JSHint needs to work with special\n        // comments.\n\n        function commentToken(label, body, opt) {\n            var special = [\"jshint\", \"jslint\", \"members\", \"member\", \"globals\", \"global\", \"exported\"];\n            var isSpecial = false;\n            var value = label + body;\n            var commentType = \"plain\";\n            opt = opt || {};\n\n            if (opt.isMultiline) {\n                value += \"*/\";\n            }\n\n            special.forEach(function (str) {\n                if (isSpecial) {\n                    return;\n                }\n\n                // Don't recognize any special comments other than jshint for single-line\n                // comments. This introduced many problems with legit comments.\n                if (label === \"//\" && str !== \"jshint\") {\n                    return;\n                }\n\n                if (body.substr(0, str.length) === str) {\n                    isSpecial = true;\n                    label = label + str;\n                    body = body.substr(str.length);\n                }\n\n                if (!isSpecial && body.charAt(0) === \" \" && body.substr(1, str.length) === str) {\n                    isSpecial = true;\n                    label = label + \" \" + str;\n                    body = body.substr(str.length + 1);\n                }\n\n                if (!isSpecial) {\n                    return;\n                }\n\n                switch (str) {\n                case \"member\":\n                    commentType = \"members\";\n                    break;\n                case \"global\":\n                    commentType = \"globals\";\n                    break;\n                default:\n                    commentType = str;\n                }\n            });\n\n            return {\n                type: Token.Comment,\n                commentType: commentType,\n                value: value,\n                body: body,\n                isSpecial: isSpecial,\n                isMultiline: opt.isMultiline || false,\n                isMalformed: opt.isMalformed || false\n            };\n        }\n\n        // End of unbegun comment. Raise an error and skip that input.\n        if (ch1 === \"*\" && ch2 === \"/\") {\n            this.trigger(\"error\", {\n                code: \"E018\",\n                line: startLine,\n                character: startChar\n            });\n\n            this.skip(2);\n            return null;\n        }\n\n        // Comments must start either with // or /*\n        if (ch1 !== \"/\" || (ch2 !== \"*\" && ch2 !== \"/\")) {\n            return null;\n        }\n\n        // One-line comment\n        if (ch2 === \"/\") {\n            this.skip(this.input.length); // Skip to the EOL.\n            return commentToken(\"//\", rest);\n        }\n\n        var body = \"\";\n\n        /* Multi-line comment */\n        if (ch2 === \"*\") {\n            this.skip(2);\n\n            while (this.peek() !== \"*\" || this.peek(1) !== \"/\") {\n                if (this.peek() === \"\") { // End of Line\n                    body += \"\\n\";\n\n                    // If we hit EOF and our comment is still unclosed,\n                    // trigger an error and end the comment implicitly.\n                    if (!this.nextLine()) {\n                        this.trigger(\"error\", {\n                            code: \"E017\",\n                            line: startLine,\n                            character: startChar\n                        });\n\n                        return commentToken(\"/*\", body, {\n                            isMultiline: true,\n                            isMalformed: true\n                        });\n                    }\n                } else {\n                    body += this.peek();\n                    this.skip();\n                }\n            }\n\n            this.skip(2);\n            return commentToken(\"/*\", body, { isMultiline: true });\n        }\n    },\n\n    /*\n     * Extract a keyword out of the next sequence of characters or\n     * return 'null' if its not possible.\n     */\n    scanKeyword: function () {\n        var result = /^[a-zA-Z_$][a-zA-Z0-9_$]*/.exec(this.input);\n        var keywords = [\n            \"if\", \"in\", \"do\", \"var\", \"for\", \"new\",\n            \"try\", \"let\", \"this\", \"else\", \"case\",\n            \"void\", \"with\", \"enum\", \"while\", \"break\",\n            \"catch\", \"throw\", \"const\", \"yield\", \"class\",\n            \"super\", \"return\", \"typeof\", \"delete\",\n            \"switch\", \"export\", \"import\", \"default\",\n            \"finally\", \"extends\", \"function\", \"continue\",\n            \"debugger\", \"instanceof\"\n        ];\n\n        if (result && keywords.indexOf(result[0]) >= 0) {\n            return {\n                type: Token.Keyword,\n                value: result[0]\n            };\n        }\n\n        return null;\n    },\n\n    /*\n     * Extract a JavaScript identifier out of the next sequence of\n     * characters or return 'null' if its not possible. In addition,\n     * to Identifier this method can also produce BooleanLiteral\n     * (true/false) and NullLiteral (null).\n     */\n    scanIdentifier: function () {\n        var id = \"\";\n        var index = 0;\n        var type, char;\n\n        // Detects any character in the Unicode categories \"Uppercase\n        // letter (Lu)\", \"Lowercase letter (Ll)\", \"Titlecase letter\n        // (Lt)\", \"Modifier letter (Lm)\", \"Other letter (Lo)\", or\n        // \"Letter number (Nl)\".\n        //\n        // Both approach and unicodeLetterTable were borrowed from\n        // Google's Traceur.\n\n        function isUnicodeLetter(code) {\n            for (var i = 0; i < unicodeLetterTable.length;) {\n                if (code < unicodeLetterTable[i++]) {\n                    return false;\n                }\n\n                if (code <= unicodeLetterTable[i++]) {\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        function isHexDigit(str) {\n            return (/^[0-9a-fA-F]$/).test(str);\n        }\n\n        var readUnicodeEscapeSequence = function () {\n            /*jshint validthis:true */\n            index += 1;\n\n            if (this.peek(index) !== \"u\") {\n                return null;\n            }\n\n            var ch1 = this.peek(index + 1);\n            var ch2 = this.peek(index + 2);\n            var ch3 = this.peek(index + 3);\n            var ch4 = this.peek(index + 4);\n            var code;\n\n            if (isHexDigit(ch1) && isHexDigit(ch2) && isHexDigit(ch3) && isHexDigit(ch4)) {\n                code = parseInt(ch1 + ch2 + ch3 + ch4, 16);\n\n                if (isUnicodeLetter(code)) {\n                    index += 5;\n                    return \"\\\\u\" + ch1 + ch2 + ch3 + ch4;\n                }\n\n                return null;\n            }\n\n            return null;\n        }.bind(this);\n\n        var getIdentifierStart = function () {\n            /*jshint validthis:true */\n            var chr = this.peek(index);\n            var code = chr.charCodeAt(0);\n\n            if (code === 92) {\n                return readUnicodeEscapeSequence();\n            }\n\n            if (code < 128) {\n                if (identifierStartTable[code]) {\n                    index += 1;\n                    return chr;\n                }\n\n                return null;\n            }\n\n            if (isUnicodeLetter(code)) {\n                index += 1;\n                return chr;\n            }\n\n            return null;\n        }.bind(this);\n\n        var getIdentifierPart = function () {\n            /*jshint validthis:true */\n            var chr = this.peek(index);\n            var code = chr.charCodeAt(0);\n\n            if (code === 92) {\n                return readUnicodeEscapeSequence();\n            }\n\n            if (code < 128) {\n                if (identifierPartTable[code]) {\n                    index += 1;\n                    return chr;\n                }\n\n                return null;\n            }\n\n            if (isUnicodeLetter(code)) {\n                index += 1;\n                return chr;\n            }\n\n            return null;\n        }.bind(this);\n\n        char = getIdentifierStart();\n        if (char === null) {\n            return null;\n        }\n\n        id = char;\n        for (;;) {\n            char = getIdentifierPart();\n\n            if (char === null) {\n                break;\n            }\n\n            id += char;\n        }\n\n        switch (id) {\n        case \"true\":\n        case \"false\":\n            type = Token.BooleanLiteral;\n            break;\n        case \"null\":\n            type = Token.NullLiteral;\n            break;\n        default:\n            type = Token.Identifier;\n        }\n\n        return {\n            type: type,\n            value: id\n        };\n    },\n\n    /*\n     * Extract a numeric literal out of the next sequence of\n     * characters or return 'null' if its not possible. This method\n     * supports all numeric literals described in section 7.8.3\n     * of the EcmaScript 5 specification.\n     *\n     * This method's implementation was heavily influenced by the\n     * scanNumericLiteral function in the Esprima parser's source code.\n     */\n    scanNumericLiteral: function () {\n        var index = 0;\n        var value = \"\";\n        var length = this.input.length;\n        var char = this.peek(index);\n        var bad;\n\n        function isDecimalDigit(str) {\n            return (/^[0-9]$/).test(str);\n        }\n\n        function isOctalDigit(str) {\n            return (/^[0-7]$/).test(str);\n        }\n\n        function isHexDigit(str) {\n            return (/^[0-9a-fA-F]$/).test(str);\n        }\n\n        function isIdentifierStart(ch) {\n            return (ch === \"$\") || (ch === \"_\") || (ch === \"\\\\\") ||\n                (ch >= \"a\" && ch <= \"z\") || (ch >= \"A\" && ch <= \"Z\");\n        }\n\n        // Numbers must start either with a decimal digit or a point.\n\n        if (char !== \".\" && !isDecimalDigit(char)) {\n            return null;\n        }\n\n        if (char !== \".\") {\n            value = this.peek(index);\n            index += 1;\n            char = this.peek(index);\n\n            if (value === \"0\") {\n                // Base-16 numbers.\n                if (char === \"x\" || char === \"X\") {\n                    index += 1;\n                    value += char;\n\n                    while (index < length) {\n                        char = this.peek(index);\n                        if (!isHexDigit(char)) {\n                            break;\n                        }\n                        value += char;\n                        index += 1;\n                    }\n\n                    if (value.length <= 2) { // 0x\n                        return {\n                            type: Token.NumericLiteral,\n                            value: value,\n                            isMalformed: true\n                        };\n                    }\n\n                    if (index < length) {\n                        char = this.peek(index);\n                        if (isIdentifierStart(char)) {\n                            return null;\n                        }\n                    }\n\n                    return {\n                        type: Token.NumericLiteral,\n                        value: value,\n                        base: 16,\n                        isMalformed: false\n                    };\n                }\n\n                // Base-8 numbers.\n                if (isOctalDigit(char)) {\n                    index += 1;\n                    value += char;\n                    bad = false;\n\n                    while (index < length) {\n                        char = this.peek(index);\n\n                        // Numbers like '019' (note the 9) are not valid octals\n                        // but we still parse them and mark as malformed.\n\n                        if (isDecimalDigit(char)) {\n                            bad = true;\n                        } else if (!isOctalDigit(char)) {\n                            break;\n                        }\n                        value += char;\n                        index += 1;\n                    }\n\n                    if (index < length) {\n                        char = this.peek(index);\n                        if (isIdentifierStart(char)) {\n                            return null;\n                        }\n                    }\n\n                    return {\n                        type: Token.NumericLiteral,\n                        value: value,\n                        base: 8,\n                        isMalformed: false\n                    };\n                }\n\n                // Decimal numbers that start with '0' such as '09' are illegal\n                // but we still parse them and return as malformed.\n\n                if (isDecimalDigit(char)) {\n                    index += 1;\n                    value += char;\n                }\n            }\n\n            while (index < length) {\n                char = this.peek(index);\n                if (!isDecimalDigit(char)) {\n                    break;\n                }\n                value += char;\n                index += 1;\n            }\n        }\n\n        // Decimal digits.\n\n        if (char === \".\") {\n            value += char;\n            index += 1;\n\n            while (index < length) {\n                char = this.peek(index);\n                if (!isDecimalDigit(char)) {\n                    break;\n                }\n                value += char;\n                index += 1;\n            }\n        }\n\n        // Exponent part.\n\n        if (char === \"e\" || char === \"E\") {\n            value += char;\n            index += 1;\n            char = this.peek(index);\n\n            if (char === \"+\" || char === \"-\") {\n                value += this.peek(index);\n                index += 1;\n            }\n\n            char = this.peek(index);\n            if (isDecimalDigit(char)) {\n                value += char;\n                index += 1;\n\n                while (index < length) {\n                    char = this.peek(index);\n                    if (!isDecimalDigit(char)) {\n                        break;\n                    }\n                    value += char;\n                    index += 1;\n                }\n            } else {\n                return null;\n            }\n        }\n\n        if (index < length) {\n            char = this.peek(index);\n            if (isIdentifierStart(char)) {\n                return null;\n            }\n        }\n\n        return {\n            type: Token.NumericLiteral,\n            value: value,\n            base: 10,\n            isMalformed: !isFinite(value)\n        };\n    },\n\n    /*\n     * Extract a string out of the next sequence of characters and/or\n     * lines or return 'null' if its not possible. Since strings can\n     * span across multiple lines this method has to move the char\n     * pointer.\n     *\n     * This method recognizes pseudo-multiline JavaScript strings:\n     *\n     *   var str = \"hello\\\n     *   world\";\n     */\n    scanStringLiteral: function (checks) {\n        /*jshint loopfunc:true */\n        var quote = this.peek();\n\n        // String must start with a quote.\n        if (quote !== \"\\\"\" && quote !== \"'\") {\n            return null;\n        }\n\n        // In JSON strings must always use double quotes.\n        this.triggerAsync(\"warning\", {\n            code: \"W108\",\n            line: this.line,\n            character: this.char // +1?\n        }, checks, function () { return state.jsonMode && quote !== \"\\\"\"; });\n\n        var value = \"\";\n        var startLine = this.line;\n        var startChar = this.char;\n        var allowNewLine = false;\n\n        this.skip();\n\n        while (this.peek() !== quote) {\n            while (this.peek() === \"\") { // End Of Line\n\n                // If an EOL is not preceded by a backslash, show a warning\n                // and proceed like it was a legit multi-line string where\n                // author simply forgot to escape the newline symbol.\n                //\n                // Another approach is to implicitly close a string on EOL\n                // but it generates too many false positives.\n\n                if (!allowNewLine) {\n                    this.trigger(\"warning\", {\n                        code: \"W112\",\n                        line: this.line,\n                        character: this.char\n                    });\n                } else {\n                    allowNewLine = false;\n\n                    // Otherwise show a warning if multistr option was not set.\n                    // For JSON, show warning no matter what.\n\n                    this.triggerAsync(\"warning\", {\n                        code: \"W043\",\n                        line: this.line,\n                        character: this.char\n                    }, checks, function () { return !state.option.multistr; });\n\n                    this.triggerAsync(\"warning\", {\n                        code: \"W042\",\n                        line: this.line,\n                        character: this.char\n                    }, checks, function () { return state.jsonMode && state.option.multistr; });\n                }\n\n                // If we get an EOF inside of an unclosed string, show an\n                // error and implicitly close it at the EOF point.\n\n                if (!this.nextLine()) {\n                    this.trigger(\"error\", {\n                        code: \"E029\",\n                        line: startLine,\n                        character: startChar\n                    });\n\n                    return {\n                        type: Token.StringLiteral,\n                        value: value,\n                        isUnclosed: true,\n                        quote: quote\n                    };\n                }\n            }\n\n            allowNewLine = false;\n            var char = this.peek();\n            var jump = 1; // A length of a jump, after we're done\n                          // parsing this character.\n\n            if (char < \" \") {\n                // Warn about a control character in a string.\n                this.trigger(\"warning\", {\n                    code: \"W113\",\n                    line: this.line,\n                    character: this.char,\n                    data: [ \"<non-printable>\" ]\n                });\n            }\n\n            // Special treatment for some escaped characters.\n\n            if (char === \"\\\\\") {\n                this.skip();\n                char = this.peek();\n\n                switch (char) {\n                case \"'\":\n                    this.triggerAsync(\"warning\", {\n                        code: \"W114\",\n                        line: this.line,\n                        character: this.char,\n                        data: [ \"\\\\'\" ]\n                    }, checks, function () {return state.jsonMode; });\n                    break;\n                case \"b\":\n                    char = \"\\b\";\n                    break;\n                case \"f\":\n                    char = \"\\f\";\n                    break;\n                case \"n\":\n                    char = \"\\n\";\n                    break;\n                case \"r\":\n                    char = \"\\r\";\n                    break;\n                case \"t\":\n                    char = \"\\t\";\n                    break;\n                case \"0\":\n                    char = \"\\0\";\n\n                    // Octal literals fail in strict mode.\n                    // Check if the number is between 00 and 07.\n                    var n = parseInt(this.peek(1), 10);\n                    this.triggerAsync(\"warning\", {\n                        code: \"W115\",\n                        line: this.line,\n                        character: this.char\n                    }, checks,\n                    function () { return n >= 0 && n <= 7 && state.directive[\"use strict\"]; });\n                    break;\n                case \"u\":\n                    char = String.fromCharCode(parseInt(this.input.substr(1, 4), 16));\n                    jump = 5;\n                    break;\n                case \"v\":\n                    this.triggerAsync(\"warning\", {\n                        code: \"W114\",\n                        line: this.line,\n                        character: this.char,\n                        data: [ \"\\\\v\" ]\n                    }, checks, function () { return state.jsonMode; });\n\n                    char = \"\\v\";\n                    break;\n                case \"x\":\n                    var x = parseInt(this.input.substr(1, 2), 16);\n\n                    this.triggerAsync(\"warning\", {\n                        code: \"W114\",\n                        line: this.line,\n                        character: this.char,\n                        data: [ \"\\\\x-\" ]\n                    }, checks, function () { return state.jsonMode; });\n\n                    char = String.fromCharCode(x);\n                    jump = 3;\n                    break;\n                case \"\\\\\":\n                case \"\\\"\":\n                case \"/\":\n                    break;\n                case \"\":\n                    allowNewLine = true;\n                    char = \"\";\n                    break;\n                case \"!\":\n                    if (value.slice(value.length - 2) === \"<\") {\n                        break;\n                    }\n\n                    /*falls through */\n                default:\n                    // Weird escaping.\n                    this.trigger(\"warning\", {\n                        code: \"W044\",\n                        line: this.line,\n                        character: this.char\n                    });\n                }\n            }\n\n            value += char;\n            this.skip(jump);\n        }\n\n        this.skip();\n        return {\n            type: Token.StringLiteral,\n            value: value,\n            isUnclosed: false,\n            quote: quote\n        };\n    },\n\n    /*\n     * Extract a regular expression out of the next sequence of\n     * characters and/or lines or return 'null' if its not possible.\n     *\n     * This method is platform dependent: it accepts almost any\n     * regular expression values but then tries to compile and run\n     * them using system's RegExp object. This means that there are\n     * rare edge cases where one JavaScript engine complains about\n     * your regular expression while others don't.\n     */\n    scanRegExp: function () {\n        var index = 0;\n        var length = this.input.length;\n        var char = this.peek();\n        var value = char;\n        var body = \"\";\n        var flags = [];\n        var malformed = false;\n        var isCharSet = false;\n        var terminated;\n\n        var scanUnexpectedChars = function () {\n            // Unexpected control character\n            if (char < \" \") {\n                malformed = true;\n                this.trigger(\"warning\", {\n                    code: \"W048\",\n                    line: this.line,\n                    character: this.char\n                });\n            }\n\n            // Unexpected escaped character\n            if (char === \"<\") {\n                malformed = true;\n                this.trigger(\"warning\", {\n                    code: \"W049\",\n                    line: this.line,\n                    character: this.char,\n                    data: [ char ]\n                });\n            }\n        }.bind(this);\n\n        // Regular expressions must start with '/'\n        if (!this.prereg || char !== \"/\") {\n            return null;\n        }\n\n        index += 1;\n        terminated = false;\n\n        // Try to get everything in between slashes. A couple of\n        // cases aside (see scanUnexpectedChars) we don't really\n        // care whether the resulting expression is valid or not.\n        // We will check that later using the RegExp object.\n\n        while (index < length) {\n            char = this.peek(index);\n            value += char;\n            body += char;\n\n            if (isCharSet) {\n                if (char === \"]\") {\n                    if (this.peek(index - 1) !== \"\\\\\" || this.peek(index - 2) === \"\\\\\") {\n                        isCharSet = false;\n                    }\n                }\n\n                if (char === \"\\\\\") {\n                    index += 1;\n                    char = this.peek(index);\n                    body += char;\n                    value += char;\n\n                    scanUnexpectedChars();\n                }\n\n                index += 1;\n                continue;\n            }\n\n            if (char === \"\\\\\") {\n                index += 1;\n                char = this.peek(index);\n                body += char;\n                value += char;\n\n                scanUnexpectedChars();\n\n                if (char === \"/\") {\n                    index += 1;\n                    continue;\n                }\n\n                if (char === \"[\") {\n                    index += 1;\n                    continue;\n                }\n            }\n\n            if (char === \"[\") {\n                isCharSet = true;\n                index += 1;\n                continue;\n            }\n\n            if (char === \"/\") {\n                body = body.substr(0, body.length - 1);\n                terminated = true;\n                index += 1;\n                break;\n            }\n\n            index += 1;\n        }\n\n        // A regular expression that was never closed is an\n        // error from which we cannot recover.\n\n        if (!terminated) {\n            this.trigger(\"error\", {\n                code: \"E015\",\n                line: this.line,\n                character: this.from\n            });\n\n            return void this.trigger(\"fatal\", {\n                line: this.line,\n                from: this.from\n            });\n        }\n\n        // Parse flags (if any).\n\n        while (index < length) {\n            char = this.peek(index);\n            if (!/[gim]/.test(char)) {\n                break;\n            }\n            flags.push(char);\n            value += char;\n            index += 1;\n        }\n\n        // Check regular expression for correctness.\n\n        try {\n            new RegExp(body, flags.join(\"\"));\n        } catch (err) {\n            malformed = true;\n            this.trigger(\"error\", {\n                code: \"E016\",\n                line: this.line,\n                character: this.char,\n                data: [ err.message ] // Platform dependent!\n            });\n        }\n\n        return {\n            type: Token.RegExp,\n            value: value,\n            flags: flags,\n            isMalformed: malformed\n        };\n    },\n\n    /*\n     * Scan for any occurence of mixed tabs and spaces. If smarttabs option\n     * is on, ignore tabs followed by spaces.\n     *\n     * Tabs followed by one space followed by a block comment are allowed.\n     */\n    scanMixedSpacesAndTabs: function () {\n        var at, match;\n\n        if (state.option.smarttabs) {\n            // Negative look-behind for \"//\"\n            match = this.input.match(/(\\/\\/|^\\s?\\*)? \\t/);\n            at = match && !match[1] ? 0 : -1;\n        } else {\n            at = this.input.search(/ \\t|\\t [^\\*]/);\n        }\n\n        return at;\n    },\n\n    /*\n     * Scan for characters that get silently deleted by one or more browsers.\n     */\n    scanUnsafeChars: function () {\n        return this.input.search(reg.unsafeChars);\n    },\n\n    /*\n     * Produce the next raw token or return 'null' if no tokens can be matched.\n     * This method skips over all space characters.\n     */\n    next: function (checks) {\n        this.from = this.char;\n\n        // Move to the next non-space character.\n        var start;\n        if (/\\s/.test(this.peek())) {\n            start = this.char;\n\n            while (/\\s/.test(this.peek())) {\n                this.from += 1;\n                this.skip();\n            }\n\n            if (this.peek() === \"\") { // EOL\n                if (!/^\\s*$/.test(this.getLines()[this.line - 1]) && state.option.trailing) {\n                    this.trigger(\"warning\", { code: \"W102\", line: this.line, character: start });\n                }\n            }\n        }\n\n        // Methods that work with multi-line structures and move the\n        // character pointer.\n\n        var match = this.scanComments() ||\n            this.scanStringLiteral(checks);\n\n        if (match) {\n            return match;\n        }\n\n        // Methods that don't move the character pointer.\n\n        match =\n            this.scanRegExp() ||\n            this.scanPunctuator() ||\n            this.scanKeyword() ||\n            this.scanIdentifier() ||\n            this.scanNumericLiteral();\n\n        if (match) {\n            this.skip(match.value.length);\n            return match;\n        }\n\n        // No token could be matched, give up.\n\n        return null;\n    },\n\n    /*\n     * Switch to the next line and reset all char pointers. Once\n     * switched, this method also checks for mixed spaces and tabs\n     * and other minor warnings.\n     */\n    nextLine: function () {\n        var char;\n\n        if (this.line >= this.getLines().length) {\n            return false;\n        }\n\n        this.input = this.getLines()[this.line];\n        this.line += 1;\n        this.char = 1;\n        this.from = 1;\n\n        char = this.scanMixedSpacesAndTabs();\n        if (char >= 0) {\n            this.trigger(\"warning\", { code: \"W099\", line: this.line, character: char + 1 });\n        }\n\n        this.input = this.input.replace(/\\t/g, state.tab);\n        char = this.scanUnsafeChars();\n\n        if (char >= 0) {\n            this.trigger(\"warning\", { code: \"W100\", line: this.line, character: char });\n        }\n\n        // If there is a limit on line length, warn when lines get too\n        // long.\n\n        if (state.option.maxlen && state.option.maxlen < this.input.length) {\n            this.trigger(\"warning\", { code: \"W101\", line: this.line, character: this.input.length });\n        }\n\n        return true;\n    },\n\n    /*\n     * This is simply a synonym for nextLine() method with a friendlier\n     * public name.\n     */\n    start: function () {\n        this.nextLine();\n    },\n\n    /*\n     * Produce the next token. This function is called by advance() to get\n     * the next token. It retuns a token in a JSLint-compatible format.\n     */\n    token: function () {\n        /*jshint loopfunc:true */\n        var checks = asyncTrigger();\n        var token;\n\n\n        function isReserved(token, isProperty) {\n            if (!token.reserved) {\n                return false;\n            }\n            var meta = token.meta;\n\n            if (meta && meta.isFutureReservedWord && state.option.inES5()) {\n                // ES3 FutureReservedWord in an ES5 environment.\n                if (!meta.es5) {\n                    return false;\n                }\n\n                // Some ES5 FutureReservedWord identifiers are active only\n                // within a strict mode environment.\n                if (meta.strictOnly) {\n                    if (!state.option.strict && !state.directive[\"use strict\"]) {\n                        return false;\n                    }\n                }\n\n                if (isProperty) {\n                    return false;\n                }\n            }\n\n            return true;\n        }\n\n        // Produce a token object.\n        var create = function (type, value, isProperty) {\n            /*jshint validthis:true */\n            var obj;\n\n            if (type !== \"(endline)\" && type !== \"(end)\") {\n                this.prereg = false;\n            }\n\n            if (type === \"(punctuator)\") {\n                switch (value) {\n                case \".\":\n                case \")\":\n                case \"~\":\n                case \"#\":\n                case \"]\":\n                    this.prereg = false;\n                    break;\n                default:\n                    this.prereg = true;\n                }\n\n                obj = Object.create(state.syntax[value] || state.syntax[\"(error)\"]);\n            }\n\n            if (type === \"(identifier)\") {\n                if (value === \"return\" || value === \"case\" || value === \"typeof\") {\n                    this.prereg = true;\n                }\n\n                if (_.has(state.syntax, value)) {\n                    obj = Object.create(state.syntax[value] || state.syntax[\"(error)\"]);\n\n                    // If this can't be a reserved keyword, reset the object.\n                    if (!isReserved(obj, isProperty && type === \"(identifier)\")) {\n                        obj = null;\n                    }\n                }\n            }\n\n            if (!obj) {\n                obj = Object.create(state.syntax[type]);\n            }\n\n            obj.identifier = (type === \"(identifier)\");\n            obj.type = obj.type || type;\n            obj.value = value;\n            obj.line = this.line;\n            obj.character = this.char;\n            obj.from = this.from;\n\n            if (isProperty && obj.identifier) {\n                obj.isProperty = isProperty;\n            }\n\n            obj.check = checks.check;\n\n            return obj;\n        }.bind(this);\n\n        for (;;) {\n            if (!this.input.length) {\n                return create(this.nextLine() ? \"(endline)\" : \"(end)\", \"\");\n            }\n\n            token = this.next(checks);\n\n            if (!token) {\n                if (this.input.length) {\n                    // Unexpected character.\n                    this.trigger(\"error\", {\n                        code: \"E024\",\n                        line: this.line,\n                        character: this.char,\n                        data: [ this.peek() ]\n                    });\n\n                    this.input = \"\";\n                }\n\n                continue;\n            }\n\n            switch (token.type) {\n            case Token.StringLiteral:\n                this.triggerAsync(\"String\", {\n                    line: this.line,\n                    char: this.char,\n                    from: this.from,\n                    value: token.value,\n                    quote: token.quote\n                }, checks, function () { return true; });\n\n                return create(\"(string)\", token.value);\n            case Token.Identifier:\n                this.trigger(\"Identifier\", {\n                    line: this.line,\n                    char: this.char,\n                    from: this.form,\n                    name: token.value,\n                    isProperty: state.tokens.curr.id === \".\"\n                });\n\n                /* falls through */\n            case Token.Keyword:\n            case Token.NullLiteral:\n            case Token.BooleanLiteral:\n                return create(\"(identifier)\", token.value, state.tokens.curr.id === \".\");\n\n            case Token.NumericLiteral:\n                if (token.isMalformed) {\n                    this.trigger(\"warning\", {\n                        code: \"W045\",\n                        line: this.line,\n                        character: this.char,\n                        data: [ token.value ]\n                    });\n                }\n\n                this.triggerAsync(\"warning\", {\n                    code: \"W114\",\n                    line: this.line,\n                    character: this.char,\n                    data: [ \"0x-\" ]\n                }, checks, function () { return token.base === 16 && state.jsonMode; });\n\n                this.triggerAsync(\"warning\", {\n                    code: \"W115\",\n                    line: this.line,\n                    character: this.char\n                }, checks, function () {\n                    return state.directive[\"use strict\"] && token.base === 8;\n                });\n\n                this.trigger(\"Number\", {\n                    line: this.line,\n                    char: this.char,\n                    from: this.from,\n                    value: token.value,\n                    base: token.base,\n                    isMalformed: token.malformed\n                });\n\n                return create(\"(number)\", token.value);\n\n            case Token.RegExp:\n                return create(\"(regexp)\", token.value);\n\n            case Token.Comment:\n                state.tokens.curr.comment = true;\n\n                if (token.isSpecial) {\n                    return {\n                        value: token.value,\n                        body: token.body,\n                        type: token.commentType,\n                        isSpecial: token.isSpecial,\n                        line: this.line,\n                        character: this.char,\n                        from: this.from\n                    };\n                }\n\n                break;\n\n            case \"\":\n                break;\n\n            default:\n                return create(\"(punctuator)\", token.value);\n            }\n        }\n    }\n};\n\nexports.Lexer = Lexer;\n\n})()\n},{\"events\":2,\"./state.js\":6,\"./reg.js\":4,\"underscore\":10}],9:[function(require,module,exports){\n(function(global){/*global window, global*/\nvar util = require(\"util\")\nvar assert = require(\"assert\")\n\nvar slice = Array.prototype.slice\nvar console\nvar times = {}\n\nif (typeof global !== \"undefined\" && global.console) {\n    console = global.console\n} else if (typeof window !== \"undefined\" && window.console) {\n    console = window.console\n} else {\n    console = window.console = {}\n}\n\nvar functions = [\n    [log, \"log\"]\n    , [info, \"info\"]\n    , [warn, \"warn\"]\n    , [error, \"error\"]\n    , [time, \"time\"]\n    , [timeEnd, \"timeEnd\"]\n    , [trace, \"trace\"]\n    , [dir, \"dir\"]\n    , [assert, \"assert\"]\n]\n\nfor (var i = 0; i < functions.length; i++) {\n    var tuple = functions[i]\n    var f = tuple[0]\n    var name = tuple[1]\n\n    if (!console[name]) {\n        console[name] = f\n    }\n}\n\nmodule.exports = console\n\nfunction log() {}\n\nfunction info() {\n    console.log.apply(console, arguments)\n}\n\nfunction warn() {\n    console.log.apply(console, arguments)\n}\n\nfunction error() {\n    console.warn.apply(console, arguments)\n}\n\nfunction time(label) {\n    times[label] = Date.now()\n}\n\nfunction timeEnd(label) {\n    var time = times[label]\n    if (!time) {\n        throw new Error(\"No such label: \" + label)\n    }\n\n    var duration = Date.now() - time\n    console.log(label + \": \" + duration + \"ms\")\n}\n\nfunction trace() {\n    var err = new Error()\n    err.name = \"Trace\"\n    err.message = util.format.apply(null, arguments)\n    console.error(err.stack)\n}\n\nfunction dir(object) {\n    console.log(util.inspect(object) + \"\\n\")\n}\n\nfunction assert(expression) {\n    if (!expression) {\n        var arr = slice.call(arguments, 1)\n        assert.ok(false, util.format.apply(null, arr))\n    }\n}\n\n})(window)\n},{\"util\":11,\"assert\":12}],10:[function(require,module,exports){\n(function(){//     Underscore.js 1.4.4\n//     http://underscorejs.org\n//     (c) 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.\n//     Underscore may be freely distributed under the MIT license.\n\n(function() {\n\n  // Baseline setup\n  // --------------\n\n  // Establish the root object, `window` in the browser, or `global` on the server.\n  var root = this;\n\n  // Save the previous value of the `_` variable.\n  var previousUnderscore = root._;\n\n  // Establish the object that gets returned to break out of a loop iteration.\n  var breaker = {};\n\n  // Save bytes in the minified (but not gzipped) version:\n  var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;\n\n  // Create quick reference variables for speed access to core prototypes.\n  var push             = ArrayProto.push,\n      slice            = ArrayProto.slice,\n      concat           = ArrayProto.concat,\n      toString         = ObjProto.toString,\n      hasOwnProperty   = ObjProto.hasOwnProperty;\n\n  // All **ECMAScript 5** native function implementations that we hope to use\n  // are declared here.\n  var\n    nativeForEach      = ArrayProto.forEach,\n    nativeMap          = ArrayProto.map,\n    nativeReduce       = ArrayProto.reduce,\n    nativeReduceRight  = ArrayProto.reduceRight,\n    nativeFilter       = ArrayProto.filter,\n    nativeEvery        = ArrayProto.every,\n    nativeSome         = ArrayProto.some,\n    nativeIndexOf      = ArrayProto.indexOf,\n    nativeLastIndexOf  = ArrayProto.lastIndexOf,\n    nativeIsArray      = Array.isArray,\n    nativeKeys         = Object.keys,\n    nativeBind         = FuncProto.bind;\n\n  // Create a safe reference to the Underscore object for use below.\n  var _ = function(obj) {\n    if (obj instanceof _) return obj;\n    if (!(this instanceof _)) return new _(obj);\n    this._wrapped = obj;\n  };\n\n  // Export the Underscore object for **Node.js**, with\n  // backwards-compatibility for the old `require()` API. If we're in\n  // the browser, add `_` as a global object via a string identifier,\n  // for Closure Compiler \"advanced\" mode.\n  if (typeof exports !== 'undefined') {\n    if (typeof module !== 'undefined' && module.exports) {\n      exports = module.exports = _;\n    }\n    exports._ = _;\n  } else {\n    root._ = _;\n  }\n\n  // Current version.\n  _.VERSION = '1.4.4';\n\n  // Collection Functions\n  // --------------------\n\n  // The cornerstone, an `each` implementation, aka `forEach`.\n  // Handles objects with the built-in `forEach`, arrays, and raw objects.\n  // Delegates to **ECMAScript 5**'s native `forEach` if available.\n  var each = _.each = _.forEach = function(obj, iterator, context) {\n    if (obj == null) return;\n    if (nativeForEach && obj.forEach === nativeForEach) {\n      obj.forEach(iterator, context);\n    } else if (obj.length === +obj.length) {\n      for (var i = 0, l = obj.length; i < l; i++) {\n        if (iterator.call(context, obj[i], i, obj) === breaker) return;\n      }\n    } else {\n      for (var key in obj) {\n        if (_.has(obj, key)) {\n          if (iterator.call(context, obj[key], key, obj) === breaker) return;\n        }\n      }\n    }\n  };\n\n  // Return the results of applying the iterator to each element.\n  // Delegates to **ECMAScript 5**'s native `map` if available.\n  _.map = _.collect = function(obj, iterator, context) {\n    var results = [];\n    if (obj == null) return results;\n    if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);\n    each(obj, function(value, index, list) {\n      results[results.length] = iterator.call(context, value, index, list);\n    });\n    return results;\n  };\n\n  var reduceError = 'Reduce of empty array with no initial value';\n\n  // **Reduce** builds up a single result from a list of values, aka `inject`,\n  // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.\n  _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {\n    var initial = arguments.length > 2;\n    if (obj == null) obj = [];\n    if (nativeReduce && obj.reduce === nativeReduce) {\n      if (context) iterator = _.bind(iterator, context);\n      return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);\n    }\n    each(obj, function(value, index, list) {\n      if (!initial) {\n        memo = value;\n        initial = true;\n      } else {\n        memo = iterator.call(context, memo, value, index, list);\n      }\n    });\n    if (!initial) throw new TypeError(reduceError);\n    return memo;\n  };\n\n  // The right-associative version of reduce, also known as `foldr`.\n  // Delegates to **ECMAScript 5**'s native `reduceRight` if available.\n  _.reduceRight = _.foldr = function(obj, iterator, memo, context) {\n    var initial = arguments.length > 2;\n    if (obj == null) obj = [];\n    if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {\n      if (context) iterator = _.bind(iterator, context);\n      return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);\n    }\n    var length = obj.length;\n    if (length !== +length) {\n      var keys = _.keys(obj);\n      length = keys.length;\n    }\n    each(obj, function(value, index, list) {\n      index = keys ? keys[--length] : --length;\n      if (!initial) {\n        memo = obj[index];\n        initial = true;\n      } else {\n        memo = iterator.call(context, memo, obj[index], index, list);\n      }\n    });\n    if (!initial) throw new TypeError(reduceError);\n    return memo;\n  };\n\n  // Return the first value which passes a truth test. Aliased as `detect`.\n  _.find = _.detect = function(obj, iterator, context) {\n    var result;\n    any(obj, function(value, index, list) {\n      if (iterator.call(context, value, index, list)) {\n        result = value;\n        return true;\n      }\n    });\n    return result;\n  };\n\n  // Return all the elements that pass a truth test.\n  // Delegates to **ECMAScript 5**'s native `filter` if available.\n  // Aliased as `select`.\n  _.filter = _.select = function(obj, iterator, context) {\n    var results = [];\n    if (obj == null) return results;\n    if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);\n    each(obj, function(value, index, list) {\n      if (iterator.call(context, value, index, list)) results[results.length] = value;\n    });\n    return results;\n  };\n\n  // Return all the elements for which a truth test fails.\n  _.reject = function(obj, iterator, context) {\n    return _.filter(obj, function(value, index, list) {\n      return !iterator.call(context, value, index, list);\n    }, context);\n  };\n\n  // Determine whether all of the elements match a truth test.\n  // Delegates to **ECMAScript 5**'s native `every` if available.\n  // Aliased as `all`.\n  _.every = _.all = function(obj, iterator, context) {\n    iterator || (iterator = _.identity);\n    var result = true;\n    if (obj == null) return result;\n    if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);\n    each(obj, function(value, index, list) {\n      if (!(result = result && iterator.call(context, value, index, list))) return breaker;\n    });\n    return !!result;\n  };\n\n  // Determine if at least one element in the object matches a truth test.\n  // Delegates to **ECMAScript 5**'s native `some` if available.\n  // Aliased as `any`.\n  var any = _.some = _.any = function(obj, iterator, context) {\n    iterator || (iterator = _.identity);\n    var result = false;\n    if (obj == null) return result;\n    if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);\n    each(obj, function(value, index, list) {\n      if (result || (result = iterator.call(context, value, index, list))) return breaker;\n    });\n    return !!result;\n  };\n\n  // Determine if the array or object contains a given value (using `===`).\n  // Aliased as `include`.\n  _.contains = _.include = function(obj, target) {\n    if (obj == null) return false;\n    if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;\n    return any(obj, function(value) {\n      return value === target;\n    });\n  };\n\n  // Invoke a method (with arguments) on every item in a collection.\n  _.invoke = function(obj, method) {\n    var args = slice.call(arguments, 2);\n    var isFunc = _.isFunction(method);\n    return _.map(obj, function(value) {\n      return (isFunc ? method : value[method]).apply(value, args);\n    });\n  };\n\n  // Convenience version of a common use case of `map`: fetching a property.\n  _.pluck = function(obj, key) {\n    return _.map(obj, function(value){ return value[key]; });\n  };\n\n  // Convenience version of a common use case of `filter`: selecting only objects\n  // containing specific `key:value` pairs.\n  _.where = function(obj, attrs, first) {\n    if (_.isEmpty(attrs)) return first ? null : [];\n    return _[first ? 'find' : 'filter'](obj, function(value) {\n      for (var key in attrs) {\n        if (attrs[key] !== value[key]) return false;\n      }\n      return true;\n    });\n  };\n\n  // Convenience version of a common use case of `find`: getting the first object\n  // containing specific `key:value` pairs.\n  _.findWhere = function(obj, attrs) {\n    return _.where(obj, attrs, true);\n  };\n\n  // Return the maximum element or (element-based computation).\n  // Can't optimize arrays of integers longer than 65,535 elements.\n  // See: https://bugs.webkit.org/show_bug.cgi?id=80797\n  _.max = function(obj, iterator, context) {\n    if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {\n      return Math.max.apply(Math, obj);\n    }\n    if (!iterator && _.isEmpty(obj)) return -Infinity;\n    var result = {computed : -Infinity, value: -Infinity};\n    each(obj, function(value, index, list) {\n      var computed = iterator ? iterator.call(context, value, index, list) : value;\n      computed >= result.computed && (result = {value : value, computed : computed});\n    });\n    return result.value;\n  };\n\n  // Return the minimum element (or element-based computation).\n  _.min = function(obj, iterator, context) {\n    if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {\n      return Math.min.apply(Math, obj);\n    }\n    if (!iterator && _.isEmpty(obj)) return Infinity;\n    var result = {computed : Infinity, value: Infinity};\n    each(obj, function(value, index, list) {\n      var computed = iterator ? iterator.call(context, value, index, list) : value;\n      computed < result.computed && (result = {value : value, computed : computed});\n    });\n    return result.value;\n  };\n\n  // Shuffle an array.\n  _.shuffle = function(obj) {\n    var rand;\n    var index = 0;\n    var shuffled = [];\n    each(obj, function(value) {\n      rand = _.random(index++);\n      shuffled[index - 1] = shuffled[rand];\n      shuffled[rand] = value;\n    });\n    return shuffled;\n  };\n\n  // An internal function to generate lookup iterators.\n  var lookupIterator = function(value) {\n    return _.isFunction(value) ? value : function(obj){ return obj[value]; };\n  };\n\n  // Sort the object's values by a criterion produced by an iterator.\n  _.sortBy = function(obj, value, context) {\n    var iterator = lookupIterator(value);\n    return _.pluck(_.map(obj, function(value, index, list) {\n      return {\n        value : value,\n        index : index,\n        criteria : iterator.call(context, value, index, list)\n      };\n    }).sort(function(left, right) {\n      var a = left.criteria;\n      var b = right.criteria;\n      if (a !== b) {\n        if (a > b || a === void 0) return 1;\n        if (a < b || b === void 0) return -1;\n      }\n      return left.index < right.index ? -1 : 1;\n    }), 'value');\n  };\n\n  // An internal function used for aggregate \"group by\" operations.\n  var group = function(obj, value, context, behavior) {\n    var result = {};\n    var iterator = lookupIterator(value || _.identity);\n    each(obj, function(value, index) {\n      var key = iterator.call(context, value, index, obj);\n      behavior(result, key, value);\n    });\n    return result;\n  };\n\n  // Groups the object's values by a criterion. Pass either a string attribute\n  // to group by, or a function that returns the criterion.\n  _.groupBy = function(obj, value, context) {\n    return group(obj, value, context, function(result, key, value) {\n      (_.has(result, key) ? result[key] : (result[key] = [])).push(value);\n    });\n  };\n\n  // Counts instances of an object that group by a certain criterion. Pass\n  // either a string attribute to count by, or a function that returns the\n  // criterion.\n  _.countBy = function(obj, value, context) {\n    return group(obj, value, context, function(result, key) {\n      if (!_.has(result, key)) result[key] = 0;\n      result[key]++;\n    });\n  };\n\n  // Use a comparator function to figure out the smallest index at which\n  // an object should be inserted so as to maintain order. Uses binary search.\n  _.sortedIndex = function(array, obj, iterator, context) {\n    iterator = iterator == null ? _.identity : lookupIterator(iterator);\n    var value = iterator.call(context, obj);\n    var low = 0, high = array.length;\n    while (low < high) {\n      var mid = (low + high) >>> 1;\n      iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;\n    }\n    return low;\n  };\n\n  // Safely convert anything iterable into a real, live array.\n  _.toArray = function(obj) {\n    if (!obj) return [];\n    if (_.isArray(obj)) return slice.call(obj);\n    if (obj.length === +obj.length) return _.map(obj, _.identity);\n    return _.values(obj);\n  };\n\n  // Return the number of elements in an object.\n  _.size = function(obj) {\n    if (obj == null) return 0;\n    return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;\n  };\n\n  // Array Functions\n  // ---------------\n\n  // Get the first element of an array. Passing **n** will return the first N\n  // values in the array. Aliased as `head` and `take`. The **guard** check\n  // allows it to work with `_.map`.\n  _.first = _.head = _.take = function(array, n, guard) {\n    if (array == null) return void 0;\n    return (n != null) && !guard ? slice.call(array, 0, n) : array[0];\n  };\n\n  // Returns everything but the last entry of the array. Especially useful on\n  // the arguments object. Passing **n** will return all the values in\n  // the array, excluding the last N. The **guard** check allows it to work with\n  // `_.map`.\n  _.initial = function(array, n, guard) {\n    return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));\n  };\n\n  // Get the last element of an array. Passing **n** will return the last N\n  // values in the array. The **guard** check allows it to work with `_.map`.\n  _.last = function(array, n, guard) {\n    if (array == null) return void 0;\n    if ((n != null) && !guard) {\n      return slice.call(array, Math.max(array.length - n, 0));\n    } else {\n      return array[array.length - 1];\n    }\n  };\n\n  // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.\n  // Especially useful on the arguments object. Passing an **n** will return\n  // the rest N values in the array. The **guard**\n  // check allows it to work with `_.map`.\n  _.rest = _.tail = _.drop = function(array, n, guard) {\n    return slice.call(array, (n == null) || guard ? 1 : n);\n  };\n\n  // Trim out all falsy values from an array.\n  _.compact = function(array) {\n    return _.filter(array, _.identity);\n  };\n\n  // Internal implementation of a recursive `flatten` function.\n  var flatten = function(input, shallow, output) {\n    each(input, function(value) {\n      if (_.isArray(value)) {\n        shallow ? push.apply(output, value) : flatten(value, shallow, output);\n      } else {\n        output.push(value);\n      }\n    });\n    return output;\n  };\n\n  // Return a completely flattened version of an array.\n  _.flatten = function(array, shallow) {\n    return flatten(array, shallow, []);\n  };\n\n  // Return a version of the array that does not contain the specified value(s).\n  _.without = function(array) {\n    return _.difference(array, slice.call(arguments, 1));\n  };\n\n  // Produce a duplicate-free version of the array. If the array has already\n  // been sorted, you have the option of using a faster algorithm.\n  // Aliased as `unique`.\n  _.uniq = _.unique = function(array, isSorted, iterator, context) {\n    if (_.isFunction(isSorted)) {\n      context = iterator;\n      iterator = isSorted;\n      isSorted = false;\n    }\n    var initial = iterator ? _.map(array, iterator, context) : array;\n    var results = [];\n    var seen = [];\n    each(initial, function(value, index) {\n      if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) {\n        seen.push(value);\n        results.push(array[index]);\n      }\n    });\n    return results;\n  };\n\n  // Produce an array that contains the union: each distinct element from all of\n  // the passed-in arrays.\n  _.union = function() {\n    return _.uniq(concat.apply(ArrayProto, arguments));\n  };\n\n  // Produce an array that contains every item shared between all the\n  // passed-in arrays.\n  _.intersection = function(array) {\n    var rest = slice.call(arguments, 1);\n    return _.filter(_.uniq(array), function(item) {\n      return _.every(rest, function(other) {\n        return _.indexOf(other, item) >= 0;\n      });\n    });\n  };\n\n  // Take the difference between one array and a number of other arrays.\n  // Only the elements present in just the first array will remain.\n  _.difference = function(array) {\n    var rest = concat.apply(ArrayProto, slice.call(arguments, 1));\n    return _.filter(array, function(value){ return !_.contains(rest, value); });\n  };\n\n  // Zip together multiple lists into a single array -- elements that share\n  // an index go together.\n  _.zip = function() {\n    var args = slice.call(arguments);\n    var length = _.max(_.pluck(args, 'length'));\n    var results = new Array(length);\n    for (var i = 0; i < length; i++) {\n      results[i] = _.pluck(args, \"\" + i);\n    }\n    return results;\n  };\n\n  // Converts lists into objects. Pass either a single array of `[key, value]`\n  // pairs, or two parallel arrays of the same length -- one of keys, and one of\n  // the corresponding values.\n  _.object = function(list, values) {\n    if (list == null) return {};\n    var result = {};\n    for (var i = 0, l = list.length; i < l; i++) {\n      if (values) {\n        result[list[i]] = values[i];\n      } else {\n        result[list[i][0]] = list[i][1];\n      }\n    }\n    return result;\n  };\n\n  // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),\n  // we need this function. Return the position of the first occurrence of an\n  // item in an array, or -1 if the item is not included in the array.\n  // Delegates to **ECMAScript 5**'s native `indexOf` if available.\n  // If the array is large and already in sort order, pass `true`\n  // for **isSorted** to use binary search.\n  _.indexOf = function(array, item, isSorted) {\n    if (array == null) return -1;\n    var i = 0, l = array.length;\n    if (isSorted) {\n      if (typeof isSorted == 'number') {\n        i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted);\n      } else {\n        i = _.sortedIndex(array, item);\n        return array[i] === item ? i : -1;\n      }\n    }\n    if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);\n    for (; i < l; i++) if (array[i] === item) return i;\n    return -1;\n  };\n\n  // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.\n  _.lastIndexOf = function(array, item, from) {\n    if (array == null) return -1;\n    var hasIndex = from != null;\n    if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) {\n      return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item);\n    }\n    var i = (hasIndex ? from : array.length);\n    while (i--) if (array[i] === item) return i;\n    return -1;\n  };\n\n  // Generate an integer Array containing an arithmetic progression. A port of\n  // the native Python `range()` function. See\n  // [the Python documentation](http://docs.python.org/library/functions.html#range).\n  _.range = function(start, stop, step) {\n    if (arguments.length <= 1) {\n      stop = start || 0;\n      start = 0;\n    }\n    step = arguments[2] || 1;\n\n    var len = Math.max(Math.ceil((stop - start) / step), 0);\n    var idx = 0;\n    var range = new Array(len);\n\n    while(idx < len) {\n      range[idx++] = start;\n      start += step;\n    }\n\n    return range;\n  };\n\n  // Function (ahem) Functions\n  // ------------------\n\n  // Create a function bound to a given object (assigning `this`, and arguments,\n  // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if\n  // available.\n  _.bind = function(func, context) {\n    if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));\n    var args = slice.call(arguments, 2);\n    return function() {\n      return func.apply(context, args.concat(slice.call(arguments)));\n    };\n  };\n\n  // Partially apply a function by creating a version that has had some of its\n  // arguments pre-filled, without changing its dynamic `this` context.\n  _.partial = function(func) {\n    var args = slice.call(arguments, 1);\n    return function() {\n      return func.apply(this, args.concat(slice.call(arguments)));\n    };\n  };\n\n  // Bind all of an object's methods to that object. Useful for ensuring that\n  // all callbacks defined on an object belong to it.\n  _.bindAll = function(obj) {\n    var funcs = slice.call(arguments, 1);\n    if (funcs.length === 0) funcs = _.functions(obj);\n    each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });\n    return obj;\n  };\n\n  // Memoize an expensive function by storing its results.\n  _.memoize = function(func, hasher) {\n    var memo = {};\n    hasher || (hasher = _.identity);\n    return function() {\n      var key = hasher.apply(this, arguments);\n      return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));\n    };\n  };\n\n  // Delays a function for the given number of milliseconds, and then calls\n  // it with the arguments supplied.\n  _.delay = function(func, wait) {\n    var args = slice.call(arguments, 2);\n    return setTimeout(function(){ return func.apply(null, args); }, wait);\n  };\n\n  // Defers a function, scheduling it to run after the current call stack has\n  // cleared.\n  _.defer = function(func) {\n    return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));\n  };\n\n  // Returns a function, that, when invoked, will only be triggered at most once\n  // during a given window of time.\n  _.throttle = function(func, wait) {\n    var context, args, timeout, result;\n    var previous = 0;\n    var later = function() {\n      previous = new Date;\n      timeout = null;\n      result = func.apply(context, args);\n    };\n    return function() {\n      var now = new Date;\n      var remaining = wait - (now - previous);\n      context = this;\n      args = arguments;\n      if (remaining <= 0) {\n        clearTimeout(timeout);\n        timeout = null;\n        previous = now;\n        result = func.apply(context, args);\n      } else if (!timeout) {\n        timeout = setTimeout(later, remaining);\n      }\n      return result;\n    };\n  };\n\n  // Returns a function, that, as long as it continues to be invoked, will not\n  // be triggered. The function will be called after it stops being called for\n  // N milliseconds. If `immediate` is passed, trigger the function on the\n  // leading edge, instead of the trailing.\n  _.debounce = function(func, wait, immediate) {\n    var timeout, result;\n    return function() {\n      var context = this, args = arguments;\n      var later = function() {\n        timeout = null;\n        if (!immediate) result = func.apply(context, args);\n      };\n      var callNow = immediate && !timeout;\n      clearTimeout(timeout);\n      timeout = setTimeout(later, wait);\n      if (callNow) result = func.apply(context, args);\n      return result;\n    };\n  };\n\n  // Returns a function that will be executed at most one time, no matter how\n  // often you call it. Useful for lazy initialization.\n  _.once = function(func) {\n    var ran = false, memo;\n    return function() {\n      if (ran) return memo;\n      ran = true;\n      memo = func.apply(this, arguments);\n      func = null;\n      return memo;\n    };\n  };\n\n  // Returns the first function passed as an argument to the second,\n  // allowing you to adjust arguments, run code before and after, and\n  // conditionally execute the original function.\n  _.wrap = function(func, wrapper) {\n    return function() {\n      var args = [func];\n      push.apply(args, arguments);\n      return wrapper.apply(this, args);\n    };\n  };\n\n  // Returns a function that is the composition of a list of functions, each\n  // consuming the return value of the function that follows.\n  _.compose = function() {\n    var funcs = arguments;\n    return function() {\n      var args = arguments;\n      for (var i = funcs.length - 1; i >= 0; i--) {\n        args = [funcs[i].apply(this, args)];\n      }\n      return args[0];\n    };\n  };\n\n  // Returns a function that will only be executed after being called N times.\n  _.after = function(times, func) {\n    if (times <= 0) return func();\n    return function() {\n      if (--times < 1) {\n        return func.apply(this, arguments);\n      }\n    };\n  };\n\n  // Object Functions\n  // ----------------\n\n  // Retrieve the names of an object's properties.\n  // Delegates to **ECMAScript 5**'s native `Object.keys`\n  _.keys = nativeKeys || function(obj) {\n    if (obj !== Object(obj)) throw new TypeError('Invalid object');\n    var keys = [];\n    for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;\n    return keys;\n  };\n\n  // Retrieve the values of an object's properties.\n  _.values = function(obj) {\n    var values = [];\n    for (var key in obj) if (_.has(obj, key)) values.push(obj[key]);\n    return values;\n  };\n\n  // Convert an object into a list of `[key, value]` pairs.\n  _.pairs = function(obj) {\n    var pairs = [];\n    for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]);\n    return pairs;\n  };\n\n  // Invert the keys and values of an object. The values must be serializable.\n  _.invert = function(obj) {\n    var result = {};\n    for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key;\n    return result;\n  };\n\n  // Return a sorted list of the function names available on the object.\n  // Aliased as `methods`\n  _.functions = _.methods = function(obj) {\n    var names = [];\n    for (var key in obj) {\n      if (_.isFunction(obj[key])) names.push(key);\n    }\n    return names.sort();\n  };\n\n  // Extend a given object with all the properties in passed-in object(s).\n  _.extend = function(obj) {\n    each(slice.call(arguments, 1), function(source) {\n      if (source) {\n        for (var prop in source) {\n          obj[prop] = source[prop];\n        }\n      }\n    });\n    return obj;\n  };\n\n  // Return a copy of the object only containing the whitelisted properties.\n  _.pick = function(obj) {\n    var copy = {};\n    var keys = concat.apply(ArrayProto, slice.call(arguments, 1));\n    each(keys, function(key) {\n      if (key in obj) copy[key] = obj[key];\n    });\n    return copy;\n  };\n\n   // Return a copy of the object without the blacklisted properties.\n  _.omit = function(obj) {\n    var copy = {};\n    var keys = concat.apply(ArrayProto, slice.call(arguments, 1));\n    for (var key in obj) {\n      if (!_.contains(keys, key)) copy[key] = obj[key];\n    }\n    return copy;\n  };\n\n  // Fill in a given object with default properties.\n  _.defaults = function(obj) {\n    each(slice.call(arguments, 1), function(source) {\n      if (source) {\n        for (var prop in source) {\n          if (obj[prop] == null) obj[prop] = source[prop];\n        }\n      }\n    });\n    return obj;\n  };\n\n  // Create a (shallow-cloned) duplicate of an object.\n  _.clone = function(obj) {\n    if (!_.isObject(obj)) return obj;\n    return _.isArray(obj) ? obj.slice() : _.extend({}, obj);\n  };\n\n  // Invokes interceptor with the obj, and then returns obj.\n  // The primary purpose of this method is to \"tap into\" a method chain, in\n  // order to perform operations on intermediate results within the chain.\n  _.tap = function(obj, interceptor) {\n    interceptor(obj);\n    return obj;\n  };\n\n  // Internal recursive comparison function for `isEqual`.\n  var eq = function(a, b, aStack, bStack) {\n    // Identical objects are equal. `0 === -0`, but they aren't identical.\n    // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.\n    if (a === b) return a !== 0 || 1 / a == 1 / b;\n    // A strict comparison is necessary because `null == undefined`.\n    if (a == null || b == null) return a === b;\n    // Unwrap any wrapped objects.\n    if (a instanceof _) a = a._wrapped;\n    if (b instanceof _) b = b._wrapped;\n    // Compare `[[Class]]` names.\n    var className = toString.call(a);\n    if (className != toString.call(b)) return false;\n    switch (className) {\n      // Strings, numbers, dates, and booleans are compared by value.\n      case '[object String]':\n        // Primitives and their corresponding object wrappers are equivalent; thus, `\"5\"` is\n        // equivalent to `new String(\"5\")`.\n        return a == String(b);\n      case '[object Number]':\n        // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for\n        // other numeric values.\n        return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);\n      case '[object Date]':\n      case '[object Boolean]':\n        // Coerce dates and booleans to numeric primitive values. Dates are compared by their\n        // millisecond representations. Note that invalid dates with millisecond representations\n        // of `NaN` are not equivalent.\n        return +a == +b;\n      // RegExps are compared by their source patterns and flags.\n      case '[object RegExp]':\n        return a.source == b.source &&\n               a.global == b.global &&\n               a.multiline == b.multiline &&\n               a.ignoreCase == b.ignoreCase;\n    }\n    if (typeof a != 'object' || typeof b != 'object') return false;\n    // Assume equality for cyclic structures. The algorithm for detecting cyclic\n    // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.\n    var length = aStack.length;\n    while (length--) {\n      // Linear search. Performance is inversely proportional to the number of\n      // unique nested structures.\n      if (aStack[length] == a) return bStack[length] == b;\n    }\n    // Add the first object to the stack of traversed objects.\n    aStack.push(a);\n    bStack.push(b);\n    var size = 0, result = true;\n    // Recursively compare objects and arrays.\n    if (className == '[object Array]') {\n      // Compare array lengths to determine if a deep comparison is necessary.\n      size = a.length;\n      result = size == b.length;\n      if (result) {\n        // Deep compare the contents, ignoring non-numeric properties.\n        while (size--) {\n          if (!(result = eq(a[size], b[size], aStack, bStack))) break;\n        }\n      }\n    } else {\n      // Objects with different constructors are not equivalent, but `Object`s\n      // from different frames are.\n      var aCtor = a.constructor, bCtor = b.constructor;\n      if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&\n                               _.isFunction(bCtor) && (bCtor instanceof bCtor))) {\n        return false;\n      }\n      // Deep compare objects.\n      for (var key in a) {\n        if (_.has(a, key)) {\n          // Count the expected number of properties.\n          size++;\n          // Deep compare each member.\n          if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;\n        }\n      }\n      // Ensure that both objects contain the same number of properties.\n      if (result) {\n        for (key in b) {\n          if (_.has(b, key) && !(size--)) break;\n        }\n        result = !size;\n      }\n    }\n    // Remove the first object from the stack of traversed objects.\n    aStack.pop();\n    bStack.pop();\n    return result;\n  };\n\n  // Perform a deep comparison to check if two objects are equal.\n  _.isEqual = function(a, b) {\n    return eq(a, b, [], []);\n  };\n\n  // Is a given array, string, or object empty?\n  // An \"empty\" object has no enumerable own-properties.\n  _.isEmpty = function(obj) {\n    if (obj == null) return true;\n    if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;\n    for (var key in obj) if (_.has(obj, key)) return false;\n    return true;\n  };\n\n  // Is a given value a DOM element?\n  _.isElement = function(obj) {\n    return !!(obj && obj.nodeType === 1);\n  };\n\n  // Is a given value an array?\n  // Delegates to ECMA5's native Array.isArray\n  _.isArray = nativeIsArray || function(obj) {\n    return toString.call(obj) == '[object Array]';\n  };\n\n  // Is a given variable an object?\n  _.isObject = function(obj) {\n    return obj === Object(obj);\n  };\n\n  // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.\n  each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {\n    _['is' + name] = function(obj) {\n      return toString.call(obj) == '[object ' + name + ']';\n    };\n  });\n\n  // Define a fallback version of the method in browsers (ahem, IE), where\n  // there isn't any inspectable \"Arguments\" type.\n  if (!_.isArguments(arguments)) {\n    _.isArguments = function(obj) {\n      return !!(obj && _.has(obj, 'callee'));\n    };\n  }\n\n  // Optimize `isFunction` if appropriate.\n  if (typeof (/./) !== 'function') {\n    _.isFunction = function(obj) {\n      return typeof obj === 'function';\n    };\n  }\n\n  // Is a given object a finite number?\n  _.isFinite = function(obj) {\n    return isFinite(obj) && !isNaN(parseFloat(obj));\n  };\n\n  // Is the given value `NaN`? (NaN is the only number which does not equal itself).\n  _.isNaN = function(obj) {\n    return _.isNumber(obj) && obj != +obj;\n  };\n\n  // Is a given value a boolean?\n  _.isBoolean = function(obj) {\n    return obj === true || obj === false || toString.call(obj) == '[object Boolean]';\n  };\n\n  // Is a given value equal to null?\n  _.isNull = function(obj) {\n    return obj === null;\n  };\n\n  // Is a given variable undefined?\n  _.isUndefined = function(obj) {\n    return obj === void 0;\n  };\n\n  // Shortcut function for checking if an object has a given property directly\n  // on itself (in other words, not on a prototype).\n  _.has = function(obj, key) {\n    return hasOwnProperty.call(obj, key);\n  };\n\n  // Utility Functions\n  // -----------------\n\n  // Run Underscore.js in *noConflict* mode, returning the `_` variable to its\n  // previous owner. Returns a reference to the Underscore object.\n  _.noConflict = function() {\n    root._ = previousUnderscore;\n    return this;\n  };\n\n  // Keep the identity function around for default iterators.\n  _.identity = function(value) {\n    return value;\n  };\n\n  // Run a function **n** times.\n  _.times = function(n, iterator, context) {\n    var accum = Array(n);\n    for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i);\n    return accum;\n  };\n\n  // Return a random integer between min and max (inclusive).\n  _.random = function(min, max) {\n    if (max == null) {\n      max = min;\n      min = 0;\n    }\n    return min + Math.floor(Math.random() * (max - min + 1));\n  };\n\n  // List of HTML entities for escaping.\n  var entityMap = {\n    escape: {\n      '&': '&amp;',\n      '<': '&lt;',\n      '>': '&gt;',\n      '\"': '&quot;',\n      \"'\": '&#x27;',\n      '/': '&#x2F;'\n    }\n  };\n  entityMap.unescape = _.invert(entityMap.escape);\n\n  // Regexes containing the keys and values listed immediately above.\n  var entityRegexes = {\n    escape:   new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),\n    unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')\n  };\n\n  // Functions for escaping and unescaping strings to/from HTML interpolation.\n  _.each(['escape', 'unescape'], function(method) {\n    _[method] = function(string) {\n      if (string == null) return '';\n      return ('' + string).replace(entityRegexes[method], function(match) {\n        return entityMap[method][match];\n      });\n    };\n  });\n\n  // If the value of the named property is a function then invoke it;\n  // otherwise, return it.\n  _.result = function(object, property) {\n    if (object == null) return null;\n    var value = object[property];\n    return _.isFunction(value) ? value.call(object) : value;\n  };\n\n  // Add your own custom functions to the Underscore object.\n  _.mixin = function(obj) {\n    each(_.functions(obj), function(name){\n      var func = _[name] = obj[name];\n      _.prototype[name] = function() {\n        var args = [this._wrapped];\n        push.apply(args, arguments);\n        return result.call(this, func.apply(_, args));\n      };\n    });\n  };\n\n  // Generate a unique integer id (unique within the entire client session).\n  // Useful for temporary DOM ids.\n  var idCounter = 0;\n  _.uniqueId = function(prefix) {\n    var id = ++idCounter + '';\n    return prefix ? prefix + id : id;\n  };\n\n  // By default, Underscore uses ERB-style template delimiters, change the\n  // following template settings to use alternative delimiters.\n  _.templateSettings = {\n    evaluate    : /<%([\\s\\S]+?)%>/g,\n    interpolate : /<%=([\\s\\S]+?)%>/g,\n    escape      : /<%-([\\s\\S]+?)%>/g\n  };\n\n  // When customizing `templateSettings`, if you don't want to define an\n  // interpolation, evaluation or escaping regex, we need one that is\n  // guaranteed not to match.\n  var noMatch = /(.)^/;\n\n  // Certain characters need to be escaped so that they can be put into a\n  // string literal.\n  var escapes = {\n    \"'\":      \"'\",\n    '\\\\':     '\\\\',\n    '\\r':     'r',\n    '\\n':     'n',\n    '\\t':     't',\n    '\\u2028': 'u2028',\n    '\\u2029': 'u2029'\n  };\n\n  var escaper = /\\\\|'|\\r|\\n|\\t|\\u2028|\\u2029/g;\n\n  // JavaScript micro-templating, similar to John Resig's implementation.\n  // Underscore templating handles arbitrary delimiters, preserves whitespace,\n  // and correctly escapes quotes within interpolated code.\n  _.template = function(text, data, settings) {\n    var render;\n    settings = _.defaults({}, settings, _.templateSettings);\n\n    // Combine delimiters into one regular expression via alternation.\n    var matcher = new RegExp([\n      (settings.escape || noMatch).source,\n      (settings.interpolate || noMatch).source,\n      (settings.evaluate || noMatch).source\n    ].join('|') + '|$', 'g');\n\n    // Compile the template source, escaping string literals appropriately.\n    var index = 0;\n    var source = \"__p+='\";\n    text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {\n      source += text.slice(index, offset)\n        .replace(escaper, function(match) { return '\\\\' + escapes[match]; });\n\n      if (escape) {\n        source += \"'+\\n((__t=(\" + escape + \"))==null?'':_.escape(__t))+\\n'\";\n      }\n      if (interpolate) {\n        source += \"'+\\n((__t=(\" + interpolate + \"))==null?'':__t)+\\n'\";\n      }\n      if (evaluate) {\n        source += \"';\\n\" + evaluate + \"\\n__p+='\";\n      }\n      index = offset + match.length;\n      return match;\n    });\n    source += \"';\\n\";\n\n    // If a variable is not specified, place data values in local scope.\n    if (!settings.variable) source = 'with(obj||{}){\\n' + source + '}\\n';\n\n    source = \"var __t,__p='',__j=Array.prototype.join,\" +\n      \"print=function(){__p+=__j.call(arguments,'');};\\n\" +\n      source + \"return __p;\\n\";\n\n    try {\n      render = new Function(settings.variable || 'obj', '_', source);\n    } catch (e) {\n      e.source = source;\n      throw e;\n    }\n\n    if (data) return render(data, _);\n    var template = function(data) {\n      return render.call(this, data, _);\n    };\n\n    // Provide the compiled function source as a convenience for precompilation.\n    template.source = 'function(' + (settings.variable || 'obj') + '){\\n' + source + '}';\n\n    return template;\n  };\n\n  // Add a \"chain\" function, which will delegate to the wrapper.\n  _.chain = function(obj) {\n    return _(obj).chain();\n  };\n\n  // OOP\n  // ---------------\n  // If Underscore is called as a function, it returns a wrapped object that\n  // can be used OO-style. This wrapper holds altered versions of all the\n  // underscore functions. Wrapped objects may be chained.\n\n  // Helper function to continue chaining intermediate results.\n  var result = function(obj) {\n    return this._chain ? _(obj).chain() : obj;\n  };\n\n  // Add all of the Underscore functions to the wrapper object.\n  _.mixin(_);\n\n  // Add all mutator Array functions to the wrapper.\n  each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {\n    var method = ArrayProto[name];\n    _.prototype[name] = function() {\n      var obj = this._wrapped;\n      method.apply(obj, arguments);\n      if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0];\n      return result.call(this, obj);\n    };\n  });\n\n  // Add all accessor Array functions to the wrapper.\n  each(['concat', 'join', 'slice'], function(name) {\n    var method = ArrayProto[name];\n    _.prototype[name] = function() {\n      return result.call(this, method.apply(this._wrapped, arguments));\n    };\n  });\n\n  _.extend(_.prototype, {\n\n    // Start chaining a wrapped Underscore object.\n    chain: function() {\n      this._chain = true;\n      return this;\n    },\n\n    // Extracts the result from a wrapped and chained object.\n    value: function() {\n      return this._wrapped;\n    }\n\n  });\n\n}).call(this);\n\n})()\n},{}],11:[function(require,module,exports){\nvar events = require('events');\n\nexports.isArray = isArray;\nexports.isDate = function(obj){return Object.prototype.toString.call(obj) === '[object Date]'};\nexports.isRegExp = function(obj){return Object.prototype.toString.call(obj) === '[object RegExp]'};\n\n\nexports.print = function () {};\nexports.puts = function () {};\nexports.debug = function() {};\n\nexports.inspect = function(obj, showHidden, depth, colors) {\n  var seen = [];\n\n  var stylize = function(str, styleType) {\n    // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\n    var styles =\n        { 'bold' : [1, 22],\n          'italic' : [3, 23],\n          'underline' : [4, 24],\n          'inverse' : [7, 27],\n          'white' : [37, 39],\n          'grey' : [90, 39],\n          'black' : [30, 39],\n          'blue' : [34, 39],\n          'cyan' : [36, 39],\n          'green' : [32, 39],\n          'magenta' : [35, 39],\n          'red' : [31, 39],\n          'yellow' : [33, 39] };\n\n    var style =\n        { 'special': 'cyan',\n          'number': 'blue',\n          'boolean': 'yellow',\n          'undefined': 'grey',\n          'null': 'bold',\n          'string': 'green',\n          'date': 'magenta',\n          // \"name\": intentionally not styling\n          'regexp': 'red' }[styleType];\n\n    if (style) {\n      return '\\033[' + styles[style][0] + 'm' + str +\n             '\\033[' + styles[style][1] + 'm';\n    } else {\n      return str;\n    }\n  };\n  if (! colors) {\n    stylize = function(str, styleType) { return str; };\n  }\n\n  function format(value, recurseTimes) {\n    // Provide a hook for user-specified inspect functions.\n    // Check that value is an object with an inspect function on it\n    if (value && typeof value.inspect === 'function' &&\n        // Filter out the util module, it's inspect function is special\n        value !== exports &&\n        // Also filter out any prototype objects using the circular check.\n        !(value.constructor && value.constructor.prototype === value)) {\n      return value.inspect(recurseTimes);\n    }\n\n    // Primitive types cannot have properties\n    switch (typeof value) {\n      case 'undefined':\n        return stylize('undefined', 'undefined');\n\n      case 'string':\n        var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                                 .replace(/'/g, \"\\\\'\")\n                                                 .replace(/\\\\\"/g, '\"') + '\\'';\n        return stylize(simple, 'string');\n\n      case 'number':\n        return stylize('' + value, 'number');\n\n      case 'boolean':\n        return stylize('' + value, 'boolean');\n    }\n    // For some reason typeof null is \"object\", so special case here.\n    if (value === null) {\n      return stylize('null', 'null');\n    }\n\n    // Look up the keys of the object.\n    var visible_keys = Object_keys(value);\n    var keys = showHidden ? Object_getOwnPropertyNames(value) : visible_keys;\n\n    // Functions without properties can be shortcutted.\n    if (typeof value === 'function' && keys.length === 0) {\n      if (isRegExp(value)) {\n        return stylize('' + value, 'regexp');\n      } else {\n        var name = value.name ? ': ' + value.name : '';\n        return stylize('[Function' + name + ']', 'special');\n      }\n    }\n\n    // Dates without properties can be shortcutted\n    if (isDate(value) && keys.length === 0) {\n      return stylize(value.toUTCString(), 'date');\n    }\n\n    var base, type, braces;\n    // Determine the object type\n    if (isArray(value)) {\n      type = 'Array';\n      braces = ['[', ']'];\n    } else {\n      type = 'Object';\n      braces = ['{', '}'];\n    }\n\n    // Make functions say that they are functions\n    if (typeof value === 'function') {\n      var n = value.name ? ': ' + value.name : '';\n      base = (isRegExp(value)) ? ' ' + value : ' [Function' + n + ']';\n    } else {\n      base = '';\n    }\n\n    // Make dates with properties first say the date\n    if (isDate(value)) {\n      base = ' ' + value.toUTCString();\n    }\n\n    if (keys.length === 0) {\n      return braces[0] + base + braces[1];\n    }\n\n    if (recurseTimes < 0) {\n      if (isRegExp(value)) {\n        return stylize('' + value, 'regexp');\n      } else {\n        return stylize('[Object]', 'special');\n      }\n    }\n\n    seen.push(value);\n\n    var output = keys.map(function(key) {\n      var name, str;\n      if (value.__lookupGetter__) {\n        if (value.__lookupGetter__(key)) {\n          if (value.__lookupSetter__(key)) {\n            str = stylize('[Getter/Setter]', 'special');\n          } else {\n            str = stylize('[Getter]', 'special');\n          }\n        } else {\n          if (value.__lookupSetter__(key)) {\n            str = stylize('[Setter]', 'special');\n          }\n        }\n      }\n      if (visible_keys.indexOf(key) < 0) {\n        name = '[' + key + ']';\n      }\n      if (!str) {\n        if (seen.indexOf(value[key]) < 0) {\n          if (recurseTimes === null) {\n            str = format(value[key]);\n          } else {\n            str = format(value[key], recurseTimes - 1);\n          }\n          if (str.indexOf('\\n') > -1) {\n            if (isArray(value)) {\n              str = str.split('\\n').map(function(line) {\n                return '  ' + line;\n              }).join('\\n').substr(2);\n            } else {\n              str = '\\n' + str.split('\\n').map(function(line) {\n                return '   ' + line;\n              }).join('\\n');\n            }\n          }\n        } else {\n          str = stylize('[Circular]', 'special');\n        }\n      }\n      if (typeof name === 'undefined') {\n        if (type === 'Array' && key.match(/^\\d+$/)) {\n          return str;\n        }\n        name = JSON.stringify('' + key);\n        if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n          name = name.substr(1, name.length - 2);\n          name = stylize(name, 'name');\n        } else {\n          name = name.replace(/'/g, \"\\\\'\")\n                     .replace(/\\\\\"/g, '\"')\n                     .replace(/(^\"|\"$)/g, \"'\");\n          name = stylize(name, 'string');\n        }\n      }\n\n      return name + ': ' + str;\n    });\n\n    seen.pop();\n\n    var numLinesEst = 0;\n    var length = output.reduce(function(prev, cur) {\n      numLinesEst++;\n      if (cur.indexOf('\\n') >= 0) numLinesEst++;\n      return prev + cur.length + 1;\n    }, 0);\n\n    if (length > 50) {\n      output = braces[0] +\n               (base === '' ? '' : base + '\\n ') +\n               ' ' +\n               output.join(',\\n  ') +\n               ' ' +\n               braces[1];\n\n    } else {\n      output = braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n    }\n\n    return output;\n  }\n  return format(obj, (typeof depth === 'undefined' ? 2 : depth));\n};\n\n\nfunction isArray(ar) {\n  return ar instanceof Array ||\n         Array.isArray(ar) ||\n         (ar && ar !== Object.prototype && isArray(ar.__proto__));\n}\n\n\nfunction isRegExp(re) {\n  return re instanceof RegExp ||\n    (typeof re === 'object' && Object.prototype.toString.call(re) === '[object RegExp]');\n}\n\n\nfunction isDate(d) {\n  if (d instanceof Date) return true;\n  if (typeof d !== 'object') return false;\n  var properties = Date.prototype && Object_getOwnPropertyNames(Date.prototype);\n  var proto = d.__proto__ && Object_getOwnPropertyNames(d.__proto__);\n  return JSON.stringify(proto) === JSON.stringify(properties);\n}\n\nfunction pad(n) {\n  return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n              'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n  var d = new Date();\n  var time = [pad(d.getHours()),\n              pad(d.getMinutes()),\n              pad(d.getSeconds())].join(':');\n  return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\nexports.log = function (msg) {};\n\nexports.pump = null;\n\nvar Object_keys = Object.keys || function (obj) {\n    var res = [];\n    for (var key in obj) res.push(key);\n    return res;\n};\n\nvar Object_getOwnPropertyNames = Object.getOwnPropertyNames || function (obj) {\n    var res = [];\n    for (var key in obj) {\n        if (Object.hasOwnProperty.call(obj, key)) res.push(key);\n    }\n    return res;\n};\n\nvar Object_create = Object.create || function (prototype, properties) {\n    // from es5-shim\n    var object;\n    if (prototype === null) {\n        object = { '__proto__' : null };\n    }\n    else {\n        if (typeof prototype !== 'object') {\n            throw new TypeError(\n                'typeof prototype[' + (typeof prototype) + '] != \\'object\\''\n            );\n        }\n        var Type = function () {};\n        Type.prototype = prototype;\n        object = new Type();\n        object.__proto__ = prototype;\n    }\n    if (typeof properties !== 'undefined' && Object.defineProperties) {\n        Object.defineProperties(object, properties);\n    }\n    return object;\n};\n\nexports.inherits = function(ctor, superCtor) {\n  ctor.super_ = superCtor;\n  ctor.prototype = Object_create(superCtor.prototype, {\n    constructor: {\n      value: ctor,\n      enumerable: false,\n      writable: true,\n      configurable: true\n    }\n  });\n};\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n  if (typeof f !== 'string') {\n    var objects = [];\n    for (var i = 0; i < arguments.length; i++) {\n      objects.push(exports.inspect(arguments[i]));\n    }\n    return objects.join(' ');\n  }\n\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  var str = String(f).replace(formatRegExp, function(x) {\n    if (x === '%%') return '%';\n    if (i >= len) return x;\n    switch (x) {\n      case '%s': return String(args[i++]);\n      case '%d': return Number(args[i++]);\n      case '%j': return JSON.stringify(args[i++]);\n      default:\n        return x;\n    }\n  });\n  for(var x = args[i]; i < len; x = args[++i]){\n    if (x === null || typeof x !== 'object') {\n      str += ' ' + x;\n    } else {\n      str += ' ' + exports.inspect(x);\n    }\n  }\n  return str;\n};\n\n},{\"events\":2}],12:[function(require,module,exports){\n(function(){// UTILITY\nvar util = require('util');\nvar Buffer = require(\"buffer\").Buffer;\nvar pSlice = Array.prototype.slice;\n\nfunction objectKeys(object) {\n  if (Object.keys) return Object.keys(object);\n  var result = [];\n  for (var name in object) {\n    if (Object.prototype.hasOwnProperty.call(object, name)) {\n      result.push(name);\n    }\n  }\n  return result;\n}\n\n// 1. The assert module provides functions that throw\n// AssertionError's when particular conditions are not met. The\n// assert module must conform to the following interface.\n\nvar assert = module.exports = ok;\n\n// 2. The AssertionError is defined in assert.\n// new assert.AssertionError({ message: message,\n//                             actual: actual,\n//                             expected: expected })\n\nassert.AssertionError = function AssertionError(options) {\n  this.name = 'AssertionError';\n  this.message = options.message;\n  this.actual = options.actual;\n  this.expected = options.expected;\n  this.operator = options.operator;\n  var stackStartFunction = options.stackStartFunction || fail;\n\n  if (Error.captureStackTrace) {\n    Error.captureStackTrace(this, stackStartFunction);\n  }\n};\nutil.inherits(assert.AssertionError, Error);\n\nfunction replacer(key, value) {\n  if (value === undefined) {\n    return '' + value;\n  }\n  if (typeof value === 'number' && (isNaN(value) || !isFinite(value))) {\n    return value.toString();\n  }\n  if (typeof value === 'function' || value instanceof RegExp) {\n    return value.toString();\n  }\n  return value;\n}\n\nfunction truncate(s, n) {\n  if (typeof s == 'string') {\n    return s.length < n ? s : s.slice(0, n);\n  } else {\n    return s;\n  }\n}\n\nassert.AssertionError.prototype.toString = function() {\n  if (this.message) {\n    return [this.name + ':', this.message].join(' ');\n  } else {\n    return [\n      this.name + ':',\n      truncate(JSON.stringify(this.actual, replacer), 128),\n      this.operator,\n      truncate(JSON.stringify(this.expected, replacer), 128)\n    ].join(' ');\n  }\n};\n\n// assert.AssertionError instanceof Error\n\nassert.AssertionError.__proto__ = Error.prototype;\n\n// At present only the three keys mentioned above are used and\n// understood by the spec. Implementations or sub modules can pass\n// other keys to the AssertionError's constructor - they will be\n// ignored.\n\n// 3. All of the following functions must throw an AssertionError\n// when a corresponding condition is not met, with a message that\n// may be undefined if not provided.  All assertion methods provide\n// both the actual and expected values to the assertion error for\n// display purposes.\n\nfunction fail(actual, expected, message, operator, stackStartFunction) {\n  throw new assert.AssertionError({\n    message: message,\n    actual: actual,\n    expected: expected,\n    operator: operator,\n    stackStartFunction: stackStartFunction\n  });\n}\n\n// EXTENSION! allows for well behaved errors defined elsewhere.\nassert.fail = fail;\n\n// 4. Pure assertion tests whether a value is truthy, as determined\n// by !!guard.\n// assert.ok(guard, message_opt);\n// This statement is equivalent to assert.equal(true, guard,\n// message_opt);. To test strictly for the value true, use\n// assert.strictEqual(true, guard, message_opt);.\n\nfunction ok(value, message) {\n  if (!!!value) fail(value, true, message, '==', assert.ok);\n}\nassert.ok = ok;\n\n// 5. The equality assertion tests shallow, coercive equality with\n// ==.\n// assert.equal(actual, expected, message_opt);\n\nassert.equal = function equal(actual, expected, message) {\n  if (actual != expected) fail(actual, expected, message, '==', assert.equal);\n};\n\n// 6. The non-equality assertion tests for whether two objects are not equal\n// with != assert.notEqual(actual, expected, message_opt);\n\nassert.notEqual = function notEqual(actual, expected, message) {\n  if (actual == expected) {\n    fail(actual, expected, message, '!=', assert.notEqual);\n  }\n};\n\n// 7. The equivalence assertion tests a deep equality relation.\n// assert.deepEqual(actual, expected, message_opt);\n\nassert.deepEqual = function deepEqual(actual, expected, message) {\n  if (!_deepEqual(actual, expected)) {\n    fail(actual, expected, message, 'deepEqual', assert.deepEqual);\n  }\n};\n\nfunction _deepEqual(actual, expected) {\n  // 7.1. All identical values are equivalent, as determined by ===.\n  if (actual === expected) {\n    return true;\n\n  } else if (Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) {\n    if (actual.length != expected.length) return false;\n\n    for (var i = 0; i < actual.length; i++) {\n      if (actual[i] !== expected[i]) return false;\n    }\n\n    return true;\n\n  // 7.2. If the expected value is a Date object, the actual value is\n  // equivalent if it is also a Date object that refers to the same time.\n  } else if (actual instanceof Date && expected instanceof Date) {\n    return actual.getTime() === expected.getTime();\n\n  // 7.3. Other pairs that do not both pass typeof value == 'object',\n  // equivalence is determined by ==.\n  } else if (typeof actual != 'object' && typeof expected != 'object') {\n    return actual == expected;\n\n  // 7.4. For all other Object pairs, including Array objects, equivalence is\n  // determined by having the same number of owned properties (as verified\n  // with Object.prototype.hasOwnProperty.call), the same set of keys\n  // (although not necessarily the same order), equivalent values for every\n  // corresponding key, and an identical 'prototype' property. Note: this\n  // accounts for both named and indexed properties on Arrays.\n  } else {\n    return objEquiv(actual, expected);\n  }\n}\n\nfunction isUndefinedOrNull(value) {\n  return value === null || value === undefined;\n}\n\nfunction isArguments(object) {\n  return Object.prototype.toString.call(object) == '[object Arguments]';\n}\n\nfunction objEquiv(a, b) {\n  if (isUndefinedOrNull(a) || isUndefinedOrNull(b))\n    return false;\n  // an identical 'prototype' property.\n  if (a.prototype !== b.prototype) return false;\n  //~~~I've managed to break Object.keys through screwy arguments passing.\n  //   Converting to array solves the problem.\n  if (isArguments(a)) {\n    if (!isArguments(b)) {\n      return false;\n    }\n    a = pSlice.call(a);\n    b = pSlice.call(b);\n    return _deepEqual(a, b);\n  }\n  try {\n    var ka = objectKeys(a),\n        kb = objectKeys(b),\n        key, i;\n  } catch (e) {//happens when one is a string literal and the other isn't\n    return false;\n  }\n  // having the same number of owned properties (keys incorporates\n  // hasOwnProperty)\n  if (ka.length != kb.length)\n    return false;\n  //the same set of keys (although not necessarily the same order),\n  ka.sort();\n  kb.sort();\n  //~~~cheap key test\n  for (i = ka.length - 1; i >= 0; i--) {\n    if (ka[i] != kb[i])\n      return false;\n  }\n  //equivalent values for every corresponding key, and\n  //~~~possibly expensive deep test\n  for (i = ka.length - 1; i >= 0; i--) {\n    key = ka[i];\n    if (!_deepEqual(a[key], b[key])) return false;\n  }\n  return true;\n}\n\n// 8. The non-equivalence assertion tests for any deep inequality.\n// assert.notDeepEqual(actual, expected, message_opt);\n\nassert.notDeepEqual = function notDeepEqual(actual, expected, message) {\n  if (_deepEqual(actual, expected)) {\n    fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);\n  }\n};\n\n// 9. The strict equality assertion tests strict equality, as determined by ===.\n// assert.strictEqual(actual, expected, message_opt);\n\nassert.strictEqual = function strictEqual(actual, expected, message) {\n  if (actual !== expected) {\n    fail(actual, expected, message, '===', assert.strictEqual);\n  }\n};\n\n// 10. The strict non-equality assertion tests for strict inequality, as\n// determined by !==.  assert.notStrictEqual(actual, expected, message_opt);\n\nassert.notStrictEqual = function notStrictEqual(actual, expected, message) {\n  if (actual === expected) {\n    fail(actual, expected, message, '!==', assert.notStrictEqual);\n  }\n};\n\nfunction expectedException(actual, expected) {\n  if (!actual || !expected) {\n    return false;\n  }\n\n  if (expected instanceof RegExp) {\n    return expected.test(actual);\n  } else if (actual instanceof expected) {\n    return true;\n  } else if (expected.call({}, actual) === true) {\n    return true;\n  }\n\n  return false;\n}\n\nfunction _throws(shouldThrow, block, expected, message) {\n  var actual;\n\n  if (typeof expected === 'string') {\n    message = expected;\n    expected = null;\n  }\n\n  try {\n    block();\n  } catch (e) {\n    actual = e;\n  }\n\n  message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +\n            (message ? ' ' + message : '.');\n\n  if (shouldThrow && !actual) {\n    fail('Missing expected exception' + message);\n  }\n\n  if (!shouldThrow && expectedException(actual, expected)) {\n    fail('Got unwanted exception' + message);\n  }\n\n  if ((shouldThrow && actual && expected &&\n      !expectedException(actual, expected)) || (!shouldThrow && actual)) {\n    throw actual;\n  }\n}\n\n// 11. Expected to throw an error:\n// assert.throws(block, Error_opt, message_opt);\n\nassert.throws = function(block, /*optional*/error, /*optional*/message) {\n  _throws.apply(this, [true].concat(pSlice.call(arguments)));\n};\n\n// EXTENSION! This is annoying to write outside this module.\nassert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) {\n  _throws.apply(this, [false].concat(pSlice.call(arguments)));\n};\n\nassert.ifError = function(err) { if (err) {throw err;}};\n\n})()\n},{\"util\":11,\"buffer\":13}],14:[function(require,module,exports){\nexports.readIEEE754 = function(buffer, offset, isBE, mLen, nBytes) {\n  var e, m,\n      eLen = nBytes * 8 - mLen - 1,\n      eMax = (1 << eLen) - 1,\n      eBias = eMax >> 1,\n      nBits = -7,\n      i = isBE ? 0 : (nBytes - 1),\n      d = isBE ? 1 : -1,\n      s = buffer[offset + i];\n\n  i += d;\n\n  e = s & ((1 << (-nBits)) - 1);\n  s >>= (-nBits);\n  nBits += eLen;\n  for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8);\n\n  m = e & ((1 << (-nBits)) - 1);\n  e >>= (-nBits);\n  nBits += mLen;\n  for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8);\n\n  if (e === 0) {\n    e = 1 - eBias;\n  } else if (e === eMax) {\n    return m ? NaN : ((s ? -1 : 1) * Infinity);\n  } else {\n    m = m + Math.pow(2, mLen);\n    e = e - eBias;\n  }\n  return (s ? -1 : 1) * m * Math.pow(2, e - mLen);\n};\n\nexports.writeIEEE754 = function(buffer, value, offset, isBE, mLen, nBytes) {\n  var e, m, c,\n      eLen = nBytes * 8 - mLen - 1,\n      eMax = (1 << eLen) - 1,\n      eBias = eMax >> 1,\n      rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),\n      i = isBE ? (nBytes - 1) : 0,\n      d = isBE ? -1 : 1,\n      s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;\n\n  value = Math.abs(value);\n\n  if (isNaN(value) || value === Infinity) {\n    m = isNaN(value) ? 1 : 0;\n    e = eMax;\n  } else {\n    e = Math.floor(Math.log(value) / Math.LN2);\n    if (value * (c = Math.pow(2, -e)) < 1) {\n      e--;\n      c *= 2;\n    }\n    if (e + eBias >= 1) {\n      value += rt / c;\n    } else {\n      value += rt * Math.pow(2, 1 - eBias);\n    }\n    if (value * c >= 2) {\n      e++;\n      c /= 2;\n    }\n\n    if (e + eBias >= eMax) {\n      m = 0;\n      e = eMax;\n    } else if (e + eBias >= 1) {\n      m = (value * c - 1) * Math.pow(2, mLen);\n      e = e + eBias;\n    } else {\n      m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);\n      e = 0;\n    }\n  }\n\n  for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8);\n\n  e = (e << mLen) | m;\n  eLen += mLen;\n  for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8);\n\n  buffer[offset + i - d] |= s * 128;\n};\n\n},{}],13:[function(require,module,exports){\n(function(){function SlowBuffer (size) {\n    this.length = size;\n};\n\nvar assert = require('assert');\n\nexports.INSPECT_MAX_BYTES = 50;\n\n\nfunction toHex(n) {\n  if (n < 16) return '0' + n.toString(16);\n  return n.toString(16);\n}\n\nfunction utf8ToBytes(str) {\n  var byteArray = [];\n  for (var i = 0; i < str.length; i++)\n    if (str.charCodeAt(i) <= 0x7F)\n      byteArray.push(str.charCodeAt(i));\n    else {\n      var h = encodeURIComponent(str.charAt(i)).substr(1).split('%');\n      for (var j = 0; j < h.length; j++)\n        byteArray.push(parseInt(h[j], 16));\n    }\n\n  return byteArray;\n}\n\nfunction asciiToBytes(str) {\n  var byteArray = []\n  for (var i = 0; i < str.length; i++ )\n    // Node's code seems to be doing this and not & 0x7F..\n    byteArray.push( str.charCodeAt(i) & 0xFF );\n\n  return byteArray;\n}\n\nfunction base64ToBytes(str) {\n  return require(\"base64-js\").toByteArray(str);\n}\n\nSlowBuffer.byteLength = function (str, encoding) {\n  switch (encoding || \"utf8\") {\n    case 'hex':\n      return str.length / 2;\n\n    case 'utf8':\n    case 'utf-8':\n      return utf8ToBytes(str).length;\n\n    case 'ascii':\n    case 'binary':\n      return str.length;\n\n    case 'base64':\n      return base64ToBytes(str).length;\n\n    default:\n      throw new Error('Unknown encoding');\n  }\n};\n\nfunction blitBuffer(src, dst, offset, length) {\n  var pos, i = 0;\n  while (i < length) {\n    if ((i+offset >= dst.length) || (i >= src.length))\n      break;\n\n    dst[i + offset] = src[i];\n    i++;\n  }\n  return i;\n}\n\nSlowBuffer.prototype.utf8Write = function (string, offset, length) {\n  var bytes, pos;\n  return SlowBuffer._charsWritten =  blitBuffer(utf8ToBytes(string), this, offset, length);\n};\n\nSlowBuffer.prototype.asciiWrite = function (string, offset, length) {\n  var bytes, pos;\n  return SlowBuffer._charsWritten =  blitBuffer(asciiToBytes(string), this, offset, length);\n};\n\nSlowBuffer.prototype.binaryWrite = SlowBuffer.prototype.asciiWrite;\n\nSlowBuffer.prototype.base64Write = function (string, offset, length) {\n  var bytes, pos;\n  return SlowBuffer._charsWritten = blitBuffer(base64ToBytes(string), this, offset, length);\n};\n\nSlowBuffer.prototype.base64Slice = function (start, end) {\n  var bytes = Array.prototype.slice.apply(this, arguments)\n  return require(\"base64-js\").fromByteArray(bytes);\n}\n\nfunction decodeUtf8Char(str) {\n  try {\n    return decodeURIComponent(str);\n  } catch (err) {\n    return String.fromCharCode(0xFFFD); // UTF 8 invalid char\n  }\n}\n\nSlowBuffer.prototype.utf8Slice = function () {\n  var bytes = Array.prototype.slice.apply(this, arguments);\n  var res = \"\";\n  var tmp = \"\";\n  var i = 0;\n  while (i < bytes.length) {\n    if (bytes[i] <= 0x7F) {\n      res += decodeUtf8Char(tmp) + String.fromCharCode(bytes[i]);\n      tmp = \"\";\n    } else\n      tmp += \"%\" + bytes[i].toString(16);\n\n    i++;\n  }\n\n  return res + decodeUtf8Char(tmp);\n}\n\nSlowBuffer.prototype.asciiSlice = function () {\n  var bytes = Array.prototype.slice.apply(this, arguments);\n  var ret = \"\";\n  for (var i = 0; i < bytes.length; i++)\n    ret += String.fromCharCode(bytes[i]);\n  return ret;\n}\n\nSlowBuffer.prototype.binarySlice = SlowBuffer.prototype.asciiSlice;\n\nSlowBuffer.prototype.inspect = function() {\n  var out = [],\n      len = this.length;\n  for (var i = 0; i < len; i++) {\n    out[i] = toHex(this[i]);\n    if (i == exports.INSPECT_MAX_BYTES) {\n      out[i + 1] = '...';\n      break;\n    }\n  }\n  return '<SlowBuffer ' + out.join(' ') + '>';\n};\n\n\nSlowBuffer.prototype.hexSlice = function(start, end) {\n  var len = this.length;\n\n  if (!start || start < 0) start = 0;\n  if (!end || end < 0 || end > len) end = len;\n\n  var out = '';\n  for (var i = start; i < end; i++) {\n    out += toHex(this[i]);\n  }\n  return out;\n};\n\n\nSlowBuffer.prototype.toString = function(encoding, start, end) {\n  encoding = String(encoding || 'utf8').toLowerCase();\n  start = +start || 0;\n  if (typeof end == 'undefined') end = this.length;\n\n  // Fastpath empty strings\n  if (+end == start) {\n    return '';\n  }\n\n  switch (encoding) {\n    case 'hex':\n      return this.hexSlice(start, end);\n\n    case 'utf8':\n    case 'utf-8':\n      return this.utf8Slice(start, end);\n\n    case 'ascii':\n      return this.asciiSlice(start, end);\n\n    case 'binary':\n      return this.binarySlice(start, end);\n\n    case 'base64':\n      return this.base64Slice(start, end);\n\n    case 'ucs2':\n    case 'ucs-2':\n      return this.ucs2Slice(start, end);\n\n    default:\n      throw new Error('Unknown encoding');\n  }\n};\n\n\nSlowBuffer.prototype.hexWrite = function(string, offset, length) {\n  offset = +offset || 0;\n  var remaining = this.length - offset;\n  if (!length) {\n    length = remaining;\n  } else {\n    length = +length;\n    if (length > remaining) {\n      length = remaining;\n    }\n  }\n\n  // must be an even number of digits\n  var strLen = string.length;\n  if (strLen % 2) {\n    throw new Error('Invalid hex string');\n  }\n  if (length > strLen / 2) {\n    length = strLen / 2;\n  }\n  for (var i = 0; i < length; i++) {\n    var byte = parseInt(string.substr(i * 2, 2), 16);\n    if (isNaN(byte)) throw new Error('Invalid hex string');\n    this[offset + i] = byte;\n  }\n  SlowBuffer._charsWritten = i * 2;\n  return i;\n};\n\n\nSlowBuffer.prototype.write = function(string, offset, length, encoding) {\n  // Support both (string, offset, length, encoding)\n  // and the legacy (string, encoding, offset, length)\n  if (isFinite(offset)) {\n    if (!isFinite(length)) {\n      encoding = length;\n      length = undefined;\n    }\n  } else {  // legacy\n    var swap = encoding;\n    encoding = offset;\n    offset = length;\n    length = swap;\n  }\n\n  offset = +offset || 0;\n  var remaining = this.length - offset;\n  if (!length) {\n    length = remaining;\n  } else {\n    length = +length;\n    if (length > remaining) {\n      length = remaining;\n    }\n  }\n  encoding = String(encoding || 'utf8').toLowerCase();\n\n  switch (encoding) {\n    case 'hex':\n      return this.hexWrite(string, offset, length);\n\n    case 'utf8':\n    case 'utf-8':\n      return this.utf8Write(string, offset, length);\n\n    case 'ascii':\n      return this.asciiWrite(string, offset, length);\n\n    case 'binary':\n      return this.binaryWrite(string, offset, length);\n\n    case 'base64':\n      return this.base64Write(string, offset, length);\n\n    case 'ucs2':\n    case 'ucs-2':\n      return this.ucs2Write(string, offset, length);\n\n    default:\n      throw new Error('Unknown encoding');\n  }\n};\n\n\n// slice(start, end)\nSlowBuffer.prototype.slice = function(start, end) {\n  if (end === undefined) end = this.length;\n\n  if (end > this.length) {\n    throw new Error('oob');\n  }\n  if (start > end) {\n    throw new Error('oob');\n  }\n\n  return new Buffer(this, end - start, +start);\n};\n\nSlowBuffer.prototype.copy = function(target, targetstart, sourcestart, sourceend) {\n  var temp = [];\n  for (var i=sourcestart; i<sourceend; i++) {\n    assert.ok(typeof this[i] !== 'undefined', \"copying undefined buffer bytes!\");\n    temp.push(this[i]);\n  }\n\n  for (var i=targetstart; i<targetstart+temp.length; i++) {\n    target[i] = temp[i-targetstart];\n  }\n};\n\nSlowBuffer.prototype.fill = function(value, start, end) {\n  if (end > this.length) {\n    throw new Error('oob');\n  }\n  if (start > end) {\n    throw new Error('oob');\n  }\n\n  for (var i = start; i < end; i++) {\n    this[i] = value;\n  }\n}\n\nfunction coerce(length) {\n  // Coerce length to a number (possibly NaN), round up\n  // in case it's fractional (e.g. 123.456) then do a\n  // double negate to coerce a NaN to 0. Easy, right?\n  length = ~~Math.ceil(+length);\n  return length < 0 ? 0 : length;\n}\n\n\n// Buffer\n\nfunction Buffer(subject, encoding, offset) {\n  if (!(this instanceof Buffer)) {\n    return new Buffer(subject, encoding, offset);\n  }\n\n  var type;\n\n  // Are we slicing?\n  if (typeof offset === 'number') {\n    this.length = coerce(encoding);\n    this.parent = subject;\n    this.offset = offset;\n  } else {\n    // Find the length\n    switch (type = typeof subject) {\n      case 'number':\n        this.length = coerce(subject);\n        break;\n\n      case 'string':\n        this.length = Buffer.byteLength(subject, encoding);\n        break;\n\n      case 'object': // Assume object is an array\n        this.length = coerce(subject.length);\n        break;\n\n      default:\n        throw new Error('First argument needs to be a number, ' +\n                        'array or string.');\n    }\n\n    if (this.length > Buffer.poolSize) {\n      // Big buffer, just alloc one.\n      this.parent = new SlowBuffer(this.length);\n      this.offset = 0;\n\n    } else {\n      // Small buffer.\n      if (!pool || pool.length - pool.used < this.length) allocPool();\n      this.parent = pool;\n      this.offset = pool.used;\n      pool.used += this.length;\n    }\n\n    // Treat array-ish objects as a byte array.\n    if (isArrayIsh(subject)) {\n      for (var i = 0; i < this.length; i++) {\n        if (subject instanceof Buffer) {\n          this.parent[i + this.offset] = subject.readUInt8(i);\n        }\n        else {\n          this.parent[i + this.offset] = subject[i];\n        }\n      }\n    } else if (type == 'string') {\n      // We are a string\n      this.length = this.write(subject, 0, encoding);\n    }\n  }\n\n}\n\nfunction isArrayIsh(subject) {\n  return Array.isArray(subject) || Buffer.isBuffer(subject) ||\n         subject && typeof subject === 'object' &&\n         typeof subject.length === 'number';\n}\n\nexports.SlowBuffer = SlowBuffer;\nexports.Buffer = Buffer;\n\nBuffer.poolSize = 8 * 1024;\nvar pool;\n\nfunction allocPool() {\n  pool = new SlowBuffer(Buffer.poolSize);\n  pool.used = 0;\n}\n\n\n// Static methods\nBuffer.isBuffer = function isBuffer(b) {\n  return b instanceof Buffer || b instanceof SlowBuffer;\n};\n\nBuffer.concat = function (list, totalLength) {\n  if (!Array.isArray(list)) {\n    throw new Error(\"Usage: Buffer.concat(list, [totalLength])\\n \\\n      list should be an Array.\");\n  }\n\n  if (list.length === 0) {\n    return new Buffer(0);\n  } else if (list.length === 1) {\n    return list[0];\n  }\n\n  if (typeof totalLength !== 'number') {\n    totalLength = 0;\n    for (var i = 0; i < list.length; i++) {\n      var buf = list[i];\n      totalLength += buf.length;\n    }\n  }\n\n  var buffer = new Buffer(totalLength);\n  var pos = 0;\n  for (var i = 0; i < list.length; i++) {\n    var buf = list[i];\n    buf.copy(buffer, pos);\n    pos += buf.length;\n  }\n  return buffer;\n};\n\n// Inspect\nBuffer.prototype.inspect = function inspect() {\n  var out = [],\n      len = this.length;\n\n  for (var i = 0; i < len; i++) {\n    out[i] = toHex(this.parent[i + this.offset]);\n    if (i == exports.INSPECT_MAX_BYTES) {\n      out[i + 1] = '...';\n      break;\n    }\n  }\n\n  return '<Buffer ' + out.join(' ') + '>';\n};\n\n\nBuffer.prototype.get = function get(i) {\n  if (i < 0 || i >= this.length) throw new Error('oob');\n  return this.parent[this.offset + i];\n};\n\n\nBuffer.prototype.set = function set(i, v) {\n  if (i < 0 || i >= this.length) throw new Error('oob');\n  return this.parent[this.offset + i] = v;\n};\n\n\n// write(string, offset = 0, length = buffer.length-offset, encoding = 'utf8')\nBuffer.prototype.write = function(string, offset, length, encoding) {\n  // Support both (string, offset, length, encoding)\n  // and the legacy (string, encoding, offset, length)\n  if (isFinite(offset)) {\n    if (!isFinite(length)) {\n      encoding = length;\n      length = undefined;\n    }\n  } else {  // legacy\n    var swap = encoding;\n    encoding = offset;\n    offset = length;\n    length = swap;\n  }\n\n  offset = +offset || 0;\n  var remaining = this.length - offset;\n  if (!length) {\n    length = remaining;\n  } else {\n    length = +length;\n    if (length > remaining) {\n      length = remaining;\n    }\n  }\n  encoding = String(encoding || 'utf8').toLowerCase();\n\n  var ret;\n  switch (encoding) {\n    case 'hex':\n      ret = this.parent.hexWrite(string, this.offset + offset, length);\n      break;\n\n    case 'utf8':\n    case 'utf-8':\n      ret = this.parent.utf8Write(string, this.offset + offset, length);\n      break;\n\n    case 'ascii':\n      ret = this.parent.asciiWrite(string, this.offset + offset, length);\n      break;\n\n    case 'binary':\n      ret = this.parent.binaryWrite(string, this.offset + offset, length);\n      break;\n\n    case 'base64':\n      // Warning: maxLength not taken into account in base64Write\n      ret = this.parent.base64Write(string, this.offset + offset, length);\n      break;\n\n    case 'ucs2':\n    case 'ucs-2':\n      ret = this.parent.ucs2Write(string, this.offset + offset, length);\n      break;\n\n    default:\n      throw new Error('Unknown encoding');\n  }\n\n  Buffer._charsWritten = SlowBuffer._charsWritten;\n\n  return ret;\n};\n\n\n// toString(encoding, start=0, end=buffer.length)\nBuffer.prototype.toString = function(encoding, start, end) {\n  encoding = String(encoding || 'utf8').toLowerCase();\n\n  if (typeof start == 'undefined' || start < 0) {\n    start = 0;\n  } else if (start > this.length) {\n    start = this.length;\n  }\n\n  if (typeof end == 'undefined' || end > this.length) {\n    end = this.length;\n  } else if (end < 0) {\n    end = 0;\n  }\n\n  start = start + this.offset;\n  end = end + this.offset;\n\n  switch (encoding) {\n    case 'hex':\n      return this.parent.hexSlice(start, end);\n\n    case 'utf8':\n    case 'utf-8':\n      return this.parent.utf8Slice(start, end);\n\n    case 'ascii':\n      return this.parent.asciiSlice(start, end);\n\n    case 'binary':\n      return this.parent.binarySlice(start, end);\n\n    case 'base64':\n      return this.parent.base64Slice(start, end);\n\n    case 'ucs2':\n    case 'ucs-2':\n      return this.parent.ucs2Slice(start, end);\n\n    default:\n      throw new Error('Unknown encoding');\n  }\n};\n\n\n// byteLength\nBuffer.byteLength = SlowBuffer.byteLength;\n\n\n// fill(value, start=0, end=buffer.length)\nBuffer.prototype.fill = function fill(value, start, end) {\n  value || (value = 0);\n  start || (start = 0);\n  end || (end = this.length);\n\n  if (typeof value === 'string') {\n    value = value.charCodeAt(0);\n  }\n  if (!(typeof value === 'number') || isNaN(value)) {\n    throw new Error('value is not a number');\n  }\n\n  if (end < start) throw new Error('end < start');\n\n  // Fill 0 bytes; we're done\n  if (end === start) return 0;\n  if (this.length == 0) return 0;\n\n  if (start < 0 || start >= this.length) {\n    throw new Error('start out of bounds');\n  }\n\n  if (end < 0 || end > this.length) {\n    throw new Error('end out of bounds');\n  }\n\n  return this.parent.fill(value,\n                          start + this.offset,\n                          end + this.offset);\n};\n\n\n// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)\nBuffer.prototype.copy = function(target, target_start, start, end) {\n  var source = this;\n  start || (start = 0);\n  end || (end = this.length);\n  target_start || (target_start = 0);\n\n  if (end < start) throw new Error('sourceEnd < sourceStart');\n\n  // Copy 0 bytes; we're done\n  if (end === start) return 0;\n  if (target.length == 0 || source.length == 0) return 0;\n\n  if (target_start < 0 || target_start >= target.length) {\n    throw new Error('targetStart out of bounds');\n  }\n\n  if (start < 0 || start >= source.length) {\n    throw new Error('sourceStart out of bounds');\n  }\n\n  if (end < 0 || end > source.length) {\n    throw new Error('sourceEnd out of bounds');\n  }\n\n  // Are we oob?\n  if (end > this.length) {\n    end = this.length;\n  }\n\n  if (target.length - target_start < end - start) {\n    end = target.length - target_start + start;\n  }\n\n  return this.parent.copy(target.parent,\n                          target_start + target.offset,\n                          start + this.offset,\n                          end + this.offset);\n};\n\n\n// slice(start, end)\nBuffer.prototype.slice = function(start, end) {\n  if (end === undefined) end = this.length;\n  if (end > this.length) throw new Error('oob');\n  if (start > end) throw new Error('oob');\n\n  return new Buffer(this.parent, end - start, +start + this.offset);\n};\n\n\n// Legacy methods for backwards compatibility.\n\nBuffer.prototype.utf8Slice = function(start, end) {\n  return this.toString('utf8', start, end);\n};\n\nBuffer.prototype.binarySlice = function(start, end) {\n  return this.toString('binary', start, end);\n};\n\nBuffer.prototype.asciiSlice = function(start, end) {\n  return this.toString('ascii', start, end);\n};\n\nBuffer.prototype.utf8Write = function(string, offset) {\n  return this.write(string, offset, 'utf8');\n};\n\nBuffer.prototype.binaryWrite = function(string, offset) {\n  return this.write(string, offset, 'binary');\n};\n\nBuffer.prototype.asciiWrite = function(string, offset) {\n  return this.write(string, offset, 'ascii');\n};\n\nBuffer.prototype.readUInt8 = function(offset, noAssert) {\n  var buffer = this;\n\n  if (!noAssert) {\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset < buffer.length,\n        'Trying to read beyond buffer length');\n  }\n\n  if (offset >= buffer.length) return;\n\n  return buffer.parent[buffer.offset + offset];\n};\n\nfunction readUInt16(buffer, offset, isBigEndian, noAssert) {\n  var val = 0;\n\n\n  if (!noAssert) {\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset + 1 < buffer.length,\n        'Trying to read beyond buffer length');\n  }\n\n  if (offset >= buffer.length) return 0;\n\n  if (isBigEndian) {\n    val = buffer.parent[buffer.offset + offset] << 8;\n    if (offset + 1 < buffer.length) {\n      val |= buffer.parent[buffer.offset + offset + 1];\n    }\n  } else {\n    val = buffer.parent[buffer.offset + offset];\n    if (offset + 1 < buffer.length) {\n      val |= buffer.parent[buffer.offset + offset + 1] << 8;\n    }\n  }\n\n  return val;\n}\n\nBuffer.prototype.readUInt16LE = function(offset, noAssert) {\n  return readUInt16(this, offset, false, noAssert);\n};\n\nBuffer.prototype.readUInt16BE = function(offset, noAssert) {\n  return readUInt16(this, offset, true, noAssert);\n};\n\nfunction readUInt32(buffer, offset, isBigEndian, noAssert) {\n  var val = 0;\n\n  if (!noAssert) {\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset + 3 < buffer.length,\n        'Trying to read beyond buffer length');\n  }\n\n  if (offset >= buffer.length) return 0;\n\n  if (isBigEndian) {\n    if (offset + 1 < buffer.length)\n      val = buffer.parent[buffer.offset + offset + 1] << 16;\n    if (offset + 2 < buffer.length)\n      val |= buffer.parent[buffer.offset + offset + 2] << 8;\n    if (offset + 3 < buffer.length)\n      val |= buffer.parent[buffer.offset + offset + 3];\n    val = val + (buffer.parent[buffer.offset + offset] << 24 >>> 0);\n  } else {\n    if (offset + 2 < buffer.length)\n      val = buffer.parent[buffer.offset + offset + 2] << 16;\n    if (offset + 1 < buffer.length)\n      val |= buffer.parent[buffer.offset + offset + 1] << 8;\n    val |= buffer.parent[buffer.offset + offset];\n    if (offset + 3 < buffer.length)\n      val = val + (buffer.parent[buffer.offset + offset + 3] << 24 >>> 0);\n  }\n\n  return val;\n}\n\nBuffer.prototype.readUInt32LE = function(offset, noAssert) {\n  return readUInt32(this, offset, false, noAssert);\n};\n\nBuffer.prototype.readUInt32BE = function(offset, noAssert) {\n  return readUInt32(this, offset, true, noAssert);\n};\n\n\n/*\n * Signed integer types, yay team! A reminder on how two's complement actually\n * works. The first bit is the signed bit, i.e. tells us whether or not the\n * number should be positive or negative. If the two's complement value is\n * positive, then we're done, as it's equivalent to the unsigned representation.\n *\n * Now if the number is positive, you're pretty much done, you can just leverage\n * the unsigned translations and return those. Unfortunately, negative numbers\n * aren't quite that straightforward.\n *\n * At first glance, one might be inclined to use the traditional formula to\n * translate binary numbers between the positive and negative values in two's\n * complement. (Though it doesn't quite work for the most negative value)\n * Mainly:\n *  - invert all the bits\n *  - add one to the result\n *\n * Of course, this doesn't quite work in Javascript. Take for example the value\n * of -128. This could be represented in 16 bits (big-endian) as 0xff80. But of\n * course, Javascript will do the following:\n *\n * > ~0xff80\n * -65409\n *\n * Whoh there, Javascript, that's not quite right. But wait, according to\n * Javascript that's perfectly correct. When Javascript ends up seeing the\n * constant 0xff80, it has no notion that it is actually a signed number. It\n * assumes that we've input the unsigned value 0xff80. Thus, when it does the\n * binary negation, it casts it into a signed value, (positive 0xff80). Then\n * when you perform binary negation on that, it turns it into a negative number.\n *\n * Instead, we're going to have to use the following general formula, that works\n * in a rather Javascript friendly way. I'm glad we don't support this kind of\n * weird numbering scheme in the kernel.\n *\n * (BIT-MAX - (unsigned)val + 1) * -1\n *\n * The astute observer, may think that this doesn't make sense for 8-bit numbers\n * (really it isn't necessary for them). However, when you get 16-bit numbers,\n * you do. Let's go back to our prior example and see how this will look:\n *\n * (0xffff - 0xff80 + 1) * -1\n * (0x007f + 1) * -1\n * (0x0080) * -1\n */\nBuffer.prototype.readInt8 = function(offset, noAssert) {\n  var buffer = this;\n  var neg;\n\n  if (!noAssert) {\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset < buffer.length,\n        'Trying to read beyond buffer length');\n  }\n\n  if (offset >= buffer.length) return;\n\n  neg = buffer.parent[buffer.offset + offset] & 0x80;\n  if (!neg) {\n    return (buffer.parent[buffer.offset + offset]);\n  }\n\n  return ((0xff - buffer.parent[buffer.offset + offset] + 1) * -1);\n};\n\nfunction readInt16(buffer, offset, isBigEndian, noAssert) {\n  var neg, val;\n\n  if (!noAssert) {\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset + 1 < buffer.length,\n        'Trying to read beyond buffer length');\n  }\n\n  val = readUInt16(buffer, offset, isBigEndian, noAssert);\n  neg = val & 0x8000;\n  if (!neg) {\n    return val;\n  }\n\n  return (0xffff - val + 1) * -1;\n}\n\nBuffer.prototype.readInt16LE = function(offset, noAssert) {\n  return readInt16(this, offset, false, noAssert);\n};\n\nBuffer.prototype.readInt16BE = function(offset, noAssert) {\n  return readInt16(this, offset, true, noAssert);\n};\n\nfunction readInt32(buffer, offset, isBigEndian, noAssert) {\n  var neg, val;\n\n  if (!noAssert) {\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset + 3 < buffer.length,\n        'Trying to read beyond buffer length');\n  }\n\n  val = readUInt32(buffer, offset, isBigEndian, noAssert);\n  neg = val & 0x80000000;\n  if (!neg) {\n    return (val);\n  }\n\n  return (0xffffffff - val + 1) * -1;\n}\n\nBuffer.prototype.readInt32LE = function(offset, noAssert) {\n  return readInt32(this, offset, false, noAssert);\n};\n\nBuffer.prototype.readInt32BE = function(offset, noAssert) {\n  return readInt32(this, offset, true, noAssert);\n};\n\nfunction readFloat(buffer, offset, isBigEndian, noAssert) {\n  if (!noAssert) {\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset + 3 < buffer.length,\n        'Trying to read beyond buffer length');\n  }\n\n  return require('./buffer_ieee754').readIEEE754(buffer, offset, isBigEndian,\n      23, 4);\n}\n\nBuffer.prototype.readFloatLE = function(offset, noAssert) {\n  return readFloat(this, offset, false, noAssert);\n};\n\nBuffer.prototype.readFloatBE = function(offset, noAssert) {\n  return readFloat(this, offset, true, noAssert);\n};\n\nfunction readDouble(buffer, offset, isBigEndian, noAssert) {\n  if (!noAssert) {\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset + 7 < buffer.length,\n        'Trying to read beyond buffer length');\n  }\n\n  return require('./buffer_ieee754').readIEEE754(buffer, offset, isBigEndian,\n      52, 8);\n}\n\nBuffer.prototype.readDoubleLE = function(offset, noAssert) {\n  return readDouble(this, offset, false, noAssert);\n};\n\nBuffer.prototype.readDoubleBE = function(offset, noAssert) {\n  return readDouble(this, offset, true, noAssert);\n};\n\n\n/*\n * We have to make sure that the value is a valid integer. This means that it is\n * non-negative. It has no fractional component and that it does not exceed the\n * maximum allowed value.\n *\n *      value           The number to check for validity\n *\n *      max             The maximum value\n */\nfunction verifuint(value, max) {\n  assert.ok(typeof (value) == 'number',\n      'cannot write a non-number as a number');\n\n  assert.ok(value >= 0,\n      'specified a negative value for writing an unsigned value');\n\n  assert.ok(value <= max, 'value is larger than maximum value for type');\n\n  assert.ok(Math.floor(value) === value, 'value has a fractional component');\n}\n\nBuffer.prototype.writeUInt8 = function(value, offset, noAssert) {\n  var buffer = this;\n\n  if (!noAssert) {\n    assert.ok(value !== undefined && value !== null,\n        'missing value');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset < buffer.length,\n        'trying to write beyond buffer length');\n\n    verifuint(value, 0xff);\n  }\n\n  if (offset < buffer.length) {\n    buffer.parent[buffer.offset + offset] = value;\n  }\n};\n\nfunction writeUInt16(buffer, value, offset, isBigEndian, noAssert) {\n  if (!noAssert) {\n    assert.ok(value !== undefined && value !== null,\n        'missing value');\n\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset + 1 < buffer.length,\n        'trying to write beyond buffer length');\n\n    verifuint(value, 0xffff);\n  }\n\n  for (var i = 0; i < Math.min(buffer.length - offset, 2); i++) {\n    buffer.parent[buffer.offset + offset + i] =\n        (value & (0xff << (8 * (isBigEndian ? 1 - i : i)))) >>>\n            (isBigEndian ? 1 - i : i) * 8;\n  }\n\n}\n\nBuffer.prototype.writeUInt16LE = function(value, offset, noAssert) {\n  writeUInt16(this, value, offset, false, noAssert);\n};\n\nBuffer.prototype.writeUInt16BE = function(value, offset, noAssert) {\n  writeUInt16(this, value, offset, true, noAssert);\n};\n\nfunction writeUInt32(buffer, value, offset, isBigEndian, noAssert) {\n  if (!noAssert) {\n    assert.ok(value !== undefined && value !== null,\n        'missing value');\n\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset + 3 < buffer.length,\n        'trying to write beyond buffer length');\n\n    verifuint(value, 0xffffffff);\n  }\n\n  for (var i = 0; i < Math.min(buffer.length - offset, 4); i++) {\n    buffer.parent[buffer.offset + offset + i] =\n        (value >>> (isBigEndian ? 3 - i : i) * 8) & 0xff;\n  }\n}\n\nBuffer.prototype.writeUInt32LE = function(value, offset, noAssert) {\n  writeUInt32(this, value, offset, false, noAssert);\n};\n\nBuffer.prototype.writeUInt32BE = function(value, offset, noAssert) {\n  writeUInt32(this, value, offset, true, noAssert);\n};\n\n\n/*\n * We now move onto our friends in the signed number category. Unlike unsigned\n * numbers, we're going to have to worry a bit more about how we put values into\n * arrays. Since we are only worrying about signed 32-bit values, we're in\n * slightly better shape. Unfortunately, we really can't do our favorite binary\n * & in this system. It really seems to do the wrong thing. For example:\n *\n * > -32 & 0xff\n * 224\n *\n * What's happening above is really: 0xe0 & 0xff = 0xe0. However, the results of\n * this aren't treated as a signed number. Ultimately a bad thing.\n *\n * What we're going to want to do is basically create the unsigned equivalent of\n * our representation and pass that off to the wuint* functions. To do that\n * we're going to do the following:\n *\n *  - if the value is positive\n *      we can pass it directly off to the equivalent wuint\n *  - if the value is negative\n *      we do the following computation:\n *         mb + val + 1, where\n *         mb   is the maximum unsigned value in that byte size\n *         val  is the Javascript negative integer\n *\n *\n * As a concrete value, take -128. In signed 16 bits this would be 0xff80. If\n * you do out the computations:\n *\n * 0xffff - 128 + 1\n * 0xffff - 127\n * 0xff80\n *\n * You can then encode this value as the signed version. This is really rather\n * hacky, but it should work and get the job done which is our goal here.\n */\n\n/*\n * A series of checks to make sure we actually have a signed 32-bit number\n */\nfunction verifsint(value, max, min) {\n  assert.ok(typeof (value) == 'number',\n      'cannot write a non-number as a number');\n\n  assert.ok(value <= max, 'value larger than maximum allowed value');\n\n  assert.ok(value >= min, 'value smaller than minimum allowed value');\n\n  assert.ok(Math.floor(value) === value, 'value has a fractional component');\n}\n\nfunction verifIEEE754(value, max, min) {\n  assert.ok(typeof (value) == 'number',\n      'cannot write a non-number as a number');\n\n  assert.ok(value <= max, 'value larger than maximum allowed value');\n\n  assert.ok(value >= min, 'value smaller than minimum allowed value');\n}\n\nBuffer.prototype.writeInt8 = function(value, offset, noAssert) {\n  var buffer = this;\n\n  if (!noAssert) {\n    assert.ok(value !== undefined && value !== null,\n        'missing value');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset < buffer.length,\n        'Trying to write beyond buffer length');\n\n    verifsint(value, 0x7f, -0x80);\n  }\n\n  if (value >= 0) {\n    buffer.writeUInt8(value, offset, noAssert);\n  } else {\n    buffer.writeUInt8(0xff + value + 1, offset, noAssert);\n  }\n};\n\nfunction writeInt16(buffer, value, offset, isBigEndian, noAssert) {\n  if (!noAssert) {\n    assert.ok(value !== undefined && value !== null,\n        'missing value');\n\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset + 1 < buffer.length,\n        'Trying to write beyond buffer length');\n\n    verifsint(value, 0x7fff, -0x8000);\n  }\n\n  if (value >= 0) {\n    writeUInt16(buffer, value, offset, isBigEndian, noAssert);\n  } else {\n    writeUInt16(buffer, 0xffff + value + 1, offset, isBigEndian, noAssert);\n  }\n}\n\nBuffer.prototype.writeInt16LE = function(value, offset, noAssert) {\n  writeInt16(this, value, offset, false, noAssert);\n};\n\nBuffer.prototype.writeInt16BE = function(value, offset, noAssert) {\n  writeInt16(this, value, offset, true, noAssert);\n};\n\nfunction writeInt32(buffer, value, offset, isBigEndian, noAssert) {\n  if (!noAssert) {\n    assert.ok(value !== undefined && value !== null,\n        'missing value');\n\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset + 3 < buffer.length,\n        'Trying to write beyond buffer length');\n\n    verifsint(value, 0x7fffffff, -0x80000000);\n  }\n\n  if (value >= 0) {\n    writeUInt32(buffer, value, offset, isBigEndian, noAssert);\n  } else {\n    writeUInt32(buffer, 0xffffffff + value + 1, offset, isBigEndian, noAssert);\n  }\n}\n\nBuffer.prototype.writeInt32LE = function(value, offset, noAssert) {\n  writeInt32(this, value, offset, false, noAssert);\n};\n\nBuffer.prototype.writeInt32BE = function(value, offset, noAssert) {\n  writeInt32(this, value, offset, true, noAssert);\n};\n\nfunction writeFloat(buffer, value, offset, isBigEndian, noAssert) {\n  if (!noAssert) {\n    assert.ok(value !== undefined && value !== null,\n        'missing value');\n\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset + 3 < buffer.length,\n        'Trying to write beyond buffer length');\n\n    verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38);\n  }\n\n  require('./buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian,\n      23, 4);\n}\n\nBuffer.prototype.writeFloatLE = function(value, offset, noAssert) {\n  writeFloat(this, value, offset, false, noAssert);\n};\n\nBuffer.prototype.writeFloatBE = function(value, offset, noAssert) {\n  writeFloat(this, value, offset, true, noAssert);\n};\n\nfunction writeDouble(buffer, value, offset, isBigEndian, noAssert) {\n  if (!noAssert) {\n    assert.ok(value !== undefined && value !== null,\n        'missing value');\n\n    assert.ok(typeof (isBigEndian) === 'boolean',\n        'missing or invalid endian');\n\n    assert.ok(offset !== undefined && offset !== null,\n        'missing offset');\n\n    assert.ok(offset + 7 < buffer.length,\n        'Trying to write beyond buffer length');\n\n    verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308);\n  }\n\n  require('./buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian,\n      52, 8);\n}\n\nBuffer.prototype.writeDoubleLE = function(value, offset, noAssert) {\n  writeDouble(this, value, offset, false, noAssert);\n};\n\nBuffer.prototype.writeDoubleBE = function(value, offset, noAssert) {\n  writeDouble(this, value, offset, true, noAssert);\n};\n\nSlowBuffer.prototype.readUInt8 = Buffer.prototype.readUInt8;\nSlowBuffer.prototype.readUInt16LE = Buffer.prototype.readUInt16LE;\nSlowBuffer.prototype.readUInt16BE = Buffer.prototype.readUInt16BE;\nSlowBuffer.prototype.readUInt32LE = Buffer.prototype.readUInt32LE;\nSlowBuffer.prototype.readUInt32BE = Buffer.prototype.readUInt32BE;\nSlowBuffer.prototype.readInt8 = Buffer.prototype.readInt8;\nSlowBuffer.prototype.readInt16LE = Buffer.prototype.readInt16LE;\nSlowBuffer.prototype.readInt16BE = Buffer.prototype.readInt16BE;\nSlowBuffer.prototype.readInt32LE = Buffer.prototype.readInt32LE;\nSlowBuffer.prototype.readInt32BE = Buffer.prototype.readInt32BE;\nSlowBuffer.prototype.readFloatLE = Buffer.prototype.readFloatLE;\nSlowBuffer.prototype.readFloatBE = Buffer.prototype.readFloatBE;\nSlowBuffer.prototype.readDoubleLE = Buffer.prototype.readDoubleLE;\nSlowBuffer.prototype.readDoubleBE = Buffer.prototype.readDoubleBE;\nSlowBuffer.prototype.writeUInt8 = Buffer.prototype.writeUInt8;\nSlowBuffer.prototype.writeUInt16LE = Buffer.prototype.writeUInt16LE;\nSlowBuffer.prototype.writeUInt16BE = Buffer.prototype.writeUInt16BE;\nSlowBuffer.prototype.writeUInt32LE = Buffer.prototype.writeUInt32LE;\nSlowBuffer.prototype.writeUInt32BE = Buffer.prototype.writeUInt32BE;\nSlowBuffer.prototype.writeInt8 = Buffer.prototype.writeInt8;\nSlowBuffer.prototype.writeInt16LE = Buffer.prototype.writeInt16LE;\nSlowBuffer.prototype.writeInt16BE = Buffer.prototype.writeInt16BE;\nSlowBuffer.prototype.writeInt32LE = Buffer.prototype.writeInt32LE;\nSlowBuffer.prototype.writeInt32BE = Buffer.prototype.writeInt32BE;\nSlowBuffer.prototype.writeFloatLE = Buffer.prototype.writeFloatLE;\nSlowBuffer.prototype.writeFloatBE = Buffer.prototype.writeFloatBE;\nSlowBuffer.prototype.writeDoubleLE = Buffer.prototype.writeDoubleLE;\nSlowBuffer.prototype.writeDoubleBE = Buffer.prototype.writeDoubleBE;\n\n})()\n},{\"assert\":12,\"./buffer_ieee754\":14,\"base64-js\":15}],15:[function(require,module,exports){\n(function (exports) {\n    'use strict';\n\n    var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n\n    function b64ToByteArray(b64) {\n        var i, j, l, tmp, placeHolders, arr;\n\n        if (b64.length % 4 > 0) {\n            throw 'Invalid string. Length must be a multiple of 4';\n        }\n\n        // the number of equal signs (place holders)\n        // if there are two placeholders, than the two characters before it\n        // represent one byte\n        // if there is only one, then the three characters before it represent 2 bytes\n        // this is just a cheap hack to not do indexOf twice\n        placeHolders = b64.indexOf('=');\n        placeHolders = placeHolders > 0 ? b64.length - placeHolders : 0;\n\n        // base64 is 4/3 + up to two characters of the original data\n        arr = [];//new Uint8Array(b64.length * 3 / 4 - placeHolders);\n\n        // if there are placeholders, only get up to the last complete 4 chars\n        l = placeHolders > 0 ? b64.length - 4 : b64.length;\n\n        for (i = 0, j = 0; i < l; i += 4, j += 3) {\n            tmp = (lookup.indexOf(b64[i]) << 18) | (lookup.indexOf(b64[i + 1]) << 12) | (lookup.indexOf(b64[i + 2]) << 6) | lookup.indexOf(b64[i + 3]);\n            arr.push((tmp & 0xFF0000) >> 16);\n            arr.push((tmp & 0xFF00) >> 8);\n            arr.push(tmp & 0xFF);\n        }\n\n        if (placeHolders === 2) {\n            tmp = (lookup.indexOf(b64[i]) << 2) | (lookup.indexOf(b64[i + 1]) >> 4);\n            arr.push(tmp & 0xFF);\n        } else if (placeHolders === 1) {\n            tmp = (lookup.indexOf(b64[i]) << 10) | (lookup.indexOf(b64[i + 1]) << 4) | (lookup.indexOf(b64[i + 2]) >> 2);\n            arr.push((tmp >> 8) & 0xFF);\n            arr.push(tmp & 0xFF);\n        }\n\n        return arr;\n    }\n\n    function uint8ToBase64(uint8) {\n        var i,\n            extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes\n            output = \"\",\n            temp, length;\n\n        function tripletToBase64 (num) {\n            return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F];\n        };\n\n        // go through the array every three bytes, we'll deal with trailing stuff later\n        for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {\n            temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]);\n            output += tripletToBase64(temp);\n        }\n\n        // pad the end with zeros, but make sure to not forget the extra bytes\n        switch (extraBytes) {\n            case 1:\n                temp = uint8[uint8.length - 1];\n                output += lookup[temp >> 2];\n                output += lookup[(temp << 4) & 0x3F];\n                output += '==';\n                break;\n            case 2:\n                temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]);\n                output += lookup[temp >> 10];\n                output += lookup[(temp >> 4) & 0x3F];\n                output += lookup[(temp << 2) & 0x3F];\n                output += '=';\n                break;\n        }\n\n        return output;\n    }\n\n    module.exports.toByteArray = b64ToByteArray;\n    module.exports.fromByteArray = uint8ToBase64;\n}());\n\n},{}]},{},[\"E/GbHF\"])\n;\nJSHINT = require('jshint').JSHINT;\n}());\n\n// Make JSHINT a Node module, if possible.\nif (typeof exports === \"object\" && exports) {\n    exports.JSHINT = JSHINT;\n}\n"
  },
  {
    "path": "sublimelinter/modules/libs/jshint/linter.js",
    "content": "/*jshint node: true */\n/*globals LINTER_PATH load */\n\nvar JSHINT = require(\"./jshint\").JSHINT;\n\nexports.lint = function (code, config) {\n    var globals,\n        results = [];\n\n    if (config.globals) {\n        globals = config.globals;\n        delete config.globals;\n    }\n\n    try {\n        JSHINT(code, config, globals);\n    } catch (e) {\n        results.push({line: 1, character: 1, reason: e.message});\n    } finally {\n        JSHINT.errors.forEach(function (error) {\n            if (error) {\n                results.push(error);\n            }\n        });\n    }\n\n    return results;\n};\n"
  },
  {
    "path": "sublimelinter/modules/libs/jslint/jslint.js",
    "content": "// jslint.js\n// 2013-07-24\n\n// Copyright (c) 2002 Douglas Crockford  (www.JSLint.com)\n\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n\n// The Software shall be used for Good, not Evil.\n\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\n// WARNING: JSLint will hurt your feelings.\n\n// JSLINT is a global function. It takes two parameters.\n\n//     var myResult = JSLINT(source, option);\n\n// The first parameter is either a string or an array of strings. If it is a\n// string, it will be split on '\\n' or '\\r'. If it is an array of strings, it\n// is assumed that each string represents one line. The source can be a\n// JavaScript text or a JSON text.\n\n// The second parameter is an optional object of options that control the\n// operation of JSLINT. Most of the options are booleans: They are all\n// optional and have a default value of false. One of the options, predef,\n// can be an array of names, which will be used to declare global variables,\n// or an object whose keys are used as global names, with a boolean value\n// that determines if they are assignable.\n\n// If it checks out, JSLINT returns true. Otherwise, it returns false.\n\n// If false, you can inspect JSLINT.errors to find out the problems.\n// JSLINT.errors is an array of objects containing these properties:\n\n//  {\n//      line      : The line (relative to 0) at which the lint was found\n//      character : The character (relative to 0) at which the lint was found\n//      reason    : The problem\n//      evidence  : The text line in which the problem occurred\n//      raw       : The raw message before the details were inserted\n//      a         : The first detail\n//      b         : The second detail\n//      c         : The third detail\n//      d         : The fourth detail\n//  }\n\n// If a stopping error was found, a null will be the last element of the\n// JSLINT.errors array. A stopping error means that JSLint was not confident\n// enough to continue. It does not necessarily mean that the error was\n// especially heinous.\n\n// You can request a data structure that contains JSLint's results.\n\n//     var myData = JSLINT.data();\n\n// It returns a structure with this form:\n\n//     {\n//         errors: [\n//             {\n//                 line: NUMBER,\n//                 character: NUMBER,\n//                 reason: STRING,\n//                 evidence: STRING\n//             }\n//         ],\n//         functions: [\n//             {\n//                 name: STRING,\n//                 line: NUMBER,\n//                 level: NUMBER,\n//                 parameter: [\n//                     STRING\n//                 ],\n//                 var: [\n//                     STRING\n//                 ],\n//                 exception: [\n//                     STRING\n//                 ],\n//                 closure: [\n//                     STRING\n//                 ],\n//                 outer: [\n//                     STRING\n//                 ],\n//                 global: [\n//                     STRING\n//                 ],\n//                 label: [\n//                     STRING\n//                 ]\n//             }\n//         ],\n//         global: [\n//             STRING\n//         ],\n//         member: {\n//             STRING: NUMBER\n//         },\n//         json: BOOLEAN\n//     }\n\n// You can request a Function Report, which shows all of the functions\n// and the parameters and vars that they use. This can be used to find\n// implied global variables and other problems. The report is in HTML and\n// can be inserted into an HTML <body>. It should be given the result of the\n// JSLINT.data function.\n\n//     var myReport = JSLINT.report(data);\n\n// You can request an HTML error report.\n\n//     var myErrorReport = JSLINT.error_report(data);\n\n// You can obtain an object containing all of the properties found in the\n// file. JSLINT.property contains an object containing a key for each\n// property used in the program, the value being the number of times that\n// property name was used in the file.\n\n// You can request a properties report, which produces a list of the program's\n// properties in the form of a /*properties*/ declaration.\n\n//      var myPropertyReport = JSLINT.properties_report(JSLINT.property);\n\n// You can obtain the parse tree that JSLint constructed while parsing. The\n// latest tree is kept in JSLINT.tree. A nice stringification can be produced\n// with\n\n//     JSON.stringify(JSLINT.tree, [\n//         'string',  'arity', 'name',  'first',\n//         'second', 'third', 'block', 'else'\n//     ], 4));\n\n// You can request a context coloring table. It contains information that can be\n// applied to the file that was analyzed. Context coloring colors functions\n// based on their nesting level, and variables on the color of the functions\n// in which they are defined.\n\n//      var myColorization = JSLINT.color(data);\n\n// It returns an array containing objects of this form:\n\n//      {\n//          from: COLUMN,\n//          thru: COLUMN,\n//          line: ROW,\n//          level: 0 or higher\n//      }\n\n// JSLint provides three inline directives. They look like slashstar comments,\n// and allow for setting options, declaring global variables, and establishing a\n// set of allowed property names.\n\n// These directives respect function scope.\n\n// The jslint directive is a special comment that can set one or more options.\n// For example:\n\n/*jslint\n    es5: true, evil: true, nomen: true, regexp: true, todo: true\n*/\n\n// The current option set is\n\n//     ass        true, if assignment expressions should be allowed\n//     bitwise    true, if bitwise operators should be allowed\n//     browser    true, if the standard browser globals should be predefined\n//     closure    true, if Google Closure idioms should be tolerated\n//     continue   true, if the continuation statement should be tolerated\n//     debug      true, if debugger statements should be allowed\n//     devel      true, if logging should be allowed (console, alert, etc.)\n//     eqeq       true, if == should be allowed\n//     es5        true, if ES5 syntax should be allowed\n//     evil       true, if eval should be allowed\n//     forin      true, if for in statements need not filter\n//     indent     the indentation factor\n//     maxerr     the maximum number of errors to allow\n//     maxlen     the maximum length of a source line\n//     newcap     true, if constructor names capitalization is ignored\n//     node       true, if Node.js globals should be predefined\n//     nomen      true, if names may have dangling _\n//     passfail   true, if the scan should stop on first error\n//     plusplus   true, if increment/decrement should be allowed\n//     properties true, if all property names must be declared with /*properties*/\n//     regexp     true, if the . should be allowed in regexp literals\n//     rhino      true, if the Rhino environment globals should be predefined\n//     unparam    true, if unused parameters should be tolerated\n//     sloppy     true, if the 'use strict'; pragma is optional\n//     stupid     true, if really stupid practices are tolerated\n//     sub        true, if all forms of subscript notation are tolerated\n//     todo       true, if TODO comments are tolerated\n//     vars       true, if multiple var statements per function should be allowed\n//     white      true, if sloppy whitespace is tolerated\n\n// The properties directive declares an exclusive list of property names.\n// Any properties named in the program that are not in the list will\n// produce a warning.\n\n// For example:\n\n/*properties\n    '\\b', '\\t', '\\n', '\\f', '\\r', '!', '!=', '!==', '\"', '%', '\\'', '(begin)',\n    '(error)', '*', '+', '-', '/', '<', '<=', '==', '===', '>', '>=', '\\\\', a,\n    a_label, a_scope, already_defined, and, arguments, arity, ass, assign,\n    assignment_expression, assignment_function_expression, at, avoid_a, b,\n    bad_assignment, bad_constructor, bad_in_a, bad_invocation, bad_new,\n    bad_number, bad_operand, bad_wrap, bitwise, block, browser, c, call, charAt,\n    charCodeAt, character, closure, code, color, combine_var, comments,\n    conditional_assignment, confusing_a, confusing_regexp, constructor_name_a,\n    continue, control_a, couch, create, d, dangling_a, data, dead, debug,\n    deleted, devel, disrupt, duplicate_a, edge, edition, else, empty_block,\n    empty_case, empty_class, entityify, eqeq, error_report, errors, es5,\n    evidence, evil, exception, exec, expected_a_at_b_c, expected_a_b,\n    expected_a_b_from_c_d, expected_id_a, expected_identifier_a,\n    expected_identifier_a_reserved, expected_number_a, expected_operator_a,\n    expected_positive_a, expected_small_a, expected_space_a_b,\n    expected_string_a, f, first, flag, floor, forEach, for_if, forin, from,\n    fromCharCode, fud, function, function_block, function_eval, function_loop,\n    function_statement, function_strict, functions, global, hasOwnProperty, id,\n    identifier, identifier_function, immed, implied_evil, indent, indexOf,\n    infix_in, init, insecure_a, isAlpha, isArray, isDigit, isNaN, join, jslint,\n    json, keys, kind, label, labeled, lbp, leading_decimal_a, led, left, length,\n    level, line, loopage, master, match, maxerr, maxlen, message, missing_a,\n    missing_a_after_b, missing_property, missing_space_a_b, missing_use_strict,\n    mode, move_invocation, move_var, n, name, name_function, nested_comment,\n    newcap, node, nomen, not, not_a_constructor, not_a_defined, not_a_function,\n    not_a_label, not_a_scope, not_greater, nud, number, octal_a, open, outer,\n    parameter, parameter_a_get_b, parameter_arguments_a, parameter_set_a,\n    params, paren, passfail, plusplus, postscript, predef, properties,\n    properties_report, property, prototype, push, quote, r, radix, raw,\n    read_only, reason, redefinition_a_b, regexp, relation, replace, report,\n    reserved, reserved_a, rhino, right, scanned_a_b, scope, search, second,\n    shift, slash_equal, slice, sloppy, sort, split, statement, statement_block,\n    stop, stopping, strange_loop, strict, string, stupid, sub, subscript,\n    substr, supplant, sync_a, t, tag_a_in_b, test, third, thru, toString, todo,\n    todo_comment, token, tokens, too_long, too_many, trailing_decimal_a, tree,\n    unclosed, unclosed_comment, unclosed_regexp, unescaped_a, unexpected_a,\n    unexpected_char_a, unexpected_comment, unexpected_label_a,\n    unexpected_property_a, unexpected_space_a_b, unexpected_typeof_a,\n    uninitialized_a, unnecessary_else, unnecessary_initialize, unnecessary_use,\n    unparam, unreachable_a_b, unsafe, unused_a, url, use_array, use_braces,\n    use_object, use_or, use_param, use_spaces, used, used_before_a, var,\n    var_a_not, var_loop, vars, varstatement, warn, warning, was,\n    weird_assignment, weird_condition, weird_new, weird_program, weird_relation,\n    weird_ternary, white, wrap, wrap_immediate, wrap_regexp, write_is_wrong,\n    writeable\n*/\n\n// The global directive is used to declare global variables that can\n// be accessed by the program. If a declaration is true, then the variable\n// is writeable. Otherwise, it is read-only.\n\n// We build the application inside a function so that we produce only a single\n// global variable. That function will be invoked immediately, and its return\n// value is the JSLINT function itself. That function is also an object that\n// can contain data and other functions.\n\nvar JSLINT = (function () {\n    'use strict';\n\n    function array_to_object(array, value) {\n\n// Make an object from an array of keys and a common value.\n\n        var i, length = array.length, object = Object.create(null);\n        for (i = 0; i < length; i += 1) {\n            object[array[i]] = value;\n        }\n        return object;\n    }\n\n\n    var allowed_option = {\n            ass       : true,\n            bitwise   : true,\n            browser   : true,\n            closure   : true,\n            continue  : true,\n            couch     : true,\n            debug     : true,\n            devel     : true,\n            eqeq      : true,\n            es5       : true,\n            evil      : true,\n            forin     : true,\n            indent    :   10,\n            maxerr    : 1000,\n            maxlen    :  256,\n            newcap    : true,\n            node      : true,\n            nomen     : true,\n            passfail  : true,\n            plusplus  : true,\n            properties: true,\n            regexp    : true,\n            rhino     : true,\n            unparam   : true,\n            sloppy    : true,\n            stupid    : true,\n            sub       : true,\n            todo      : true,\n            vars      : true,\n            white     : true\n        },\n        anonname,       // The guessed name for anonymous functions.\n\n// These are operators that should not be used with the ! operator.\n\n        bang = {\n            '<'  : true,\n            '<=' : true,\n            '==' : true,\n            '===': true,\n            '!==': true,\n            '!=' : true,\n            '>'  : true,\n            '>=' : true,\n            '+'  : true,\n            '-'  : true,\n            '*'  : true,\n            '/'  : true,\n            '%'  : true\n        },\n        begin,          // The root token\n        block_var,     // vars defined in the current block\n\n// browser contains a set of global names that are commonly provided by a\n// web browser environment.\n\n        browser = array_to_object([\n            'clearInterval', 'clearTimeout', 'document', 'event', 'FormData',\n            'frames', 'history', 'Image', 'localStorage', 'location', 'name',\n            'navigator', 'Option', 'parent', 'screen', 'sessionStorage',\n            'setInterval', 'setTimeout', 'Storage', 'window', 'XMLHttpRequest'\n        ], false),\n\n// bundle contains the text messages.\n\n        bundle = {\n            a_label: \"'{a}' is a statement label.\",\n            a_scope: \"'{a}' used out of scope.\",\n            already_defined: \"'{a}' is already defined.\",\n            and: \"The '&&' subexpression should be wrapped in parens.\",\n            assignment_expression: \"Unexpected assignment expression.\",\n            assignment_function_expression: \"Expected an assignment or \" +\n                \"function call and instead saw an expression.\",\n            avoid_a: \"Avoid '{a}'.\",\n            bad_assignment: \"Bad assignment.\",\n            bad_constructor: \"Bad constructor.\",\n            bad_in_a: \"Bad for in variable '{a}'.\",\n            bad_invocation: \"Bad invocation.\",\n            bad_new: \"Do not use 'new' for side effects.\",\n            bad_number: \"Bad number '{a}'.\",\n            bad_operand: \"Bad operand.\",\n            bad_wrap: \"Do not wrap function literals in parens unless they \" +\n                \"are to be immediately invoked.\",\n            combine_var: \"Combine this with the previous 'var' statement.\",\n            conditional_assignment: \"Expected a conditional expression and \" +\n                \"instead saw an assignment.\",\n            confusing_a: \"Confusing use of '{a}'.\",\n            confusing_regexp: \"Confusing regular expression.\",\n            constructor_name_a: \"A constructor name '{a}' should start with \" +\n                \"an uppercase letter.\",\n            control_a: \"Unexpected control character '{a}'.\",\n            dangling_a: \"Unexpected dangling '_' in '{a}'.\",\n            deleted: \"Only properties should be deleted.\",\n            duplicate_a: \"Duplicate '{a}'.\",\n            empty_block: \"Empty block.\",\n            empty_case: \"Empty case.\",\n            empty_class: \"Empty class.\",\n            es5: \"This is an ES5 feature.\",\n            evil: \"eval is evil.\",\n            expected_a_b: \"Expected '{a}' and instead saw '{b}'.\",\n            expected_a_b_from_c_d: \"Expected '{a}' to match '{b}' from line \" +\n                \"{c} and instead saw '{d}'.\",\n            expected_a_at_b_c: \"Expected '{a}' at column {b}, not column {c}.\",\n            expected_id_a: \"Expected an id, and instead saw #{a}.\",\n            expected_identifier_a: \"Expected an identifier and instead saw '{a}'.\",\n            expected_identifier_a_reserved: \"Expected an identifier and \" +\n                \"instead saw '{a}' (a reserved word).\",\n            expected_number_a: \"Expected a number and instead saw '{a}'.\",\n            expected_operator_a: \"Expected an operator and instead saw '{a}'.\",\n            expected_positive_a: \"Expected a positive number and instead saw '{a}'\",\n            expected_small_a: \"Expected a small positive integer and instead saw '{a}'\",\n            expected_space_a_b: \"Expected exactly one space between '{a}' and '{b}'.\",\n            expected_string_a: \"Expected a string and instead saw '{a}'.\",\n            for_if: \"The body of a for in should be wrapped in an if \" +\n                \"statement to filter unwanted properties from the prototype.\",\n            function_block: \"Function statements should not be placed in blocks.\" +\n                \"Use a function expression or move the statement to the top of \" +\n                \"the outer function.\",\n            function_eval: \"The Function constructor is eval.\",\n            function_loop: \"Don't make functions within a loop.\",\n            function_statement: \"Function statements are not invocable. \" +\n                \"Wrap the whole function invocation in parens.\",\n            function_strict: \"Use the function form of 'use strict'.\",\n            identifier_function: \"Expected an identifier in an assignment \" +\n                \"and instead saw a function invocation.\",\n            implied_evil: \"Implied eval is evil. Pass a function instead of a string.\",\n            infix_in: \"Unexpected 'in'. Compare with undefined, or use the \" +\n                \"hasOwnProperty method instead.\",\n            insecure_a: \"Insecure '{a}'.\",\n            isNaN: \"Use the isNaN function to compare with NaN.\",\n            leading_decimal_a: \"A leading decimal point can be confused with a dot: '.{a}'.\",\n            missing_a: \"Missing '{a}'.\",\n            missing_a_after_b: \"Missing '{a}' after '{b}'.\",\n            missing_property: \"Missing property name.\",\n            missing_space_a_b: \"Missing space between '{a}' and '{b}'.\",\n            missing_use_strict: \"Missing 'use strict' statement.\",\n            move_invocation: \"Move the invocation into the parens that \" +\n                \"contain the function.\",\n            move_var: \"Move 'var' declarations to the top of the function.\",\n            name_function: \"Missing name in function statement.\",\n            nested_comment: \"Nested comment.\",\n            not: \"Nested not.\",\n            not_a_constructor: \"Do not use {a} as a constructor.\",\n            not_a_defined: \"'{a}' has not been fully defined yet.\",\n            not_a_function: \"'{a}' is not a function.\",\n            not_a_label: \"'{a}' is not a label.\",\n            not_a_scope: \"'{a}' is out of scope.\",\n            not_greater: \"'{a}' should not be greater than '{b}'.\",\n            octal_a: \"Don't use octal: '{a}'. Use '\\\\u....' instead.\",\n            parameter_arguments_a: \"Do not mutate parameter '{a}' when using 'arguments'.\",\n            parameter_a_get_b: \"Unexpected parameter '{a}' in get {b} function.\",\n            parameter_set_a: \"Expected parameter (value) in set {a} function.\",\n            radix: \"Missing radix parameter.\",\n            read_only: \"Read only.\",\n            redefinition_a_b: \"Redefinition of '{a}' from line {b}.\",\n            reserved_a: \"Reserved name '{a}'.\",\n            scanned_a_b: \"{a} ({b}% scanned).\",\n            slash_equal: \"A regular expression literal can be confused with '/='.\",\n            statement_block: \"Expected to see a statement and instead saw a block.\",\n            stopping: \"Stopping.\",\n            strange_loop: \"Strange loop.\",\n            strict: \"Strict violation.\",\n            subscript: \"['{a}'] is better written in dot notation.\",\n            sync_a: \"Unexpected sync method: '{a}'.\",\n            tag_a_in_b: \"A '<{a}>' must be within '<{b}>'.\",\n            todo_comment: \"Unexpected TODO comment.\",\n            too_long: \"Line too long.\",\n            too_many: \"Too many errors.\",\n            trailing_decimal_a: \"A trailing decimal point can be confused \" +\n                \"with a dot: '.{a}'.\",\n            unclosed: \"Unclosed string.\",\n            unclosed_comment: \"Unclosed comment.\",\n            unclosed_regexp: \"Unclosed regular expression.\",\n            unescaped_a: \"Unescaped '{a}'.\",\n            unexpected_a: \"Unexpected '{a}'.\",\n            unexpected_char_a: \"Unexpected character '{a}'.\",\n            unexpected_comment: \"Unexpected comment.\",\n            unexpected_label_a: \"Unexpected label '{a}'.\",\n            unexpected_property_a: \"Unexpected /*property*/ '{a}'.\",\n            unexpected_space_a_b: \"Unexpected space between '{a}' and '{b}'.\",\n            unexpected_typeof_a: \"Unexpected 'typeof'. \" +\n                \"Use '===' to compare directly with {a}.\",\n            uninitialized_a: \"Uninitialized '{a}'.\",\n            unnecessary_else: \"Unnecessary 'else' after disruption.\",\n            unnecessary_initialize: \"It is not necessary to initialize '{a}' \" +\n                \"to 'undefined'.\",\n            unnecessary_use: \"Unnecessary 'use strict'.\",\n            unreachable_a_b: \"Unreachable '{a}' after '{b}'.\",\n            unsafe: \"Unsafe character.\",\n            unused_a: \"Unused '{a}'.\",\n            url: \"JavaScript URL.\",\n            use_array: \"Use the array literal notation [].\",\n            use_braces: \"Spaces are hard to count. Use {{a}}.\",\n            use_object: \"Use the object literal notation {} or Object.create(null).\",\n            use_or: \"Use the || operator.\",\n            use_param: \"Use a named parameter.\",\n            use_spaces: \"Use spaces, not tabs.\",\n            used_before_a: \"'{a}' was used before it was defined.\",\n            var_a_not: \"Variable {a} was not declared correctly.\",\n            var_loop: \"Don't declare variables in a loop.\",\n            weird_assignment: \"Weird assignment.\",\n            weird_condition: \"Weird condition.\",\n            weird_new: \"Weird construction. Delete 'new'.\",\n            weird_program: \"Weird program.\",\n            weird_relation: \"Weird relation.\",\n            weird_ternary: \"Weird ternary.\",\n            wrap_immediate: \"Wrap an immediate function invocation in \" +\n                \"parentheses to assist the reader in understanding that the \" +\n                \"expression is the result of a function, and not the \" +\n                \"function itself.\",\n            wrap_regexp: \"Wrap the /regexp/ literal in parens to \" +\n                \"disambiguate the slash operator.\",\n            write_is_wrong: \"document.write can be a form of eval.\"\n        },\n        closure = array_to_object([\n            'goog'\n        ], false),\n        comments,\n        comments_off,\n        couch = array_to_object([\n            'emit', 'getRow', 'isArray', 'log', 'provides', 'registerType',\n            'require', 'send', 'start', 'sum', 'toJSON'\n        ], false),\n\n        descapes = {\n            'b': '\\b',\n            't': '\\t',\n            'n': '\\n',\n            'f': '\\f',\n            'r': '\\r',\n            '\"': '\"',\n            '/': '/',\n            '\\\\': '\\\\',\n            '!': '!'\n        },\n\n        devel = array_to_object([\n            'alert', 'confirm', 'console', 'Debug', 'opera', 'prompt', 'WSH'\n        ], false),\n        directive,\n        escapes = {\n            '\\b': '\\\\b',\n            '\\t': '\\\\t',\n            '\\n': '\\\\n',\n            '\\f': '\\\\f',\n            '\\r': '\\\\r',\n            '\\'': '\\\\\\'',\n            '\"' : '\\\\\"',\n            '/' : '\\\\/',\n            '\\\\': '\\\\\\\\'\n        },\n\n        funct,          // The current function\n\n        functions,      // All of the functions\n        global_funct,   // The global body\n        global_scope,   // The global scope\n        in_block,       // Where function statements are not allowed\n        indent,\n        itself,         // JSLINT itself\n        json_mode,\n        lex,            // the tokenizer\n        lines,\n        lookahead,\n        node = array_to_object([\n            'Buffer', 'clearImmediate', 'clearInterval', 'clearTimeout',\n            'console', 'exports', 'global', 'module', 'process', 'querystring',\n            'require', 'setImmediate', 'setInterval', 'setTimeout',\n            '__dirname', '__filename'\n        ], false),\n        node_js,\n        numbery = array_to_object(['indexOf', 'lastIndexOf', 'search'], true),\n        next_token,\n        option,\n        predefined,     // Global variables defined by option\n        prereg,\n        prev_token,\n        property,\n        protosymbol,\n        regexp_flag = array_to_object(['g', 'i', 'm'], true),\n        return_this = function return_this() {\n            return this;\n        },\n        rhino = array_to_object([\n            'defineClass', 'deserialize', 'gc', 'help', 'load', 'loadClass',\n            'print', 'quit', 'readFile', 'readUrl', 'runCommand', 'seal',\n            'serialize', 'spawn', 'sync', 'toint32', 'version'\n        ], false),\n\n        scope,      // An object containing an object for each variable in scope\n        semicolon_coda = array_to_object([';', '\"', '\\'', ')'], true),\n\n// standard contains the global names that are provided by the\n// ECMAScript standard.\n\n        standard = array_to_object([\n            'Array', 'Boolean', 'Date', 'decodeURI', 'decodeURIComponent',\n            'encodeURI', 'encodeURIComponent', 'Error', 'eval', 'EvalError',\n            'Function', 'isFinite', 'isNaN', 'JSON', 'Math', 'Number',\n            'Object', 'parseInt', 'parseFloat', 'RangeError', 'ReferenceError',\n            'RegExp', 'String', 'SyntaxError', 'TypeError', 'URIError'\n        ], false),\n\n        strict_mode,\n        syntax = Object.create(null),\n        token,\n        tokens,\n        var_mode,\n        warnings,\n\n// Regular expressions. Some of these are stupidly long.\n\n// carriage return, carriage return linefeed, or linefeed\n        crlfx = /\\r\\n?|\\n/,\n// unsafe characters that are silently deleted by one or more browsers\n        cx = /[\\u0000-\\u0008\\u000a-\\u001f\\u007f-\\u009f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/,\n// identifier\n        ix = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/,\n// javascript url\n        jx = /^(?:javascript|jscript|ecmascript|vbscript)\\s*:/i,\n// star slash\n        lx = /\\*\\/|\\/\\*/,\n// characters in strings that need escapement\n        nx = /[\\u0000-\\u001f'\\\\\\u007f-\\u009f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g,\n// sync\n        syx = /Sync$/,\n// comment todo\n        tox = /^\\W*to\\s*do(?:\\W|$)/i,\n// token\n        tx = /^\\s*([(){}\\[\\]\\?.,:;'\"~#@`]|={1,3}|\\/(\\*(jslint|properties|property|members?|globals?)?|=|\\/)?|\\*[\\/=]?|\\+(?:=|\\++)?|-(?:=|-+)?|[\\^%]=?|&[&=]?|\\|[|=]?|>{1,3}=?|<(?:[\\/=!]|\\!(\\[|--)?|<=?)?|\\!(\\!|==?)?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+(?:[xX][0-9a-fA-F]+|\\.[0-9]*)?(?:[eE][+\\-]?[0-9]+)?)/;\n\n\n    if (typeof String.prototype.entityify !== 'function') {\n        String.prototype.entityify = function () {\n            return this\n                .replace(/&/g, '&amp;')\n                .replace(/</g, '&lt;')\n                .replace(/>/g, '&gt;');\n        };\n    }\n\n    if (typeof String.prototype.isAlpha !== 'function') {\n        String.prototype.isAlpha = function () {\n            return (this >= 'a' && this <= 'z\\uffff') ||\n                (this >= 'A' && this <= 'Z\\uffff');\n        };\n    }\n\n    if (typeof String.prototype.isDigit !== 'function') {\n        String.prototype.isDigit = function () {\n            return (this >= '0' && this <= '9');\n        };\n    }\n\n    if (typeof String.prototype.supplant !== 'function') {\n        String.prototype.supplant = function (o) {\n            return this.replace(/\\{([^{}]*)\\}/g, function (a, b) {\n                var replacement = o[b];\n                return typeof replacement === 'string' ||\n                    typeof replacement === 'number' ? replacement : a;\n            });\n        };\n    }\n\n\n    function sanitize(a) {\n\n//  Escapify a troublesome character.\n\n        return escapes[a] ||\n            '\\\\u' + ('0000' + a.charCodeAt().toString(16)).slice(-4);\n    }\n\n\n    function add_to_predefined(group) {\n        Object.keys(group).forEach(function (name) {\n            predefined[name] = group[name];\n        });\n    }\n\n\n    function assume() {\n        if (option.browser) {\n            add_to_predefined(browser);\n            option.browser = false;\n        }\n        if (option.closure) {\n            add_to_predefined(closure);\n        }\n        if (option.couch) {\n            add_to_predefined(couch);\n            option.couch = false;\n            option.es5 = true;\n        }\n        if (option.devel) {\n            add_to_predefined(devel);\n            option.devel = false;\n        }\n        if (option.node) {\n            add_to_predefined(node);\n            option.node = false;\n            option.es5 = true;\n            node_js = true;\n        }\n        if (option.rhino) {\n            add_to_predefined(rhino);\n            option.rhino = false;\n        }\n    }\n\n\n// Produce an error warning.\n\n    function artifact(tok) {\n        if (!tok) {\n            tok = next_token;\n        }\n        return tok.id === '(number)' ? tok.number : tok.string;\n    }\n\n    function quit(message, line, character) {\n        throw {\n            name: 'JSLintError',\n            line: line,\n            character: character,\n            message: bundle.scanned_a_b.supplant({\n                a: bundle[message] || message,\n                b: Math.floor((line / lines.length) * 100)\n            })\n        };\n    }\n\n    function warn(code, line, character, a, b, c, d) {\n        var warning = {         // ~~\n            id: '(error)',\n            raw: bundle[code] || code,\n            code: code,\n            evidence: lines[line - 1] || '',\n            line: line,\n            character: character,\n            a: a || artifact(this),\n            b: b,\n            c: c,\n            d: d\n        };\n        warning.reason = warning.raw.supplant(warning);\n        itself.errors.push(warning);\n        if (option.passfail) {\n            quit('stopping', line, character);\n        }\n        warnings += 1;\n        if (warnings >= option.maxerr) {\n            quit('too_many', line, character);\n        }\n        return warning;\n    }\n\n    function stop(code, line, character, a, b, c, d) {\n        var warning = warn(code, line, character, a, b, c, d);\n        quit('stopping', warning.line, warning.character);\n    }\n\n    function expected_at(at) {\n        if (!option.white && next_token.from !== at) {\n            next_token.warn('expected_a_at_b_c', '', at, next_token.from);\n        }\n    }\n\n// lexical analysis and token construction\n\n    lex = (function lex() {\n        var character, c, from, length, line, pos, source_row;\n\n// Private lex methods\n\n        function next_line() {\n            var at;\n            character = 1;\n            source_row = lines[line];\n            line += 1;\n            if (source_row === undefined) {\n                return false;\n            }\n            at = source_row.search(/\\t/);\n            if (at >= 0) {\n                if (option.white) {\n                    source_row = source_row.replace(/\\t/g, ' ');\n                } else {\n                    warn('use_spaces', line, at + 1);\n                }\n            }\n            at = source_row.search(cx);\n            if (at >= 0) {\n                warn('unsafe', line, at);\n            }\n            if (option.maxlen && option.maxlen < source_row.length) {\n                warn('too_long', line, source_row.length);\n            }\n            return true;\n        }\n\n// Produce a token object.  The token inherits from a syntax symbol.\n\n        function it(type, value) {\n            var id, the_token;\n            if (type === '(string)') {\n                if (jx.test(value)) {\n                    warn('url', line, from);\n                }\n            }\n            the_token = Object.create(syntax[(\n                type === '(punctuator)' || (type === '(identifier)' &&\n                        Object.prototype.hasOwnProperty.call(syntax, value))\n                    ? value\n                    : type\n            )] || syntax['(error)']);\n            if (type === '(identifier)') {\n                the_token.identifier = true;\n                if (value === '__iterator__' || value === '__proto__') {\n                    stop('reserved_a', line, from, value);\n                } else if (!option.nomen &&\n                        (value.charAt(0) === '_' ||\n                        value.charAt(value.length - 1) === '_')) {\n                    warn('dangling_a', line, from, value);\n                }\n            }\n            if (type === '(number)') {\n                the_token.number = +value;\n            } else if (value !== undefined) {\n                the_token.string = String(value);\n            }\n            the_token.line = line;\n            the_token.from = from;\n            the_token.thru = character;\n            if (comments.length) {\n                the_token.comments = comments;\n                comments = [];\n            }\n            id = the_token.id;\n            prereg = id && (\n                ('(,=:[!&|?{};~+-*%^<>'.indexOf(id.charAt(id.length - 1)) >= 0) ||\n                id === 'return' || id === 'case'\n            );\n            return the_token;\n        }\n\n        function match(x) {\n            var exec = x.exec(source_row), first;\n            if (exec) {\n                length = exec[0].length;\n                first = exec[1];\n                c = first.charAt(0);\n                source_row = source_row.slice(length);\n                from = character + length - first.length;\n                character += length;\n                return first;\n            }\n            for (;;) {\n                if (!source_row) {\n                    if (!option.white) {\n                        warn('unexpected_char_a', line, character - 1, '(space)');\n                    }\n                    return;\n                }\n                c = source_row.charAt(0);\n                if (c !== ' ') {\n                    break;\n                }\n                source_row = source_row.slice(1);\n                character += 1;\n            }\n            stop('unexpected_char_a', line, character, c);\n\n        }\n\n        function string(x) {\n            var ch, at = 0, r = '', result;\n\n            function hex(n) {\n                var i = parseInt(source_row.substr(at + 1, n), 16);\n                at += n;\n                if (i >= 32 && i <= 126 &&\n                        i !== 34 && i !== 92 && i !== 39) {\n                    warn('unexpected_a', line, character, '\\\\');\n                }\n                character += n;\n                ch = String.fromCharCode(i);\n            }\n\n            if (json_mode && x !== '\"') {\n                warn('expected_a_b', line, character, '\"', x);\n            }\n\n            for (;;) {\n                while (at >= source_row.length) {\n                    at = 0;\n                    if (!next_line()) {\n                        stop('unclosed', line - 1, from);\n                    }\n                }\n                ch = source_row.charAt(at);\n                if (ch === x) {\n                    character += 1;\n                    source_row = source_row.slice(at + 1);\n                    result = it('(string)', r);\n                    result.quote = x;\n                    return result;\n                }\n                if (ch < ' ') {\n                    if (ch === '\\n' || ch === '\\r') {\n                        break;\n                    }\n                    warn('control_a', line, character + at,\n                        source_row.slice(0, at));\n                } else if (ch === '\\\\') {\n                    at += 1;\n                    character += 1;\n                    ch = source_row.charAt(at);\n                    switch (ch) {\n                    case '':\n                        if (!option.es5) {\n                            warn('es5', line, character);\n                        }\n                        next_line();\n                        at = -1;\n                        break;\n                    case '\\'':\n                        if (json_mode) {\n                            warn('unexpected_a', line, character, '\\\\\\'');\n                        }\n                        break;\n                    case 'u':\n                        hex(4);\n                        break;\n                    case 'v':\n                        if (json_mode) {\n                            warn('unexpected_a', line, character, '\\\\v');\n                        }\n                        ch = '\\v';\n                        break;\n                    case 'x':\n                        if (json_mode) {\n                            warn('unexpected_a', line, character, '\\\\x');\n                        }\n                        hex(2);\n                        break;\n                    default:\n                        if (typeof descapes[ch] !== 'string') {\n                            warn(ch >= '0' && ch <= '7' ? 'octal_a' : 'unexpected_a',\n                                line, character, '\\\\' + ch);\n                        } else {\n                            ch = descapes[ch];\n                        }\n                    }\n                }\n                r += ch;\n                character += 1;\n                at += 1;\n            }\n        }\n\n        function number(snippet) {\n            var digit;\n            if (source_row.charAt(0).isAlpha()) {\n                warn('expected_space_a_b',\n                    line, character, c, source_row.charAt(0));\n            }\n            if (c === '0') {\n                digit = snippet.charAt(1);\n                if (digit.isDigit()) {\n                    if (token.id !== '.') {\n                        warn('unexpected_a', line, character, snippet);\n                    }\n                } else if (json_mode && (digit === 'x' || digit === 'X')) {\n                    warn('unexpected_a', line, character, '0x');\n                }\n            }\n            if (snippet.slice(snippet.length - 1) === '.') {\n                warn('trailing_decimal_a', line, character, snippet);\n            }\n            digit = +snippet;\n            if (!isFinite(digit)) {\n                warn('bad_number', line, character, snippet);\n            }\n            snippet = digit;\n            return it('(number)', snippet);\n        }\n\n        function comment(snippet, type) {\n            if (comments_off) {\n                warn('unexpected_comment', line, character);\n            } else if (!option.todo && tox.test(snippet)) {\n                warn('todo_comment', line, character);\n            }\n            comments.push({\n                id: type,\n                from: from,\n                thru: character,\n                line: line,\n                string: snippet\n            });\n        }\n\n        function regexp() {\n            var at = 0,\n                b,\n                bit,\n                depth = 0,\n                flag = '',\n                high,\n                letter,\n                low,\n                potential,\n                quote,\n                result;\n            for (;;) {\n                b = true;\n                c = source_row.charAt(at);\n                at += 1;\n                switch (c) {\n                case '':\n                    stop('unclosed_regexp', line, from);\n                    return;\n                case '/':\n                    if (depth > 0) {\n                        warn('unescaped_a', line, from + at, '/');\n                    }\n                    c = source_row.slice(0, at - 1);\n                    potential = Object.create(regexp_flag);\n                    for (;;) {\n                        letter = source_row.charAt(at);\n                        if (potential[letter] !== true) {\n                            break;\n                        }\n                        potential[letter] = false;\n                        at += 1;\n                        flag += letter;\n                    }\n                    if (source_row.charAt(at).isAlpha()) {\n                        stop('unexpected_a', line, from, source_row.charAt(at));\n                    }\n                    character += at;\n                    source_row = source_row.slice(at);\n                    quote = source_row.charAt(0);\n                    if (quote === '/' || quote === '*') {\n                        stop('confusing_regexp', line, from);\n                    }\n                    result = it('(regexp)', c);\n                    result.flag = flag;\n                    return result;\n                case '\\\\':\n                    c = source_row.charAt(at);\n                    if (c < ' ') {\n                        warn('control_a', line, from + at, String(c));\n                    } else if (c === '<') {\n                        warn('unexpected_a', line, from + at, '\\\\');\n                    }\n                    at += 1;\n                    break;\n                case '(':\n                    depth += 1;\n                    b = false;\n                    if (source_row.charAt(at) === '?') {\n                        at += 1;\n                        switch (source_row.charAt(at)) {\n                        case ':':\n                        case '=':\n                        case '!':\n                            at += 1;\n                            break;\n                        default:\n                            warn('expected_a_b', line, from + at,\n                                ':', source_row.charAt(at));\n                        }\n                    }\n                    break;\n                case '|':\n                    b = false;\n                    break;\n                case ')':\n                    if (depth === 0) {\n                        warn('unescaped_a', line, from + at, ')');\n                    } else {\n                        depth -= 1;\n                    }\n                    break;\n                case ' ':\n                    pos = 1;\n                    while (source_row.charAt(at) === ' ') {\n                        at += 1;\n                        pos += 1;\n                    }\n                    if (pos > 1) {\n                        warn('use_braces', line, from + at, pos);\n                    }\n                    break;\n                case '[':\n                    c = source_row.charAt(at);\n                    if (c === '^') {\n                        at += 1;\n                        if (!option.regexp) {\n                            warn('insecure_a', line, from + at, c);\n                        } else if (source_row.charAt(at) === ']') {\n                            stop('unescaped_a', line, from + at, '^');\n                        }\n                    }\n                    bit = false;\n                    if (c === ']') {\n                        warn('empty_class', line, from + at - 1);\n                        bit = true;\n                    }\nklass:              do {\n                        c = source_row.charAt(at);\n                        at += 1;\n                        switch (c) {\n                        case '[':\n                        case '^':\n                            warn('unescaped_a', line, from + at, c);\n                            bit = true;\n                            break;\n                        case '-':\n                            if (bit) {\n                                bit = false;\n                            } else {\n                                warn('unescaped_a', line, from + at, '-');\n                                bit = true;\n                            }\n                            break;\n                        case ']':\n                            if (!bit) {\n                                warn('unescaped_a', line, from + at - 1, '-');\n                            }\n                            break klass;\n                        case '\\\\':\n                            c = source_row.charAt(at);\n                            if (c < ' ') {\n                                warn('control_a', line, from + at, String(c));\n                            } else if (c === '<') {\n                                warn('unexpected_a', line, from + at, '\\\\');\n                            }\n                            at += 1;\n                            bit = true;\n                            break;\n                        case '/':\n                            warn('unescaped_a', line, from + at - 1, '/');\n                            bit = true;\n                            break;\n                        default:\n                            bit = true;\n                        }\n                    } while (c);\n                    break;\n                case '.':\n                    if (!option.regexp) {\n                        warn('insecure_a', line, from + at, c);\n                    }\n                    break;\n                case ']':\n                case '?':\n                case '{':\n                case '}':\n                case '+':\n                case '*':\n                    warn('unescaped_a', line, from + at, c);\n                    break;\n                }\n                if (b) {\n                    switch (source_row.charAt(at)) {\n                    case '?':\n                    case '+':\n                    case '*':\n                        at += 1;\n                        if (source_row.charAt(at) === '?') {\n                            at += 1;\n                        }\n                        break;\n                    case '{':\n                        at += 1;\n                        c = source_row.charAt(at);\n                        if (c < '0' || c > '9') {\n                            warn('expected_number_a', line,\n                                from + at, c);\n                        }\n                        at += 1;\n                        low = +c;\n                        for (;;) {\n                            c = source_row.charAt(at);\n                            if (c < '0' || c > '9') {\n                                break;\n                            }\n                            at += 1;\n                            low = +c + (low * 10);\n                        }\n                        high = low;\n                        if (c === ',') {\n                            at += 1;\n                            high = Infinity;\n                            c = source_row.charAt(at);\n                            if (c >= '0' && c <= '9') {\n                                at += 1;\n                                high = +c;\n                                for (;;) {\n                                    c = source_row.charAt(at);\n                                    if (c < '0' || c > '9') {\n                                        break;\n                                    }\n                                    at += 1;\n                                    high = +c + (high * 10);\n                                }\n                            }\n                        }\n                        if (source_row.charAt(at) !== '}') {\n                            warn('expected_a_b', line, from + at,\n                                '}', c);\n                        } else {\n                            at += 1;\n                        }\n                        if (source_row.charAt(at) === '?') {\n                            at += 1;\n                        }\n                        if (low > high) {\n                            warn('not_greater', line, from + at,\n                                low, high);\n                        }\n                        break;\n                    }\n                }\n            }\n            c = source_row.slice(0, at - 1);\n            character += at;\n            source_row = source_row.slice(at);\n            return it('(regexp)', c);\n        }\n\n// Public lex methods\n\n        return {\n            init: function (source) {\n                if (typeof source === 'string') {\n                    lines = source.split(crlfx);\n                } else {\n                    lines = source;\n                }\n                line = 0;\n                next_line();\n                from = 1;\n            },\n\n// token -- this is called by advance to get the next token.\n\n            token: function () {\n                var first, i, snippet;\n\n                for (;;) {\n                    while (!source_row) {\n                        if (!next_line()) {\n                            return it('(end)');\n                        }\n                    }\n                    snippet = match(tx);\n                    if (snippet) {\n\n//      identifier\n\n                        first = snippet.charAt(0);\n                        if (first.isAlpha() || first === '_' || first === '$') {\n                            return it('(identifier)', snippet);\n                        }\n\n//      number\n\n                        if (first.isDigit()) {\n                            return number(snippet);\n                        }\n                        switch (snippet) {\n\n//      string\n\n                        case '\"':\n                        case \"'\":\n                            return string(snippet);\n\n//      // comment\n\n                        case '//':\n                            comment(source_row, '//');\n                            source_row = '';\n                            break;\n\n//      /* comment\n\n                        case '/*':\n                            for (;;) {\n                                i = source_row.search(lx);\n                                if (i >= 0) {\n                                    break;\n                                }\n                                character = source_row.length;\n                                comment(source_row);\n                                from = 0;\n                                if (!next_line()) {\n                                    stop('unclosed_comment', line, character);\n                                }\n                            }\n                            comment(source_row.slice(0, i), '/*');\n                            character += i + 2;\n                            if (source_row.charAt(i) === '/') {\n                                stop('nested_comment', line, character);\n                            }\n                            source_row = source_row.slice(i + 2);\n                            break;\n\n                        case '':\n                            break;\n//      /\n                        case '/':\n                            if (token.id === '/=') {\n                                stop('slash_equal', line, from);\n                            }\n                            return prereg\n                                ? regexp()\n                                : it('(punctuator)', snippet);\n\n//      punctuator\n                        default:\n                            return it('(punctuator)', snippet);\n                        }\n                    }\n                }\n            }\n        };\n    }());\n\n    function define(kind, token) {\n\n// Define a name.\n\n        var name = token.string,\n            master = scope[name];       // The current definition of the name\n\n// vars are created with a deadzone, so that the expression that initializes\n// the var cannot access the var. Functions are not writeable.\n\n        token.dead = false;\n        token.init = false;\n        token.kind = kind;\n        token.master = master;\n        token.used = 0;\n        token.writeable = false;\n\n// Global variables are a little weird. They can be defined multiple times.\n// Some predefined global vars are (or should) not be writeable.\n\n        if (kind === 'var' && funct === global_funct) {\n            if (!master) {\n                if (predefined[name] === false) {\n                    token.writeable = false;\n                }\n                global_scope[name] = token;\n            }\n        } else {\n\n// It is an error if the name has already been defined in this scope, except\n// when reusing an exception variable name.\n\n            if (master) {\n                if (master.function === funct) {\n                    if (master.kind !== 'exception' || kind !== 'exception' ||\n                            !master.dead) {\n                        token.warn('already_defined', name);\n                    }\n                } else if (master.function !== global_funct) {\n                    if (kind === 'var') {\n                        token.warn('redefinition_a_b', name, master.line);\n                    }\n                }\n            }\n            scope[name] = token;\n            if (kind === 'var') {\n                block_var.push(name);\n            }\n        }\n    }\n\n    function peek(distance) {\n\n// Peek ahead to a future token. The distance is how far ahead to look. The\n// default is the next token.\n\n        var found, slot = 0;\n\n        distance = distance || 0;\n        while (slot <= distance) {\n            found = lookahead[slot];\n            if (!found) {\n                found = lookahead[slot] = lex.token();\n            }\n            slot += 1;\n        }\n        return found;\n    }\n\n\n    function advance(id, match) {\n\n// Produce the next token, also looking for programming errors.\n\n        if (indent) {\n\n// If indentation checking was requested, then inspect all of the line breakings.\n// The var statement is tricky because the names might be aligned or not. We\n// look at the first line break after the var to determine the programmer's\n// intention.\n\n            if (var_mode && next_token.line !== token.line) {\n                if ((var_mode !== indent || !next_token.edge) &&\n                        next_token.from === indent.at -\n                        (next_token.edge ? option.indent : 0)) {\n                    var dent = indent;\n                    for (;;) {\n                        dent.at -= option.indent;\n                        if (dent === var_mode) {\n                            break;\n                        }\n                        dent = dent.was;\n                    }\n                    dent.open = false;\n                }\n                var_mode = null;\n            }\n            if (next_token.id === '?' && indent.mode === ':' &&\n                    token.line !== next_token.line) {\n                indent.at -= option.indent;\n            }\n            if (indent.open) {\n\n// If the token is an edge.\n\n                if (next_token.edge) {\n                    if (next_token.edge === 'label') {\n                        expected_at(1);\n                    } else if (next_token.edge === 'case' || indent.mode === 'statement') {\n                        expected_at(indent.at - option.indent);\n                    } else if (indent.mode !== 'array' || next_token.line !== token.line) {\n                        expected_at(indent.at);\n                    }\n\n// If the token is not an edge, but is the first token on the line.\n\n                } else if (next_token.line !== token.line) {\n                    if (next_token.from < indent.at + (indent.mode ===\n                            'expression' ? 0 : option.indent)) {\n                        expected_at(indent.at + option.indent);\n                    }\n                    indent.wrap = true;\n                }\n            } else if (next_token.line !== token.line) {\n                if (next_token.edge) {\n                    expected_at(indent.at);\n                } else {\n                    indent.wrap = true;\n                    if (indent.mode === 'statement' || indent.mode === 'var') {\n                        expected_at(indent.at + option.indent);\n                    } else if (next_token.from < indent.at + (indent.mode ===\n                            'expression' ? 0 : option.indent)) {\n                        expected_at(indent.at + option.indent);\n                    }\n                }\n            }\n        }\n\n        switch (token.id) {\n        case '(number)':\n            if (next_token.id === '.') {\n                next_token.warn('trailing_decimal_a');\n            }\n            break;\n        case '-':\n            if (next_token.id === '-' || next_token.id === '--') {\n                next_token.warn('confusing_a');\n            }\n            break;\n        case '+':\n            if (next_token.id === '+' || next_token.id === '++') {\n                next_token.warn('confusing_a');\n            }\n            break;\n        }\n        if (token.id === '(string)' || token.identifier) {\n            anonname = token.string;\n        }\n\n        if (id && next_token.id !== id) {\n            if (match) {\n                next_token.warn('expected_a_b_from_c_d', id,\n                    match.id, match.line, artifact());\n            } else if (!next_token.identifier || next_token.string !== id) {\n                next_token.warn('expected_a_b', id, artifact());\n            }\n        }\n        prev_token = token;\n        token = next_token;\n        next_token = lookahead.shift() || lex.token();\n        next_token.function = funct;\n        tokens.push(next_token);\n    }\n\n\n    function do_globals() {\n        var name, writeable;\n        for (;;) {\n            if (next_token.id !== '(string)' && !next_token.identifier) {\n                return;\n            }\n            name = next_token.string;\n            advance();\n            writeable = false;\n            if (next_token.id === ':') {\n                advance(':');\n                switch (next_token.id) {\n                case 'true':\n                    writeable = predefined[name] !== false;\n                    advance('true');\n                    break;\n                case 'false':\n                    advance('false');\n                    break;\n                default:\n                    next_token.stop('unexpected_a');\n                }\n            }\n            predefined[name] = writeable;\n            if (next_token.id !== ',') {\n                return;\n            }\n            advance(',');\n        }\n    }\n\n\n    function do_jslint() {\n        var name, value;\n        while (next_token.id === '(string)' || next_token.identifier) {\n            name = next_token.string;\n            if (!allowed_option[name]) {\n                next_token.stop('unexpected_a');\n            }\n            advance();\n            if (next_token.id !== ':') {\n                next_token.stop('expected_a_b', ':', artifact());\n            }\n            advance(':');\n            if (typeof allowed_option[name] === 'number') {\n                value = next_token.number;\n                if (value > allowed_option[name] || value <= 0 ||\n                        Math.floor(value) !== value) {\n                    next_token.stop('expected_small_a');\n                }\n                option[name] = value;\n            } else {\n                if (next_token.id === 'true') {\n                    option[name] = true;\n                } else if (next_token.id === 'false') {\n                    option[name] = false;\n                } else {\n                    next_token.stop('unexpected_a');\n                }\n            }\n            advance();\n            if (next_token.id === ',') {\n                advance(',');\n            }\n        }\n        assume();\n    }\n\n\n    function do_properties() {\n        var name;\n        option.properties = true;\n        for (;;) {\n            if (next_token.id !== '(string)' && !next_token.identifier) {\n                return;\n            }\n            name = next_token.string;\n            advance();\n            if (next_token.id === ':') {\n                for (;;) {\n                    advance();\n                    if (next_token.id !== '(string)' && !next_token.identifier) {\n                        break;\n                    }\n                }\n            }\n            property[name] = 0;\n            if (next_token.id !== ',') {\n                return;\n            }\n            advance(',');\n        }\n    }\n\n\n    directive = function directive() {\n        var command = this.id,\n            old_comments_off = comments_off,\n            old_indent = indent;\n        comments_off = true;\n        indent = null;\n        if (next_token.line === token.line && next_token.from === token.thru) {\n            next_token.warn('missing_space_a_b', artifact(token), artifact());\n        }\n        if (lookahead.length > 0) {\n            this.warn('unexpected_a');\n        }\n        switch (command) {\n        case '/*properties':\n        case '/*property':\n        case '/*members':\n        case '/*member':\n            do_properties();\n            break;\n        case '/*jslint':\n            do_jslint();\n            break;\n        case '/*globals':\n        case '/*global':\n            do_globals();\n            break;\n        default:\n            this.stop('unexpected_a');\n        }\n        comments_off = old_comments_off;\n        advance('*/');\n        indent = old_indent;\n    };\n\n\n// Indentation intention\n\n    function edge(mode) {\n        next_token.edge = indent ? indent.open && (mode || 'edge') : '';\n    }\n\n\n    function step_in(mode) {\n        var open;\n        if (typeof mode === 'number') {\n            indent = {\n                at: +mode,\n                open: true,\n                was: indent\n            };\n        } else if (!indent) {\n            indent = {\n                at: 1,\n                mode: 'statement',\n                open: true\n            };\n        } else if (mode === 'statement') {\n            indent = {\n                at: indent.at,\n                open: true,\n                was: indent\n            };\n        } else {\n            open = mode === 'var' || next_token.line !== token.line;\n            indent = {\n                at: (open || mode === 'control'\n                    ? indent.at + option.indent\n                    : indent.at) + (indent.wrap ? option.indent : 0),\n                mode: mode,\n                open: open,\n                was: indent\n            };\n            if (mode === 'var' && open) {\n                var_mode = indent;\n            }\n        }\n    }\n\n    function step_out(id, symbol) {\n        if (id) {\n            if (indent && indent.open) {\n                indent.at -= option.indent;\n                edge();\n            }\n            advance(id, symbol);\n        }\n        if (indent) {\n            indent = indent.was;\n        }\n    }\n\n// Functions for conformance of whitespace.\n\n    function one_space(left, right) {\n        left = left || token;\n        right = right || next_token;\n        if (right.id !== '(end)' && !option.white &&\n                (token.line !== right.line ||\n                token.thru + 1 !== right.from)) {\n            right.warn('expected_space_a_b', artifact(token), artifact(right));\n        }\n    }\n\n    function one_space_only(left, right) {\n        left = left || token;\n        right = right || next_token;\n        if (right.id !== '(end)' && (left.line !== right.line ||\n                (!option.white && left.thru + 1 !== right.from))) {\n            right.warn('expected_space_a_b', artifact(left), artifact(right));\n        }\n    }\n\n    function no_space(left, right) {\n        left = left || token;\n        right = right || next_token;\n        if ((!option.white) &&\n                left.thru !== right.from && left.line === right.line) {\n            right.warn('unexpected_space_a_b', artifact(left), artifact(right));\n        }\n    }\n\n    function no_space_only(left, right) {\n        left = left || token;\n        right = right || next_token;\n        if (right.id !== '(end)' && (left.line !== right.line ||\n                (!option.white && left.thru !== right.from))) {\n            right.warn('unexpected_space_a_b', artifact(left), artifact(right));\n        }\n    }\n\n    function spaces(left, right) {\n        if (!option.white) {\n            left = left || token;\n            right = right || next_token;\n            if (left.thru === right.from && left.line === right.line) {\n                right.warn('missing_space_a_b', artifact(left), artifact(right));\n            }\n        }\n    }\n\n    function comma() {\n        if (next_token.id !== ',') {\n            warn('expected_a_b', token.line, token.thru, ',', artifact());\n        } else {\n            if (!option.white) {\n                no_space_only();\n            }\n            advance(',');\n            spaces();\n        }\n    }\n\n\n    function semicolon() {\n        if (next_token.id !== ';') {\n            warn('expected_a_b', token.line, token.thru, ';', artifact());\n        } else {\n            if (!option.white) {\n                no_space_only();\n            }\n            advance(';');\n            if (semicolon_coda[next_token.id] !== true) {\n                spaces();\n            }\n        }\n    }\n\n    function use_strict() {\n        if (next_token.string === 'use strict') {\n            if (strict_mode) {\n                next_token.warn('unnecessary_use');\n            }\n            edge();\n            advance();\n            semicolon();\n            strict_mode = true;\n            return true;\n        }\n        return false;\n    }\n\n\n    function are_similar(a, b) {\n        if (a === b) {\n            return true;\n        }\n        if (Array.isArray(a)) {\n            if (Array.isArray(b) && a.length === b.length) {\n                var i;\n                for (i = 0; i < a.length; i += 1) {\n                    if (!are_similar(a[i], b[i])) {\n                        return false;\n                    }\n                }\n                return true;\n            }\n            return false;\n        }\n        if (Array.isArray(b)) {\n            return false;\n        }\n        if (a.id === '(number)' && b.id === '(number)') {\n            return a.number === b.number;\n        }\n        if (a.arity === b.arity && a.string === b.string) {\n            switch (a.arity) {\n            case undefined:\n                return a.string === b.string;\n            case 'prefix':\n            case 'suffix':\n                return a.id === b.id && are_similar(a.first, b.first) &&\n                    a.id !== '{' && a.id !== '[';\n            case 'infix':\n                return are_similar(a.first, b.first) &&\n                    are_similar(a.second, b.second);\n            case 'ternary':\n                return are_similar(a.first, b.first) &&\n                    are_similar(a.second, b.second) &&\n                    are_similar(a.third, b.third);\n            case 'function':\n            case 'regexp':\n                return false;\n            default:\n                return true;\n            }\n        }\n        if (a.id === '.' && b.id === '[' && b.arity === 'infix') {\n            return a.second.string === b.second.string && b.second.id === '(string)';\n        }\n        if (a.id === '[' && a.arity === 'infix' && b.id === '.') {\n            return a.second.string === b.second.string && a.second.id === '(string)';\n        }\n        return false;\n    }\n\n\n// This is the heart of JSLINT, the Pratt parser. In addition to parsing, it\n// is looking for ad hoc lint patterns. We add .fud to Pratt's model, which is\n// like .nud except that it is only used on the first token of a statement.\n// Having .fud makes it much easier to define statement-oriented languages like\n// JavaScript. I retained Pratt's nomenclature.\n\n// .nud     Null denotation\n// .fud     First null denotation\n// .led     Left denotation\n//  lbp     Left binding power\n//  rbp     Right binding power\n\n// They are elements of the parsing method called Top Down Operator Precedence.\n\n    function expression(rbp, initial) {\n\n// rbp is the right binding power.\n// initial indicates that this is the first expression of a statement.\n\n        var left;\n        if (next_token.id === '(end)') {\n            token.stop('unexpected_a', next_token.id);\n        }\n        advance();\n        if (initial) {\n            anonname = 'anonymous';\n        }\n        if (initial === true && token.fud) {\n            left = token.fud();\n        } else {\n            if (token.nud) {\n                left = token.nud();\n            } else {\n                if (next_token.id === '(number)' && token.id === '.') {\n                    token.warn('leading_decimal_a', artifact());\n                    advance();\n                    return token;\n                }\n                token.stop('expected_identifier_a', artifact(token));\n            }\n            while (rbp < next_token.lbp) {\n                advance();\n                left = token.led(left);\n            }\n        }\n        if (left && left.assign && !initial) {\n            if (!option.ass) {\n                left.warn('assignment_expression');\n            }\n            if (left.id !== '=' && left.first.master) {\n                left.first.master.used = true;\n            }\n        }\n        return left;\n    }\n\n    protosymbol = {\n        nud: function () {\n            this.stop('unexpected_a');\n        },\n        led: function () {\n            this.stop('expected_operator_a');\n        },\n        warn: function (code, a, b, c, d) {\n            if (!this.warning) {\n                this.warning = warn(code, this.line || 0, this.from || 0,\n                    a || artifact(this), b, c, d);\n            }\n        },\n        stop: function (code, a, b, c, d) {\n            this.warning = undefined;\n            this.warn(code, a, b, c, d);\n            return quit('stopping', this.line, this.character);\n        },\n        lbp: 0\n    };\n\n// Functional constructors for making the symbols that will be inherited by\n// tokens.\n\n    function symbol(s, bp) {\n        var x = syntax[s];\n        if (!x) {\n            x = Object.create(protosymbol);\n            x.id = x.string = s;\n            x.lbp = bp || 0;\n            syntax[s] = x;\n        }\n        return x;\n    }\n\n    function postscript(x) {\n        x.postscript = true;\n        return x;\n    }\n\n    function ultimate(s) {\n        var x = symbol(s, 0);\n        x.from = 1;\n        x.thru = 1;\n        x.line = 0;\n        x.edge = 'edge';\n        x.string = s;\n        return postscript(x);\n    }\n\n    function reserve_name(x) {\n        var c = x.id.charAt(0);\n        if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {\n            x.identifier = x.reserved = true;\n        }\n        return x;\n    }\n\n    function stmt(s, f) {\n        var x = symbol(s);\n        x.fud = f;\n        return reserve_name(x);\n    }\n\n    function disrupt_stmt(s, f) {\n        var x = stmt(s, f);\n        x.disrupt = true;\n    }\n\n    function labeled_stmt(s, f) {\n        var x = stmt(s, f);\n        x.labeled = true;\n    }\n\n    function prefix(s, f) {\n        var x = symbol(s, 150);\n        reserve_name(x);\n        x.nud = function () {\n            var that = this;\n            that.arity = 'prefix';\n            if (typeof f === 'function') {\n                that = f(that);\n                if (that.arity !== 'prefix') {\n                    return that;\n                }\n            } else {\n                if (s === 'typeof') {\n                    one_space();\n                } else {\n                    no_space_only();\n                }\n                that.first = expression(150);\n            }\n            switch (that.id) {\n            case '++':\n            case '--':\n                if (!option.plusplus) {\n                    that.warn('unexpected_a');\n                } else if ((!that.first.identifier || that.first.reserved) &&\n                        that.first.id !== '.' && that.first.id !== '[') {\n                    that.warn('bad_operand');\n                }\n                break;\n            default:\n                if (that.first.arity === 'prefix' ||\n                        that.first.arity === 'function') {\n                    that.warn('unexpected_a');\n                }\n            }\n            return that;\n        };\n        return x;\n    }\n\n\n    function type(s, t, nud) {\n        var x = symbol(s);\n        x.arity = t;\n        if (nud) {\n            x.nud = nud;\n        }\n        return x;\n    }\n\n\n    function reserve(s, f) {\n        var x = symbol(s);\n        x.identifier = x.reserved = true;\n        if (typeof f === 'function') {\n            x.nud = f;\n        }\n        return x;\n    }\n\n\n    function constant(name) {\n        var x = reserve(name);\n        x.string = name;\n        x.nud = return_this;\n        return x;\n    }\n\n\n    function reservevar(s, v) {\n        return reserve(s, function () {\n            if (typeof v === 'function') {\n                v(this);\n            }\n            return this;\n        });\n    }\n\n\n    function infix(s, p, f, w) {\n        var x = symbol(s, p);\n        reserve_name(x);\n        x.led = function (left) {\n            this.arity = 'infix';\n            if (!w) {\n                spaces(prev_token, token);\n                spaces();\n            }\n            if (!option.bitwise && this.bitwise) {\n                this.warn('unexpected_a');\n            }\n            if (typeof f === 'function') {\n                return f(left, this);\n            }\n            this.first = left;\n            this.second = expression(p);\n            return this;\n        };\n        return x;\n    }\n\n    function expected_relation(node, message) {\n        if (node.assign) {\n            node.warn(message || 'conditional_assignment');\n        }\n        return node;\n    }\n\n    function expected_condition(node, message) {\n        switch (node.id) {\n        case '[':\n        case '-':\n            if (node.arity !== 'infix') {\n                node.warn(message || 'weird_condition');\n            }\n            break;\n        case 'false':\n        case 'function':\n        case 'Infinity':\n        case 'NaN':\n        case 'null':\n        case 'true':\n        case 'undefined':\n        case 'void':\n        case '(number)':\n        case '(regexp)':\n        case '(string)':\n        case '{':\n        case '?':\n        case '~':\n            node.warn(message || 'weird_condition');\n            break;\n        case '(':\n            if (node.first.id === 'new' ||\n                    (node.first.string === 'Boolean') ||\n                    (node.first.id === '.' &&\n                        numbery[node.first.second.string] === true)) {\n                node.warn(message || 'weird_condition');\n            }\n            break;\n        }\n        return node;\n    }\n\n    function check_relation(node) {\n        switch (node.arity) {\n        case 'prefix':\n            switch (node.id) {\n            case '{':\n            case '[':\n                node.warn('unexpected_a');\n                break;\n            case '!':\n                node.warn('confusing_a');\n                break;\n            }\n            break;\n        case 'function':\n        case 'regexp':\n            node.warn('unexpected_a');\n            break;\n        default:\n            if (node.id  === 'NaN') {\n                node.warn('isNaN');\n            } else if (node.relation) {\n                node.warn('weird_relation');\n            }\n        }\n        return node;\n    }\n\n\n    function relation(s, eqeq) {\n        var x = infix(s, 100, function (left, that) {\n            check_relation(left);\n            if (eqeq && !option.eqeq) {\n                that.warn('expected_a_b', eqeq, that.id);\n            }\n            var right = expression(100);\n            if (are_similar(left, right) ||\n                    ((left.id === '(string)' || left.id === '(number)') &&\n                    (right.id === '(string)' || right.id === '(number)'))) {\n                that.warn('weird_relation');\n            } else if (left.id === 'typeof') {\n                if (right.id !== '(string)') {\n                    right.warn(\"expected_string_a\", artifact(right));\n                } else if (right.string === 'undefined' ||\n                        right.string === 'null') {\n                    left.warn(\"unexpected_typeof_a\", right.string);\n                }\n            } else if (right.id === 'typeof') {\n                if (left.id !== '(string)') {\n                    left.warn(\"expected_string_a\", artifact(left));\n                } else if (left.string === 'undefined' ||\n                        left.string === 'null') {\n                    right.warn(\"unexpected_typeof_a\", left.string);\n                }\n            }\n            that.first = left;\n            that.second = check_relation(right);\n            return that;\n        });\n        x.relation = true;\n        return x;\n    }\n\n    function lvalue(that, s) {\n        var master;\n        if (that.identifier) {\n            master = scope[that.string];\n            if (master) {\n                if (scope[that.string].writeable !== true) {\n                    that.warn('read_only');\n                }\n                master.used -= 1;\n                if (s === '=') {\n                    master.init = true;\n                }\n            }\n        } else if (that.id === '.' || that.id === '[') {\n            if (!that.first || that.first.string === 'arguments') {\n                that.warn('bad_assignment');\n            }\n        } else {\n            that.warn('bad_assignment');\n        }\n    }\n\n\n    function assignop(s, op) {\n        var x = infix(s, 20, function (left, that) {\n            var next;\n            that.first = left;\n            lvalue(left, s);\n            that.second = expression(20);\n            if (that.id === '=' && are_similar(that.first, that.second)) {\n                that.warn('weird_assignment');\n            }\n            next = that;\n            while (next_token.id === '=') {\n                lvalue(next.second, '=');\n                next_token.first = next.second;\n                next.second = next_token;\n                next = next_token;\n                advance('=');\n                next.second = expression(20);\n            }\n            return that;\n        });\n        x.assign = true;\n        if (op) {\n            if (syntax[op].bitwise) {\n                x.bitwise = true;\n            }\n        }\n        return x;\n    }\n\n\n    function bitwise(s, p) {\n        var x = infix(s, p, 'number');\n        x.bitwise = true;\n        return x;\n    }\n\n\n    function suffix(s) {\n        var x = symbol(s, 150);\n        x.led = function (left) {\n            no_space_only(prev_token, token);\n            if (!option.plusplus) {\n                this.warn('unexpected_a');\n            } else if ((!left.identifier || left.reserved) &&\n                    left.id !== '.' && left.id !== '[') {\n                this.warn('bad_operand');\n            }\n            this.first = left;\n            this.arity = 'suffix';\n            return this;\n        };\n        return x;\n    }\n\n\n    function optional_identifier(variable) {\n        if (next_token.identifier) {\n            advance();\n            if (token.reserved && (!option.es5 || variable)) {\n                token.warn('expected_identifier_a_reserved');\n            }\n            return token.string;\n        }\n    }\n\n\n    function identifier(variable) {\n        var i = optional_identifier(variable);\n        if (!i) {\n            next_token.stop(token.id === 'function' && next_token.id === '('\n                ? 'name_function'\n                : 'expected_identifier_a');\n        }\n        return i;\n    }\n\n\n    function statement() {\n\n        var label, preamble, the_statement;\n\n// We don't like the empty statement.\n\n        if (next_token.id === ';') {\n            next_token.warn('unexpected_a');\n            semicolon();\n            return;\n        }\n\n// Is this a labeled statement?\n\n        if (next_token.identifier && !next_token.reserved && peek().id === ':') {\n            edge('label');\n            label = next_token;\n            advance();\n            advance(':');\n            define('label', label);\n            if (next_token.labeled !== true || funct === global_funct) {\n                label.stop('unexpected_label_a');\n            } else if (jx.test(label.string + ':')) {\n                label.warn('url');\n            }\n            next_token.label = label;\n            label.init = true;\n        }\n\n// Parse the statement.\n\n        preamble = next_token;\n        if (token.id !== 'else') {\n            edge();\n        }\n        step_in('statement');\n        the_statement = expression(0, true);\n        if (the_statement) {\n\n// Look for the final semicolon.\n\n            if (the_statement.arity === 'statement') {\n                if (the_statement.id === 'switch' ||\n                        (the_statement.block && the_statement.id !== 'do')) {\n                    spaces();\n                } else {\n                    semicolon();\n                }\n            } else {\n\n// If this is an expression statement, determine if it is acceptable.\n// We do not like\n//      new Blah;\n// statements. If it is to be used at all, new should only be used to make\n// objects, not side effects. The expression statements we do like do\n// assignment or invocation or delete.\n\n                if (the_statement.id === '(') {\n                    if (the_statement.first.id === 'new') {\n                        next_token.warn('bad_new');\n                    }\n                } else if (the_statement.id === '++' ||\n                        the_statement.id === '--') {\n                    lvalue(the_statement.first);\n                } else if (!the_statement.assign &&\n                        the_statement.id !== 'delete') {\n                    if (!option.closure || !preamble.comments) {\n                        preamble.warn('assignment_function_expression');\n                    }\n                }\n                semicolon();\n            }\n        }\n        step_out();\n        if (label) {\n            label.dead = true;\n        }\n        return the_statement;\n    }\n\n\n    function statements() {\n        var array = [], disruptor, the_statement;\n\n// A disrupt statement may not be followed by any other statement.\n// If the last statement is disrupt, then the sequence is disrupt.\n\n        while (next_token.postscript !== true) {\n            if (next_token.id === ';') {\n                next_token.warn('unexpected_a');\n                semicolon();\n            } else {\n                if (next_token.string === 'use strict') {\n                    if ((!node_js) || funct !== global_funct || array.length > 0) {\n                        next_token.warn('function_strict');\n                    }\n                    use_strict();\n                }\n                if (disruptor) {\n                    next_token.warn('unreachable_a_b', next_token.string,\n                        disruptor.string);\n                    disruptor = null;\n                }\n                the_statement = statement();\n                if (the_statement) {\n                    array.push(the_statement);\n                    if (the_statement.disrupt) {\n                        disruptor = the_statement;\n                        array.disrupt = true;\n                    }\n                }\n            }\n        }\n        return array;\n    }\n\n\n    function block(kind) {\n\n// A block is a sequence of statements wrapped in braces.\n\n        var array,\n            curly = next_token,\n            old_block_var = block_var,\n            old_in_block = in_block,\n            old_strict_mode = strict_mode;\n\n        in_block = kind !== 'function' && kind !== 'try' && kind !== 'catch';\n        block_var = [];\n        if (curly.id === '{') {\n            spaces();\n            advance('{');\n            step_in();\n            if (kind === 'function' && !use_strict() && !old_strict_mode &&\n                    !option.sloppy && funct.level === 1) {\n                next_token.warn('missing_use_strict');\n            }\n            array = statements();\n            strict_mode = old_strict_mode;\n            step_out('}', curly);\n        } else if (in_block) {\n            curly.stop('expected_a_b', '{', artifact());\n        } else {\n            curly.warn('expected_a_b', '{', artifact());\n            array = [statement()];\n            array.disrupt = array[0].disrupt;\n        }\n        if (kind !== 'catch' && array.length === 0) {\n            curly.warn('empty_block');\n        }\n        block_var.forEach(function (name) {\n            scope[name].dead = true;\n        });\n        block_var = old_block_var;\n        in_block = old_in_block;\n        return array;\n    }\n\n\n    function tally_property(name) {\n        if (option.properties && typeof property[name] !== 'number') {\n            token.warn('unexpected_property_a', name);\n        }\n        if (property[name]) {\n            property[name] += 1;\n        } else {\n            property[name] = 1;\n        }\n    }\n\n\n// ECMAScript parser\n\n    (function () {\n        var x = symbol('(identifier)');\n        x.nud = function () {\n            var name = this.string,\n                master = scope[name],\n                writeable;\n\n// If the master is not in scope, then we may have an undeclared variable.\n// Check the predefined list. If it was predefined, create the global\n// variable.\n\n            if (!master) {\n                writeable = predefined[name];\n                if (typeof writeable === 'boolean') {\n                    global_scope[name] = master = {\n                        dead: false,\n                        function: global_funct,\n                        kind: 'var',\n                        string: name,\n                        writeable: writeable\n                    };\n\n// But if the variable is not in scope, and is not predefined, and if we are not\n// in the global scope, then we have an undefined variable error.\n\n                } else {\n                    token.warn('used_before_a');\n                }\n            } else {\n                this.master = master;\n            }\n\n// Annotate uses that cross scope boundaries.\n\n            if (master) {\n                if (master.kind === 'label') {\n                    this.warn('a_label');\n                } else {\n                    if (master.dead === true || master.dead === funct) {\n                        this.warn('a_scope');\n                    }\n                    master.used += 1;\n                    if (master.function !== funct) {\n                        if (master.function === global_funct) {\n                            funct.global.push(name);\n                        } else {\n                            master.function.closure.push(name);\n                            funct.outer.push(name);\n                        }\n                    }\n                }\n            }\n            return this;\n        };\n        x.identifier = true;\n    }());\n\n\n// Build the syntax table by declaring the syntactic elements.\n\n    type('(array)', 'array');\n    type('(function)', 'function');\n    type('(number)', 'number', return_this);\n    type('(object)', 'object');\n    type('(string)', 'string', return_this);\n    type('(boolean)', 'boolean', return_this);\n    type('(regexp)', 'regexp', return_this);\n\n    ultimate('(begin)');\n    ultimate('(end)');\n    ultimate('(error)');\n    postscript(symbol('}'));\n    symbol(')');\n    symbol(']');\n    postscript(symbol('\"'));\n    postscript(symbol('\\''));\n    symbol(';');\n    symbol(':');\n    symbol(',');\n    symbol('#');\n    symbol('@');\n    symbol('*/');\n    postscript(reserve('case'));\n    reserve('catch');\n    postscript(reserve('default'));\n    reserve('else');\n    reserve('finally');\n\n    reservevar('arguments', function (x) {\n        if (strict_mode && funct === global_funct) {\n            x.warn('strict');\n        }\n        funct.arguments = true;\n    });\n    reservevar('eval');\n    constant('false', 'boolean');\n    constant('Infinity', 'number');\n    constant('NaN', 'number');\n    constant('null', '');\n    reservevar('this', function (x) {\n        if (strict_mode && funct.statement && funct.name.charAt(0) > 'Z') {\n            x.warn('strict');\n        }\n    });\n    constant('true', 'boolean');\n    constant('undefined', '');\n\n    infix('?', 30, function (left, that) {\n        step_in('?');\n        that.first = expected_condition(expected_relation(left));\n        that.second = expression(0);\n        spaces();\n        step_out();\n        var colon = next_token;\n        advance(':');\n        step_in(':');\n        spaces();\n        that.third = expression(10);\n        that.arity = 'ternary';\n        if (are_similar(that.second, that.third)) {\n            colon.warn('weird_ternary');\n        } else if (are_similar(that.first, that.second)) {\n            that.warn('use_or');\n        }\n        step_out();\n        return that;\n    });\n\n    infix('||', 40, function (left, that) {\n        function paren_check(that) {\n            if (that.id === '&&' && !that.paren) {\n                that.warn('and');\n            }\n            return that;\n        }\n\n        that.first = paren_check(expected_condition(expected_relation(left)));\n        that.second = paren_check(expected_relation(expression(40)));\n        if (are_similar(that.first, that.second)) {\n            that.warn('weird_condition');\n        }\n        return that;\n    });\n\n    infix('&&', 50, function (left, that) {\n        that.first = expected_condition(expected_relation(left));\n        that.second = expected_relation(expression(50));\n        if (are_similar(that.first, that.second)) {\n            that.warn('weird_condition');\n        }\n        return that;\n    });\n\n    prefix('void', function (that) {\n        that.first = expression(0);\n        if (option.es5 || strict_mode) {\n            that.warn('expected_a_b', 'undefined', 'void');\n        } else if (that.first.number !== 0) {\n            that.first.warn('expected_a_b', '0', artifact(that.first));\n        }\n        return that;\n    });\n\n    bitwise('|', 70);\n    bitwise('^', 80);\n    bitwise('&', 90);\n\n    relation('==', '===');\n    relation('===');\n    relation('!=', '!==');\n    relation('!==');\n    relation('<');\n    relation('>');\n    relation('<=');\n    relation('>=');\n\n    bitwise('<<', 120);\n    bitwise('>>', 120);\n    bitwise('>>>', 120);\n\n    infix('in', 120, function (left, that) {\n        that.warn('infix_in');\n        that.left = left;\n        that.right = expression(130);\n        return that;\n    });\n    infix('instanceof', 120);\n    infix('+', 130, function (left, that) {\n        if (left.id === '(number)') {\n            if (left.number === 0) {\n                left.warn('unexpected_a', '0');\n            }\n        } else if (left.id === '(string)') {\n            if (left.string === '') {\n                left.warn('expected_a_b', 'String', '\\'\\'');\n            }\n        }\n        var right = expression(130);\n        if (right.id === '(number)') {\n            if (right.number === 0) {\n                right.warn('unexpected_a', '0');\n            }\n        } else if (right.id === '(string)') {\n            if (right.string === '') {\n                right.warn('expected_a_b', 'String', '\\'\\'');\n            }\n        }\n        if (left.id === right.id) {\n            if (left.id === '(string)' || left.id === '(number)') {\n                if (left.id === '(string)') {\n                    left.string += right.string;\n                    if (jx.test(left.string)) {\n                        left.warn('url');\n                    }\n                } else {\n                    left.number += right.number;\n                }\n                left.thru = right.thru;\n                return left;\n            }\n        }\n        that.first = left;\n        that.second = right;\n        return that;\n    });\n    prefix('+');\n    prefix('+++', function () {\n        token.warn('confusing_a');\n        this.first = expression(150);\n        this.arity = 'prefix';\n        return this;\n    });\n    infix('+++', 130, function (left) {\n        token.warn('confusing_a');\n        this.first = left;\n        this.second = expression(130);\n        return this;\n    });\n    infix('-', 130, function (left, that) {\n        if ((left.id === '(number)' && left.number === 0) || left.id === '(string)') {\n            left.warn('unexpected_a');\n        }\n        var right = expression(130);\n        if ((right.id === '(number)' && right.number === 0) || right.id === '(string)') {\n            right.warn('unexpected_a');\n        }\n        if (left.id === right.id && left.id === '(number)') {\n            left.number -= right.number;\n            left.thru = right.thru;\n            return left;\n        }\n        that.first = left;\n        that.second = right;\n        return that;\n    });\n    prefix('-');\n    prefix('---', function () {\n        token.warn('confusing_a');\n        this.first = expression(150);\n        this.arity = 'prefix';\n        return this;\n    });\n    infix('---', 130, function (left) {\n        token.warn('confusing_a');\n        this.first = left;\n        this.second = expression(130);\n        return this;\n    });\n    infix('*', 140, function (left, that) {\n        if ((left.id === '(number)' && (left.number === 0 || left.number === 1)) || left.id === '(string)') {\n            left.warn('unexpected_a');\n        }\n        var right = expression(140);\n        if ((right.id === '(number)' && (right.number === 0 || right.number === 1)) || right.id === '(string)') {\n            right.warn('unexpected_a');\n        }\n        if (left.id === right.id && left.id === '(number)') {\n            left.number *= right.number;\n            left.thru = right.thru;\n            return left;\n        }\n        that.first = left;\n        that.second = right;\n        return that;\n    });\n    infix('/', 140, function (left, that) {\n        if ((left.id === '(number)' && left.number === 0) || left.id === '(string)') {\n            left.warn('unexpected_a');\n        }\n        var right = expression(140);\n        if ((right.id === '(number)' && (right.number === 0 || right.number === 1)) || right.id === '(string)') {\n            right.warn('unexpected_a');\n        }\n        if (left.id === right.id && left.id === '(number)') {\n            left.number /= right.number;\n            left.thru = right.thru;\n            return left;\n        }\n        that.first = left;\n        that.second = right;\n        return that;\n    });\n    infix('%', 140, function (left, that) {\n        if ((left.id === '(number)' && (left.number === 0 || left.number === 1)) || left.id === '(string)') {\n            left.warn('unexpected_a');\n        }\n        var right = expression(140);\n        if ((right.id === '(number)' && right.number === 0) || right.id === '(string)') {\n            right.warn('unexpected_a');\n        }\n        if (left.id === right.id && left.id === '(number)') {\n            left.number %= right.number;\n            left.thru = right.thru;\n            return left;\n        }\n        that.first = left;\n        that.second = right;\n        return that;\n    });\n\n    suffix('++');\n    prefix('++');\n\n    suffix('--');\n    prefix('--');\n    prefix('delete', function (that) {\n        one_space();\n        var p = expression(0);\n        if (!p || (p.id !== '.' && p.id !== '[')) {\n            next_token.warn('deleted');\n        }\n        that.first = p;\n        return that;\n    });\n\n\n    prefix('~', function (that) {\n        no_space_only();\n        if (!option.bitwise) {\n            that.warn('unexpected_a');\n        }\n        that.first = expression(150);\n        return that;\n    });\n    function banger(that) {\n        no_space_only();\n        that.first = expected_condition(expression(150));\n        if (bang[that.first.id] === that || that.first.assign) {\n            that.warn('confusing_a');\n        }\n        return that;\n    }\n    prefix('!', banger);\n    prefix('!!', banger);\n    prefix('typeof');\n    prefix('new', function (that) {\n        one_space();\n        var c = expression(160), n, p, v;\n        that.first = c;\n        if (c.id !== 'function') {\n            if (c.identifier) {\n                switch (c.string) {\n                case 'Object':\n                    token.warn('use_object');\n                    break;\n                case 'Array':\n                    if (next_token.id === '(') {\n                        p = next_token;\n                        p.first = this;\n                        advance('(');\n                        if (next_token.id !== ')') {\n                            n = expression(0);\n                            p.second = [n];\n                            if (n.id !== '(number)' || next_token.id === ',') {\n                                p.warn('use_array');\n                            }\n                            while (next_token.id === ',') {\n                                advance(',');\n                                p.second.push(expression(0));\n                            }\n                        } else {\n                            token.warn('use_array');\n                        }\n                        advance(')', p);\n                        return p;\n                    }\n                    token.warn('use_array');\n                    break;\n                case 'Number':\n                case 'String':\n                case 'Boolean':\n                case 'Math':\n                case 'JSON':\n                    c.warn('not_a_constructor');\n                    break;\n                case 'Function':\n                    if (!option.evil) {\n                        next_token.warn('function_eval');\n                    }\n                    break;\n                case 'Date':\n                case 'RegExp':\n                case 'this':\n                    break;\n                default:\n                    if (c.id !== 'function') {\n                        v = c.string.charAt(0);\n                        if (!option.newcap && (v < 'A' || v > 'Z')) {\n                            token.warn('constructor_name_a');\n                        }\n                    }\n                }\n            } else {\n                if (c.id !== '.' && c.id !== '[' && c.id !== '(') {\n                    token.warn('bad_constructor');\n                }\n            }\n        } else {\n            that.warn('weird_new');\n        }\n        if (next_token.id !== '(') {\n            next_token.warn('missing_a', '()');\n        }\n        return that;\n    });\n\n    infix('(', 160, function (left, that) {\n        var e, p;\n        if (indent && indent.mode === 'expression') {\n            no_space(prev_token, token);\n        } else {\n            no_space_only(prev_token, token);\n        }\n        if (!left.immed && left.id === 'function') {\n            next_token.warn('wrap_immediate');\n        }\n        p = [];\n        if (left.identifier) {\n            if (left.string.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) {\n                if (left.string !== 'Number' && left.string !== 'String' &&\n                        left.string !== 'Boolean' && left.string !== 'Date') {\n                    if (left.string === 'Math') {\n                        left.warn('not_a_function');\n                    } else if (left.string === 'Object') {\n                        token.warn('use_object');\n                    } else if (left.string === 'Array' || !option.newcap) {\n                        left.warn('missing_a', 'new');\n                    }\n                }\n            } else if (left.string === 'JSON') {\n                left.warn('not_a_function');\n            }\n        } else if (left.id === '.') {\n            if (left.second.string === 'split' &&\n                    left.first.id === '(string)') {\n                left.second.warn('use_array');\n            }\n        }\n        step_in();\n        if (next_token.id !== ')') {\n            no_space();\n            for (;;) {\n                edge();\n                e = expression(10);\n                if (left.string === 'Boolean' && (e.id === '!' || e.id === '~')) {\n                    e.warn('weird_condition');\n                }\n                p.push(e);\n                if (next_token.id !== ',') {\n                    break;\n                }\n                comma();\n            }\n        }\n        no_space();\n        step_out(')', that);\n        if (typeof left === 'object') {\n            if (left.string === 'parseInt' && p.length === 1) {\n                left.warn('radix');\n            } else if (left.string === 'String' && p.length >= 1 && p[0].id === '(string)') {\n                left.warn('unexpected_a');\n            }\n            if (!option.evil) {\n                if (left.string === 'eval' || left.string === 'Function' ||\n                        left.string === 'execScript') {\n                    left.warn('evil');\n                } else if (p[0] && p[0].id === '(string)' &&\n                        (left.string === 'setTimeout' ||\n                        left.string === 'setInterval')) {\n                    left.warn('implied_evil');\n                }\n            }\n            if (!left.identifier && left.id !== '.' && left.id !== '[' &&\n                    left.id !== '(' && left.id !== '&&' && left.id !== '||' &&\n                    left.id !== '?') {\n                left.warn('bad_invocation');\n            }\n            if (left.id === '.') {\n                if (p.length > 0 &&\n                        left.first && left.first.first &&\n                        are_similar(p[0], left.first.first)) {\n                    if (left.second.string === 'call' ||\n                            (left.second.string === 'apply' && (p.length === 1 ||\n                            (p[1].arity === 'prefix' && p[1].id === '[')))) {\n                        left.second.warn('unexpected_a');\n                    }\n                }\n                if (left.second.string === 'toString') {\n                    if (left.first.id === '(string)' || left.first.id === '(number)') {\n                        left.second.warn('unexpected_a');\n                    }\n                }\n            }\n        }\n        that.first = left;\n        that.second = p;\n        return that;\n    }, true);\n\n    prefix('(', function (that) {\n        step_in('expression');\n        no_space();\n        edge();\n        if (next_token.id === 'function') {\n            next_token.immed = true;\n        }\n        var value = expression(0);\n        value.paren = true;\n        no_space();\n        step_out(')', that);\n        if (value.id === 'function') {\n            switch (next_token.id) {\n            case '(':\n                next_token.warn('move_invocation');\n                break;\n            case '.':\n            case '[':\n                next_token.warn('unexpected_a');\n                break;\n            default:\n                that.warn('bad_wrap');\n            }\n        } else if (!value.arity) {\n            if (!option.closure || !that.comments) {\n                that.warn('unexpected_a');\n            }\n        }\n        return value;\n    });\n\n    infix('.', 170, function (left, that) {\n        no_space(prev_token, token);\n        no_space();\n        var name = identifier();\n        if (typeof name === 'string') {\n            tally_property(name);\n        }\n        that.first = left;\n        that.second = token;\n        if (left && left.string === 'arguments' &&\n                (name === 'callee' || name === 'caller')) {\n            left.warn('avoid_a', 'arguments.' + name);\n        } else if (!option.evil && left && left.string === 'document' &&\n                (name === 'write' || name === 'writeln')) {\n            left.warn('write_is_wrong');\n        } else if (!option.stupid && syx.test(name)) {\n            token.warn('sync_a');\n        }\n        if (!option.evil && (name === 'eval' || name === 'execScript')) {\n            next_token.warn('evil');\n        }\n        return that;\n    }, true);\n\n    infix('[', 170, function (left, that) {\n        var e, s;\n        no_space_only(prev_token, token);\n        no_space();\n        step_in();\n        edge();\n        e = expression(0);\n        switch (e.id) {\n        case '(number)':\n            if (e.id === '(number)' && left.id === 'arguments') {\n                left.warn('use_param');\n            }\n            break;\n        case '(string)':\n            if (!option.evil &&\n                    (e.string === 'eval' || e.string === 'execScript')) {\n                e.warn('evil');\n            } else if (!option.sub && ix.test(e.string)) {\n                s = syntax[e.string];\n                if (!s || !s.reserved) {\n                    e.warn('subscript');\n                }\n            }\n            tally_property(e.string);\n            break;\n        }\n        step_out(']', that);\n        no_space(prev_token, token);\n        that.first = left;\n        that.second = e;\n        return that;\n    }, true);\n\n    prefix('[', function (that) {\n        that.first = [];\n        step_in('array');\n        while (next_token.id !== '(end)') {\n            while (next_token.id === ',') {\n                next_token.warn('unexpected_a');\n                advance(',');\n            }\n            if (next_token.id === ']') {\n                break;\n            }\n            indent.wrap = false;\n            edge();\n            that.first.push(expression(10));\n            if (next_token.id === ',') {\n                comma();\n                if (next_token.id === ']' && !option.es5) {\n                    token.warn('unexpected_a');\n                    break;\n                }\n            } else {\n                break;\n            }\n        }\n        step_out(']', that);\n        return that;\n    }, 170);\n\n\n    function property_name() {\n        var id = optional_identifier();\n        if (!id) {\n            if (next_token.id === '(string)') {\n                id = next_token.string;\n                advance();\n            } else if (next_token.id === '(number)') {\n                id = next_token.number.toString();\n                advance();\n            }\n        }\n        return id;\n    }\n\n\n\n    assignop('=');\n    assignop('+=', '+');\n    assignop('-=', '-');\n    assignop('*=', '*');\n    assignop('/=', '/').nud = function () {\n        next_token.stop('slash_equal');\n    };\n    assignop('%=', '%');\n    assignop('&=', '&');\n    assignop('|=', '|');\n    assignop('^=', '^');\n    assignop('<<=', '<<');\n    assignop('>>=', '>>');\n    assignop('>>>=', '>>>');\n\n    function function_parameters() {\n        var id, parameters = [], paren = next_token;\n        advance('(');\n        token.function = funct;\n        step_in();\n        no_space();\n        if (next_token.id !== ')') {\n            for (;;) {\n                edge();\n                id = identifier();\n                define('parameter', token);\n                parameters.push(id);\n                token.init = true;\n                token.writeable = true;\n                if (next_token.id !== ',') {\n                    break;\n                }\n                comma();\n            }\n        }\n        no_space();\n        step_out(')', paren);\n        return parameters;\n    }\n\n    function do_function(func, name) {\n        var old_funct = funct,\n            old_option = option,\n            old_scope = scope;\n        scope = Object.create(old_scope);\n        funct = {\n            closure: [],\n            global: [],\n            level: old_funct.level + 1,\n            line: next_token.line,\n            loopage: 0,\n            name: name || '\\'' + (anonname || '').replace(nx, sanitize) + '\\'',\n            outer: [],\n            scope: scope\n        };\n        funct.parameter = function_parameters();\n        func.function = funct;\n        option = Object.create(old_option);\n        functions.push(funct);\n        if (name) {\n            func.name = name;\n            func.string = name;\n            define('function', func);\n            func.init = true;\n            func.used += 1;\n        }\n        func.writeable = false;\n        one_space();\n        func.block = block('function');\n        Object.keys(scope).forEach(function (name) {\n            var master = scope[name];\n            if (!master.used && master.kind !== 'exception' &&\n                    (master.kind !== 'parameter' || !option.unparam)) {\n                master.warn('unused_a');\n            } else if (!master.init) {\n                master.warn('uninitialized_a');\n            }\n        });\n        funct = old_funct;\n        option = old_option;\n        scope = old_scope;\n    }\n\n    prefix('{', function (that) {\n        var get, i, j, name, p, set, seen = Object.create(null);\n        that.first = [];\n        step_in();\n        while (next_token.id !== '}') {\n            indent.wrap = false;\n\n// JSLint recognizes the ES5 extension for get/set in object literals,\n// but requires that they be used in pairs.\n\n            edge();\n            if (next_token.string === 'get' && peek().id !== ':') {\n                if (!option.es5) {\n                    next_token.warn('es5');\n                }\n                get = next_token;\n                advance('get');\n                one_space_only();\n                name = next_token;\n                i = property_name();\n                if (!i) {\n                    next_token.stop('missing_property');\n                }\n                get.string = '';\n                do_function(get);\n                if (funct.loopage) {\n                    get.warn('function_loop');\n                }\n                p = get.first;\n                if (p && p.length) {\n                    p[0].warn('parameter_a_get_b', p[0].string, i);\n                }\n                comma();\n                set = next_token;\n                spaces();\n                edge();\n                advance('set');\n                set.string = '';\n                one_space_only();\n                j = property_name();\n                if (i !== j) {\n                    token.stop('expected_a_b', i, j || next_token.string);\n                }\n                do_function(set);\n                if (set.block.length === 0) {\n                    token.warn('missing_a', 'throw');\n                }\n                p = set.first;\n                if (!p || p.length !== 1) {\n                    set.stop('parameter_set_a', 'value');\n                } else if (p[0].string !== 'value') {\n                    p[0].stop('expected_a_b', 'value', p[0].string);\n                }\n                name.first = [get, set];\n            } else {\n                name = next_token;\n                i = property_name();\n                if (typeof i !== 'string') {\n                    next_token.stop('missing_property');\n                }\n                advance(':');\n                spaces();\n                name.first = expression(10);\n            }\n            that.first.push(name);\n            if (seen[i] === true) {\n                next_token.warn('duplicate_a', i);\n            }\n            seen[i] = true;\n            tally_property(i);\n            if (next_token.id !== ',') {\n                break;\n            }\n            for (;;) {\n                comma();\n                if (next_token.id !== ',') {\n                    break;\n                }\n                next_token.warn('unexpected_a');\n            }\n            if (next_token.id === '}' && !option.es5) {\n                token.warn('unexpected_a');\n            }\n        }\n        step_out('}', that);\n        return that;\n    });\n\n    stmt('{', function () {\n        next_token.warn('statement_block');\n        this.arity = 'statement';\n        this.block = statements();\n        this.disrupt = this.block.disrupt;\n        advance('}', this);\n        return this;\n    });\n\n    stmt('/*global', directive);\n    stmt('/*globals', directive);\n    stmt('/*jslint', directive);\n    stmt('/*member', directive);\n    stmt('/*members', directive);\n    stmt('/*property', directive);\n    stmt('/*properties', directive);\n\n    stmt('var', function () {\n\n// JavaScript does not have block scope. It only has function scope. So,\n// declaring a variable in a block can have unexpected consequences.\n\n// var.first will contain an array, the array containing name tokens\n// and assignment tokens.\n\n        var assign, id, name;\n\n        if (funct.loopage) {\n            next_token.warn('var_loop');\n        } else if (funct.varstatement && !option.vars) {\n            next_token.warn('combine_var');\n        }\n        if (funct !== global_funct) {\n            funct.varstatement = true;\n        }\n        this.arity = 'statement';\n        this.first = [];\n        step_in('var');\n        for (;;) {\n            name = next_token;\n            id = identifier(true);\n            define('var', name);\n            name.dead = funct;\n            if (next_token.id === '=') {\n                assign = next_token;\n                assign.first = name;\n                spaces();\n                advance('=');\n                spaces();\n                if (next_token.id === 'undefined') {\n                    token.warn('unnecessary_initialize', id);\n                }\n                if (peek(0).id === '=' && next_token.identifier) {\n                    next_token.stop('var_a_not');\n                }\n                assign.second = expression(0);\n                assign.arity = 'infix';\n                name.init = true;\n                this.first.push(assign);\n            } else {\n                this.first.push(name);\n            }\n            name.dead = false;\n            name.writeable = true;\n            if (next_token.id !== ',') {\n                break;\n            }\n            comma();\n            indent.wrap = false;\n            if (var_mode && next_token.line === token.line &&\n                    this.first.length === 1) {\n                var_mode = null;\n                indent.open = false;\n                indent.at -= option.indent;\n            }\n            spaces();\n            edge();\n        }\n        var_mode = null;\n        step_out();\n        return this;\n    });\n\n    stmt('function', function () {\n        one_space();\n        if (in_block) {\n            token.warn('function_block');\n        }\n        var name = next_token,\n            id = identifier(true);\n        define('var', name);\n        name.init = true;\n        name.statement = true;\n        no_space();\n        this.arity = 'statement';\n        do_function(this, id);\n        if (next_token.id === '(' && next_token.line === token.line) {\n            next_token.stop('function_statement');\n        }\n        return this;\n    });\n\n    prefix('function', function (that) {\n        var id = optional_identifier(true), name;\n        if (id) {\n            name = token;\n            no_space();\n        } else {\n            id = '';\n            one_space();\n        }\n        do_function(that, id);\n        if (name) {\n            name.function = that.function;\n        }\n        if (funct.loopage) {\n            that.warn('function_loop');\n        }\n        switch (next_token.id) {\n        case ';':\n        case '(':\n        case ')':\n        case ',':\n        case ']':\n        case '}':\n        case ':':\n            break;\n        case '.':\n            if (peek().string !== 'bind' || peek(1).id !== '(') {\n                next_token.warn('unexpected_a');\n            }\n            break;\n        default:\n            next_token.stop('unexpected_a');\n        }\n        that.arity = 'function';\n        return that;\n    });\n\n    stmt('if', function () {\n        var paren = next_token;\n        one_space();\n        advance('(');\n        step_in('control');\n        no_space();\n        edge();\n        this.arity = 'statement';\n        this.first = expected_condition(expected_relation(expression(0)));\n        no_space();\n        step_out(')', paren);\n        one_space();\n        this.block = block('if');\n        if (next_token.id === 'else') {\n            if (this.block.disrupt) {\n                next_token.warn('unnecessary_else');\n            }\n            one_space();\n            advance('else');\n            one_space();\n            this.else = next_token.id === 'if' || next_token.id === 'switch'\n                ? statement(true)\n                : block('else');\n            if (this.else.disrupt && this.block.disrupt) {\n                this.disrupt = true;\n            }\n        }\n        return this;\n    });\n\n    stmt('try', function () {\n\n// try.first    The catch variable\n// try.second   The catch clause\n// try.third    The finally clause\n// try.block    The try block\n\n        var exception_variable, paren;\n        one_space();\n        this.arity = 'statement';\n        this.block = block('try');\n        if (next_token.id === 'catch') {\n            one_space();\n            advance('catch');\n            one_space();\n            paren = next_token;\n            advance('(');\n            step_in('control');\n            no_space();\n            edge();\n            exception_variable = next_token;\n            this.first = identifier();\n            define('exception', exception_variable);\n            exception_variable.init = true;\n            no_space();\n            step_out(')', paren);\n            one_space();\n            this.second = block('catch');\n            if (this.second.length) {\n                if (this.first === 'ignore') {\n                    exception_variable.warn('unexpected_a');\n                }\n            } else {\n                if (this.first !== 'ignore') {\n                    exception_variable.warn('expected_a_b', 'ignore',\n                        exception_variable.string);\n                }\n            }\n            exception_variable.dead = true;\n        }\n        if (next_token.id === 'finally') {\n            one_space();\n            advance('finally');\n            one_space();\n            this.third = block('finally');\n        } else if (!this.second) {\n            next_token.stop('expected_a_b', 'catch', artifact());\n        }\n        return this;\n    });\n\n    labeled_stmt('while', function () {\n        one_space();\n        var paren = next_token;\n        funct.loopage += 1;\n        advance('(');\n        step_in('control');\n        no_space();\n        edge();\n        this.arity = 'statement';\n        this.first = expected_relation(expression(0));\n        if (this.first.id !== 'true') {\n            expected_condition(this.first, 'unexpected_a');\n        }\n        no_space();\n        step_out(')', paren);\n        one_space();\n        this.block = block('while');\n        if (this.block.disrupt) {\n            prev_token.warn('strange_loop');\n        }\n        funct.loopage -= 1;\n        return this;\n    });\n\n    reserve('with');\n\n    labeled_stmt('switch', function () {\n\n// switch.first         the switch expression\n// switch.second        the array of cases. A case is 'case' or 'default' token:\n//    case.first        the array of case expressions\n//    case.second       the array of statements\n// If all of the arrays of statements are disrupt, then the switch is disrupt.\n\n        var cases = [],\n            old_in_block = in_block,\n            particular,\n            that = token,\n            the_case = next_token,\n            unbroken = true;\n\n        function find_duplicate_case(value) {\n            if (are_similar(particular, value)) {\n                value.warn('duplicate_a');\n            }\n        }\n\n        one_space();\n        advance('(');\n        no_space();\n        step_in();\n        this.arity = 'statement';\n        this.first = expected_condition(expected_relation(expression(0)));\n        no_space();\n        step_out(')', the_case);\n        one_space();\n        advance('{');\n        step_in();\n        in_block = true;\n        this.second = [];\n        if (that.from !== next_token.from && !option.white) {\n            next_token.warn('expected_a_at_b_c', next_token.string, that.from, next_token.from);\n        }\n        while (next_token.id === 'case') {\n            the_case = next_token;\n            cases.forEach(find_duplicate_case);\n            the_case.first = [];\n            the_case.arity = 'case';\n            spaces();\n            edge('case');\n            advance('case');\n            for (;;) {\n                one_space();\n                particular = expression(0);\n                cases.forEach(find_duplicate_case);\n                cases.push(particular);\n                the_case.first.push(particular);\n                if (particular.id === 'NaN') {\n                    particular.warn('unexpected_a');\n                }\n                no_space_only();\n                advance(':');\n                if (next_token.id !== 'case') {\n                    break;\n                }\n                spaces();\n                edge('case');\n                advance('case');\n            }\n            spaces();\n            the_case.second = statements();\n            if (the_case.second && the_case.second.length > 0) {\n                particular = the_case.second[the_case.second.length - 1];\n                if (particular.disrupt) {\n                    if (particular.id === 'break') {\n                        unbroken = false;\n                    }\n                } else {\n                    next_token.warn('missing_a_after_b', 'break', 'case');\n                }\n            } else {\n                next_token.warn('empty_case');\n            }\n            this.second.push(the_case);\n        }\n        if (this.second.length === 0) {\n            next_token.warn('missing_a', 'case');\n        }\n        if (next_token.id === 'default') {\n            spaces();\n            the_case = next_token;\n            the_case.arity = 'case';\n            edge('case');\n            advance('default');\n            no_space_only();\n            advance(':');\n            spaces();\n            the_case.second = statements();\n            if (the_case.second && the_case.second.length > 0) {\n                particular = the_case.second[the_case.second.length - 1];\n                if (unbroken && particular.disrupt && particular.id !== 'break') {\n                    this.disrupt = true;\n                }\n            }\n            this.second.push(the_case);\n        }\n        spaces();\n        step_out('}', this);\n        in_block = old_in_block;\n        return this;\n    });\n\n    stmt('debugger', function () {\n        if (!option.debug) {\n            this.warn('unexpected_a');\n        }\n        this.arity = 'statement';\n        return this;\n    });\n\n    labeled_stmt('do', function () {\n        funct.loopage += 1;\n        one_space();\n        this.arity = 'statement';\n        this.block = block('do');\n        if (this.block.disrupt) {\n            prev_token.warn('strange_loop');\n        }\n        one_space();\n        advance('while');\n        var paren = next_token;\n        one_space();\n        advance('(');\n        step_in();\n        no_space();\n        edge();\n        this.first = expected_condition(expected_relation(expression(0)), 'unexpected_a');\n        no_space();\n        step_out(')', paren);\n        funct.loopage -= 1;\n        return this;\n    });\n\n    labeled_stmt('for', function () {\n\n        var blok, filter, master, ok = false, paren = next_token, value;\n        this.arity = 'statement';\n        funct.loopage += 1;\n        advance('(');\n        if (next_token.id === ';') {\n            no_space();\n            advance(';');\n            no_space();\n            advance(';');\n            no_space();\n            advance(')');\n            blok = block('for');\n        } else {\n            step_in('control');\n            spaces(this, paren);\n            no_space();\n            if (next_token.id === 'var') {\n                next_token.stop('move_var');\n            }\n            edge();\n            if (peek(0).id === 'in') {\n                this.forin = true;\n                value = expression(1000);\n                master = value.master;\n                if (master.kind !== 'var' || master.function !== funct ||\n                        !master.writeable || master.dead) {\n                    value.warn('bad_in_a');\n                }\n                master.init = true;\n                master.used -= 1;\n                this.first = value;\n                advance('in');\n                this.second = expression(20);\n                step_out(')', paren);\n                blok = block('for');\n                if (!option.forin) {\n                    if (blok.length === 1 && typeof blok[0] === 'object') {\n                        if (blok[0].id === 'if' && !blok[0].else) {\n                            filter = blok[0].first;\n                            while (filter.id === '&&') {\n                                filter = filter.first;\n                            }\n                            switch (filter.id) {\n                            case '===':\n                            case '!==':\n                                ok = filter.first.id === '['\n                                    ? are_similar(filter.first.first, this.second) &&\n                                        are_similar(filter.first.second, this.first)\n                                    : filter.first.id === 'typeof' &&\n                                        filter.first.first.id === '[' &&\n                                        are_similar(filter.first.first.first, this.second) &&\n                                        are_similar(filter.first.first.second, this.first);\n                                break;\n                            case '(':\n                                ok = filter.first.id === '.' && ((\n                                    are_similar(filter.first.first, this.second) &&\n                                    filter.first.second.string === 'hasOwnProperty' &&\n                                    are_similar(filter.second[0], this.first)\n                                ) || (\n                                    filter.first.first.id === '.' &&\n                                    filter.first.first.first.first &&\n                                    filter.first.first.first.first.string === 'Object' &&\n                                    filter.first.first.first.id === '.' &&\n                                    filter.first.first.first.second.string === 'prototype' &&\n                                    filter.first.first.second.string === 'hasOwnProperty' &&\n                                    filter.first.second.string === 'call' &&\n                                    are_similar(filter.second[0], this.second) &&\n                                    are_similar(filter.second[1], this.first)\n                                ));\n                                break;\n                            }\n                        } else if (blok[0].id === 'switch') {\n                            ok = blok[0].id === 'switch' &&\n                                blok[0].first.id === 'typeof' &&\n                                blok[0].first.first.id === '[' &&\n                                are_similar(blok[0].first.first.first, this.second) &&\n                                are_similar(blok[0].first.first.second, this.first);\n                        }\n                    }\n                    if (!ok) {\n                        this.warn('for_if');\n                    }\n                }\n            } else {\n                edge();\n                this.first = [];\n                for (;;) {\n                    this.first.push(expression(0, 'for'));\n                    if (next_token.id !== ',') {\n                        break;\n                    }\n                    comma();\n                }\n                semicolon();\n                edge();\n                this.second = expected_relation(expression(0));\n                if (this.second.id !== 'true') {\n                    expected_condition(this.second, 'unexpected_a');\n                }\n                semicolon(token);\n                if (next_token.id === ';') {\n                    next_token.stop('expected_a_b', ')', ';');\n                }\n                this.third = [];\n                edge();\n                for (;;) {\n                    this.third.push(expression(0, 'for'));\n                    if (next_token.id !== ',') {\n                        break;\n                    }\n                    comma();\n                }\n                no_space();\n                step_out(')', paren);\n                one_space();\n                blok = block('for');\n            }\n        }\n        if (blok.disrupt) {\n            prev_token.warn('strange_loop');\n        }\n        this.block = blok;\n        funct.loopage -= 1;\n        return this;\n    });\n\n    function optional_label(that) {\n        var label = next_token.string,\n            master;\n        that.arity = 'statement';\n        if (next_token.identifier && token.line === next_token.line) {\n            one_space_only();\n            master = scope[label];\n            if (!master || master.kind !== 'label') {\n                next_token.warn('not_a_label');\n            } else if (master.dead || master.function !== funct) {\n                next_token.warn('not_a_scope');\n            } else {\n                master.used += 1;\n            }\n            that.first = next_token;\n            advance();\n        }\n        return that;\n\n    }\n\n    disrupt_stmt('break', function () {\n        return optional_label(this);\n    });\n\n    disrupt_stmt('continue', function () {\n        if (!option.continue) {\n            this.warn('unexpected_a');\n        }\n        return optional_label(this);\n    });\n\n    disrupt_stmt('return', function () {\n        if (funct === global_funct) {\n            this.warn('unexpected_a');\n        }\n        this.arity = 'statement';\n        if (next_token.id !== ';' && next_token.line === token.line) {\n            if (option.closure) {\n                spaces();\n            } else {\n                one_space_only();\n            }\n            if (next_token.id === '/' || next_token.id === '(regexp)') {\n                next_token.warn('wrap_regexp');\n            }\n            this.first = expression(0);\n            if (this.first.assign) {\n                this.first.warn('unexpected_a');\n            }\n        }\n        return this;\n    });\n\n    disrupt_stmt('throw', function () {\n        this.arity = 'statement';\n        one_space_only();\n        this.first = expression(20);\n        return this;\n    });\n\n\n//  Superfluous reserved words\n\n    reserve('class');\n    reserve('const');\n    reserve('enum');\n    reserve('export');\n    reserve('extends');\n    reserve('import');\n    reserve('super');\n\n// Harmony reserved words\n\n    reserve('implements');\n    reserve('interface');\n    reserve('let');\n    reserve('package');\n    reserve('private');\n    reserve('protected');\n    reserve('public');\n    reserve('static');\n    reserve('yield');\n\n\n// Parse JSON\n\n    function json_value() {\n\n        function json_object() {\n            var brace = next_token, object = Object.create(null);\n            advance('{');\n            if (next_token.id !== '}') {\n                while (next_token.id !== '(end)') {\n                    while (next_token.id === ',') {\n                        next_token.warn('unexpected_a');\n                        advance(',');\n                    }\n                    if (next_token.id !== '(string)') {\n                        next_token.warn('expected_string_a');\n                    }\n                    if (object[next_token.string] === true) {\n                        next_token.warn('duplicate_a');\n                    } else if (next_token.string === '__proto__') {\n                        next_token.warn('dangling_a');\n                    } else {\n                        object[next_token.string] = true;\n                    }\n                    advance();\n                    advance(':');\n                    json_value();\n                    if (next_token.id !== ',') {\n                        break;\n                    }\n                    advance(',');\n                    if (next_token.id === '}') {\n                        token.warn('unexpected_a');\n                        break;\n                    }\n                }\n            }\n            advance('}', brace);\n        }\n\n        function json_array() {\n            var bracket = next_token;\n            advance('[');\n            if (next_token.id !== ']') {\n                while (next_token.id !== '(end)') {\n                    while (next_token.id === ',') {\n                        next_token.warn('unexpected_a');\n                        advance(',');\n                    }\n                    json_value();\n                    if (next_token.id !== ',') {\n                        break;\n                    }\n                    advance(',');\n                    if (next_token.id === ']') {\n                        token.warn('unexpected_a');\n                        break;\n                    }\n                }\n            }\n            advance(']', bracket);\n        }\n\n        switch (next_token.id) {\n        case '{':\n            json_object();\n            break;\n        case '[':\n            json_array();\n            break;\n        case 'true':\n        case 'false':\n        case 'null':\n        case '(number)':\n        case '(string)':\n            advance();\n            break;\n        case '-':\n            advance('-');\n            no_space_only();\n            advance('(number)');\n            break;\n        default:\n            next_token.stop('unexpected_a');\n        }\n    }\n\n\n// The actual JSLINT function itself.\n\n    itself = function JSLint(the_source, the_option) {\n\n        var i, predef, tree;\n        itself.errors = [];\n        itself.tree = '';\n        itself.properties = '';\n        begin = prev_token = token = next_token =\n            Object.create(syntax['(begin)']);\n        tokens = [];\n        predefined = Object.create(null);\n        add_to_predefined(standard);\n        property = Object.create(null);\n        if (the_option) {\n            option = Object.create(the_option);\n            predef = option.predef;\n            if (predef) {\n                if (Array.isArray(predef)) {\n                    for (i = 0; i < predef.length; i += 1) {\n                        predefined[predef[i]] = true;\n                    }\n                } else if (typeof predef === 'object') {\n                    add_to_predefined(predef);\n                }\n            }\n        } else {\n            option = Object.create(null);\n        }\n        option.indent = +option.indent || 4;\n        option.maxerr = +option.maxerr || 50;\n        global_scope = scope = Object.create(null);\n        global_funct = funct = {\n            scope: scope,\n            loopage: 0,\n            level: 0\n        };\n        functions = [funct];\n        block_var = [];\n\n        comments = [];\n        comments_off = false;\n        in_block = false;\n        indent = null;\n        json_mode = false;\n        lookahead = [];\n        node_js = false;\n        prereg = true;\n        strict_mode = false;\n        var_mode = null;\n        warnings = 0;\n        lex.init(the_source);\n\n        assume();\n\n        try {\n            advance();\n            if (next_token.id === '(number)') {\n                next_token.stop('unexpected_a');\n            } else {\n                switch (next_token.id) {\n                case '{':\n                case '[':\n                    comments_off = true;\n                    json_mode = true;\n                    json_value();\n                    break;\n                default:\n\n// If the first token is a semicolon, ignore it. This is sometimes used when\n// files are intended to be appended to files that may be sloppy. A sloppy\n// file may be depending on semicolon insertion on its last line.\n\n                    step_in(1);\n                    if (next_token.id === ';' && !node_js) {\n                        semicolon();\n                    }\n                    tree = statements();\n                    begin.first = tree;\n                    itself.tree = begin;\n                    if (tree.disrupt) {\n                        prev_token.warn('weird_program');\n                    }\n                }\n            }\n            indent = null;\n            advance('(end)');\n            itself.property = property;\n        } catch (e) {\n            if (e) {        // ~~\n                itself.errors.push({\n                    reason    : e.message,\n                    line      : e.line || next_token.line,\n                    character : e.character || next_token.from\n                }, null);\n            }\n        }\n        return itself.errors.length === 0;\n    };\n\n    function unique(array) {\n        array = array.sort();\n        var i, length = 0, previous, value;\n        for (i = 0; i < array.length; i += 1) {\n            value = array[i];\n            if (value !== previous) {\n                array[length] = value;\n                previous = value;\n                length += 1;\n            }\n        }\n        array.length = length;\n        return array;\n    }\n\n// Data summary.\n\n    itself.data = function () {\n        var data = {functions: []},\n            function_data,\n            i,\n            the_function,\n            the_scope;\n        data.errors = itself.errors;\n        data.json = json_mode;\n        data.global = unique(Object.keys(global_scope));\n\n        function selects(name) {\n            var kind = the_scope[name].kind;\n            switch (kind) {\n            case 'var':\n            case 'exception':\n            case 'label':\n                function_data[kind].push(name);\n                break;\n            }\n        }\n\n        for (i = 1; i < functions.length; i += 1) {\n            the_function = functions[i];\n            function_data = {\n                name: the_function.name,\n                line: the_function.line,\n                level: the_function.level,\n                parameter: the_function.parameter,\n                var: [],\n                exception: [],\n                closure: unique(the_function.closure),\n                outer: unique(the_function.outer),\n                global: unique(the_function.global),\n                label: []\n            };\n            the_scope = the_function.scope;\n            Object.keys(the_scope).forEach(selects);\n            function_data.var.sort();\n            function_data.exception.sort();\n            function_data.label.sort();\n            data.functions.push(function_data);\n        }\n        data.tokens = tokens;\n        return data;\n    };\n\n    itself.error_report = function (data) {\n        var evidence, i, output = [], warning;\n        if (data.errors.length) {\n            if (data.json) {\n                output.push('<cite>JSON: bad.</cite><br>');\n            }\n            for (i = 0; i < data.errors.length; i += 1) {\n                warning = data.errors[i];\n                if (warning) {\n                    evidence = warning.evidence || '';\n                    output.push('<cite>');\n                    if (isFinite(warning.line)) {\n                        output.push('<address>line ' +\n                            String(warning.line) +\n                            ' character ' + String(warning.character) +\n                            '</address>');\n                    }\n                    output.push(warning.reason.entityify() + '</cite>');\n                    if (evidence) {\n                        output.push('<pre>' + evidence.entityify() + '</pre>');\n                    }\n                }\n            }\n        }\n        return output.join('');\n    };\n\n\n    itself.report = function (data) {\n        var dl, i, j, names, output = [], the_function;\n\n        function detail(h, array) {\n            var comma_needed = false;\n            if (array.length) {\n                output.push(\"<dt>\" + h + \"</dt><dd>\");\n                array.forEach(function (item) {\n                    output.push((comma_needed ? ', ' : '') + item);\n                    comma_needed = true;\n                });\n                output.push(\"</dd>\");\n            }\n        }\n\n        output.push('<dl class=level0>');\n        if (data.global.length) {\n            detail('global', data.global);\n            dl = true;\n        } else if (data.json) {\n            if (!data.errors.length) {\n                output.push(\"<dt>JSON: good.</dt>\");\n            }\n        } else {\n            output.push(\"<dt><i>No new global variables introduced.</i></dt>\");\n        }\n        if (dl) {\n            output.push(\"</dl>\");\n        } else {\n            output[0] = '';\n        }\n\n        if (data.functions) {\n            for (i = 0; i < data.functions.length; i += 1) {\n                the_function = data.functions[i];\n                names = [];\n                if (the_function.params) {\n                    for (j = 0; j < the_function.params.length; j += 1) {\n                        names[j] = the_function.params[j].string;\n                    }\n                }\n                output.push('<dl class=level' + the_function.level +\n                    '><address>line ' + String(the_function.line) +\n                    '</address>' + the_function.name.entityify() + '(' +\n                    names.join(', ') + ')');\n                detail('parameter', the_function.parameter);\n                detail('variable', the_function.var);\n                detail('exception', the_function.exception);\n                detail('closure', the_function.closure);\n                detail('outer', the_function.outer);\n                detail('global', the_function.global);\n                detail('label', the_function.label);\n                output.push('</dl>');\n            }\n        }\n        return output.join('');\n    };\n\n    itself.properties_report = function (property) {\n        if (!property) {\n            return '';\n        }\n        var i,\n            key,\n            keys = Object.keys(property).sort(),\n            mem = '    ',\n            name,\n            not_first = false,\n            output = ['/*properties'];\n        for (i = 0; i < keys.length; i += 1) {\n            key = keys[i];\n            if (property[key] > 0) {\n                if (not_first) {\n                    mem += ', ';\n                }\n                name = ix.test(key)\n                    ? key\n                    : '\\'' + key.replace(nx, sanitize) + '\\'';\n                if (mem.length + name.length >= 80) {\n                    output.push(mem);\n                    mem = '    ';\n                }\n                mem += name;\n                not_first = true;\n            }\n        }\n        output.push(mem, '*/\\n');\n        return output.join('\\n');\n    };\n\n    itself.color = function (data) {\n        var from,\n            i = 1,\n            level,\n            line,\n            result = [],\n            thru,\n            data_token = data.tokens[0];\n        while (data_token && data_token.id !== '(end)') {\n            from = data_token.from;\n            line = data_token.line;\n            thru = data_token.thru;\n            level = data_token.function.level;\n            do {\n                thru = data_token.thru;\n                data_token = data.tokens[i];\n                i += 1;\n            } while (data_token && data_token.line === line &&\n                    data_token.from - thru < 5 &&\n                    level === data_token.function.level);\n            result.push({\n                line: line,\n                level: level,\n                from: from,\n                thru: thru\n            });\n        }\n        return result;\n    };\n\n    itself.jslint = itself;\n\n    itself.edition = '2013-07-24';\n\n    return itself;\n}());\n\n// Make JSLINT a Node module, if possible.\nif (typeof exports === 'object' && exports)\n    exports.JSLINT = JSLINT;\n"
  },
  {
    "path": "sublimelinter/modules/libs/jslint/linter.js",
    "content": "/*jslint node: true, sloppy: true */\n/*globals LINTER_PATH, load */\n\nvar JSLINT = require(\"./jslint\").JSLINT;\n\nexports.lint = function (code, config) {\n    var results = [];\n\n    try {\n        JSLINT(code, config);\n    } catch (e) {\n        results.push({line: 1, character: 1, reason: e.message});\n    } finally {\n        JSLINT.errors.forEach(function (error) {\n            if (error) {\n                results.push(error);\n            }\n        });\n    }\n\n    return results;\n};\n"
  },
  {
    "path": "sublimelinter/modules/libs/pep8.py",
    "content": "#!/usr/bin/env python\n# pep8.py - Check Python source code formatting, according to PEP 8\n# Copyright (C) 2006-2009 Johann C. Rocholl <johann@rocholl.net>\n# Copyright (C) 2009-2013 Florent Xicluna <florent.xicluna@gmail.com>\n#\n# Permission is hereby granted, free of charge, to any person\n# obtaining a copy of this software and associated documentation files\n# (the \"Software\"), to deal in the Software without restriction,\n# including without limitation the rights to use, copy, modify, merge,\n# publish, distribute, sublicense, and/or sell copies of the Software,\n# and to permit persons to whom the Software is furnished to do so,\n# subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be\n# included in all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n# SOFTWARE.\n\nr\"\"\"\nCheck Python source code formatting, according to PEP 8:\nhttp://www.python.org/dev/peps/pep-0008/\n\nFor usage and a list of options, try this:\n$ python pep8.py -h\n\nThis program and its regression test suite live here:\nhttp://github.com/jcrocholl/pep8\n\nGroups of errors and warnings:\nE errors\nW warnings\n100 indentation\n200 whitespace\n300 blank lines\n400 imports\n500 line length\n600 deprecation\n700 statements\n900 syntax error\n\"\"\"\n__version__ = '1.4.6'\n\nimport os\nimport sys\nimport re\nimport time\nimport inspect\nimport keyword\nimport tokenize\nfrom optparse import OptionParser\nfrom fnmatch import fnmatch\ntry:\n    from configparser import RawConfigParser\n    from io import TextIOWrapper\nexcept ImportError:\n    from ConfigParser import RawConfigParser\n\nDEFAULT_EXCLUDE = '.svn,CVS,.bzr,.hg,.git,__pycache__'\nDEFAULT_IGNORE = 'E123,E226,E24'\nif sys.platform == 'win32':\n    DEFAULT_CONFIG = os.path.expanduser(r'~\\.pep8')\nelse:\n    DEFAULT_CONFIG = os.path.join(os.getenv('XDG_CONFIG_HOME') or\n                                  os.path.expanduser('~/.config'), 'pep8')\nPROJECT_CONFIG = ('setup.cfg', 'tox.ini', '.pep8')\nTESTSUITE_PATH = os.path.join(os.path.dirname(__file__), 'testsuite')\nMAX_LINE_LENGTH = 79\nREPORT_FORMAT = {\n    'default': '%(path)s:%(row)d:%(col)d: %(code)s %(text)s',\n    'pylint': '%(path)s:%(row)d: [%(code)s] %(text)s',\n}\n\nPyCF_ONLY_AST = 1024\nSINGLETONS = frozenset(['False', 'None', 'True'])\nKEYWORDS = frozenset(keyword.kwlist + ['print']) - SINGLETONS\nUNARY_OPERATORS = frozenset(['>>', '**', '*', '+', '-'])\nARITHMETIC_OP = frozenset(['**', '*', '/', '//', '+', '-'])\nWS_OPTIONAL_OPERATORS = ARITHMETIC_OP.union(['^', '&', '|', '<<', '>>', '%'])\nWS_NEEDED_OPERATORS = frozenset([\n    '**=', '*=', '/=', '//=', '+=', '-=', '!=', '<>', '<', '>',\n    '%=', '^=', '&=', '|=', '==', '<=', '>=', '<<=', '>>=', '='])\nWHITESPACE = frozenset(' \\t')\nSKIP_TOKENS = frozenset([tokenize.COMMENT, tokenize.NL, tokenize.NEWLINE,\n                         tokenize.INDENT, tokenize.DEDENT])\nBENCHMARK_KEYS = ['directories', 'files', 'logical lines', 'physical lines']\n\nINDENT_REGEX = re.compile(r'([ \\t]*)')\nRAISE_COMMA_REGEX = re.compile(r'raise\\s+\\w+\\s*,')\nRERAISE_COMMA_REGEX = re.compile(r'raise\\s+\\w+\\s*,\\s*\\w+\\s*,\\s*\\w+')\nERRORCODE_REGEX = re.compile(r'\\b[A-Z]\\d{3}\\b')\nDOCSTRING_REGEX = re.compile(r'u?r?[\"\\']')\nEXTRANEOUS_WHITESPACE_REGEX = re.compile(r'[[({] | []}),;:]')\nWHITESPACE_AFTER_COMMA_REGEX = re.compile(r'[,;:]\\s*(?:  |\\t)')\nCOMPARE_SINGLETON_REGEX = re.compile(r'([=!]=)\\s*(None|False|True)')\nCOMPARE_TYPE_REGEX = re.compile(r'(?:[=!]=|is(?:\\s+not)?)\\s*type(?:s.\\w+Type'\n                                r'|\\s*\\(\\s*([^)]*[^ )])\\s*\\))')\nKEYWORD_REGEX = re.compile(r'(\\s*)\\b(?:%s)\\b(\\s*)' % r'|'.join(KEYWORDS))\nOPERATOR_REGEX = re.compile(r'(?:[^,\\s])(\\s*)(?:[-+*/|!<=>%&^]+)(\\s*)')\nLAMBDA_REGEX = re.compile(r'\\blambda\\b')\nHUNK_REGEX = re.compile(r'^@@ -\\d+(?:,\\d+)? \\+(\\d+)(?:,(\\d+))? @@.*$')\n\n# Work around Python < 2.6 behaviour, which does not generate NL after\n# a comment which is on a line by itself.\nCOMMENT_WITH_NL = tokenize.generate_tokens(['#\\n'].pop).send(None)[1] == '#\\n'\n\n\n##############################################################################\n# Plugins (check functions) for physical lines\n##############################################################################\n\n\ndef tabs_or_spaces(physical_line, indent_char):\n    r\"\"\"\n    Never mix tabs and spaces.\n\n    The most popular way of indenting Python is with spaces only.  The\n    second-most popular way is with tabs only.  Code indented with a mixture\n    of tabs and spaces should be converted to using spaces exclusively.  When\n    invoking the Python command line interpreter with the -t option, it issues\n    warnings about code that illegally mixes tabs and spaces.  When using -tt\n    these warnings become errors.  These options are highly recommended!\n\n    Okay: if a == 0:\\n        a = 1\\n        b = 1\n    E101: if a == 0:\\n        a = 1\\n\\tb = 1\n    \"\"\"\n    indent = INDENT_REGEX.match(physical_line).group(1)\n    for offset, char in enumerate(indent):\n        if char != indent_char:\n            return offset, \"E101 indentation contains mixed spaces and tabs\"\n\n\ndef tabs_obsolete(physical_line):\n    r\"\"\"\n    For new projects, spaces-only are strongly recommended over tabs.  Most\n    editors have features that make this easy to do.\n\n    Okay: if True:\\n    return\n    W191: if True:\\n\\treturn\n    \"\"\"\n    indent = INDENT_REGEX.match(physical_line).group(1)\n    if '\\t' in indent:\n        return indent.index('\\t'), \"W191 indentation contains tabs\"\n\n\ndef trailing_whitespace(physical_line):\n    r\"\"\"\n    JCR: Trailing whitespace is superfluous.\n    FBM: Except when it occurs as part of a blank line (i.e. the line is\n         nothing but whitespace). According to Python docs[1] a line with only\n         whitespace is considered a blank line, and is to be ignored. However,\n         matching a blank line to its indentation level avoids mistakenly\n         terminating a multi-line statement (e.g. class declaration) when\n         pasting code into the standard Python interpreter.\n\n         [1] http://docs.python.org/reference/lexical_analysis.html#blank-lines\n\n    The warning returned varies on whether the line itself is blank, for easier\n    filtering for those who want to indent their blank lines.\n\n    Okay: spam(1)\\n#\n    W291: spam(1) \\n#\n    W293: class Foo(object):\\n    \\n    bang = 12\n    \"\"\"\n    physical_line = physical_line.rstrip('\\n')    # chr(10), newline\n    physical_line = physical_line.rstrip('\\r')    # chr(13), carriage return\n    physical_line = physical_line.rstrip('\\x0c')  # chr(12), form feed, ^L\n    stripped = physical_line.rstrip(' \\t\\v')\n    if physical_line != stripped:\n        if stripped:\n            return len(stripped), \"W291 trailing whitespace\"\n        else:\n            return 0, \"W293 blank line contains whitespace\"\n\n\ndef trailing_blank_lines(physical_line, lines, line_number):\n    r\"\"\"\n    JCR: Trailing blank lines are superfluous.\n\n    Okay: spam(1)\n    W391: spam(1)\\n\n    \"\"\"\n    if not physical_line.rstrip() and line_number == len(lines):\n        return 0, \"W391 blank line at end of file\"\n\n\ndef missing_newline(physical_line):\n    \"\"\"\n    JCR: The last line should have a newline.\n\n    Reports warning W292.\n    \"\"\"\n    if physical_line.rstrip() == physical_line:\n        return len(physical_line), \"W292 no newline at end of file\"\n\n\ndef maximum_line_length(physical_line, max_line_length):\n    \"\"\"\n    Limit all lines to a maximum of 79 characters.\n\n    There are still many devices around that are limited to 80 character\n    lines; plus, limiting windows to 80 characters makes it possible to have\n    several windows side-by-side.  The default wrapping on such devices looks\n    ugly.  Therefore, please limit all lines to a maximum of 79 characters.\n    For flowing long blocks of text (docstrings or comments), limiting the\n    length to 72 characters is recommended.\n\n    Reports error E501.\n    \"\"\"\n    line = physical_line.rstrip()\n    length = len(line)\n    if length > max_line_length and not noqa(line):\n        if hasattr(line, 'decode'):   # Python 2\n            # The line could contain multi-byte characters\n            try:\n                length = len(line.decode('utf-8'))\n            except UnicodeError:\n                pass\n        if length > max_line_length:\n            return (max_line_length, \"E501 line too long \"\n                    \"(%d > %d characters)\" % (length, max_line_length))\n\n\n##############################################################################\n# Plugins (check functions) for logical lines\n##############################################################################\n\n\ndef blank_lines(logical_line, blank_lines, indent_level, line_number,\n                previous_logical, previous_indent_level):\n    r\"\"\"\n    Separate top-level function and class definitions with two blank lines.\n\n    Method definitions inside a class are separated by a single blank line.\n\n    Extra blank lines may be used (sparingly) to separate groups of related\n    functions.  Blank lines may be omitted between a bunch of related\n    one-liners (e.g. a set of dummy implementations).\n\n    Use blank lines in functions, sparingly, to indicate logical sections.\n\n    Okay: def a():\\n    pass\\n\\n\\ndef b():\\n    pass\n    Okay: def a():\\n    pass\\n\\n\\n# Foo\\n# Bar\\n\\ndef b():\\n    pass\n\n    E301: class Foo:\\n    b = 0\\n    def bar():\\n        pass\n    E302: def a():\\n    pass\\n\\ndef b(n):\\n    pass\n    E303: def a():\\n    pass\\n\\n\\n\\ndef b(n):\\n    pass\n    E303: def a():\\n\\n\\n\\n    pass\n    E304: @decorator\\n\\ndef a():\\n    pass\n    \"\"\"\n    if line_number < 3 and not previous_logical:\n        return  # Don't expect blank lines before the first line\n    if previous_logical.startswith('@'):\n        if blank_lines:\n            yield 0, \"E304 blank lines found after function decorator\"\n    elif blank_lines > 2 or (indent_level and blank_lines == 2):\n        yield 0, \"E303 too many blank lines (%d)\" % blank_lines\n    elif logical_line.startswith(('def ', 'class ', '@')):\n        if indent_level:\n            if not (blank_lines or previous_indent_level < indent_level or\n                    DOCSTRING_REGEX.match(previous_logical)):\n                yield 0, \"E301 expected 1 blank line, found 0\"\n        elif blank_lines != 2:\n            yield 0, \"E302 expected 2 blank lines, found %d\" % blank_lines\n\n\ndef extraneous_whitespace(logical_line):\n    \"\"\"\n    Avoid extraneous whitespace in the following situations:\n\n    - Immediately inside parentheses, brackets or braces.\n\n    - Immediately before a comma, semicolon, or colon.\n\n    Okay: spam(ham[1], {eggs: 2})\n    E201: spam( ham[1], {eggs: 2})\n    E201: spam(ham[ 1], {eggs: 2})\n    E201: spam(ham[1], { eggs: 2})\n    E202: spam(ham[1], {eggs: 2} )\n    E202: spam(ham[1 ], {eggs: 2})\n    E202: spam(ham[1], {eggs: 2 })\n\n    E203: if x == 4: print x, y; x, y = y , x\n    E203: if x == 4: print x, y ; x, y = y, x\n    E203: if x == 4 : print x, y; x, y = y, x\n    \"\"\"\n    line = logical_line\n    for match in EXTRANEOUS_WHITESPACE_REGEX.finditer(line):\n        text = match.group()\n        char = text.strip()\n        found = match.start()\n        if text == char + ' ':\n            # assert char in '([{'\n            yield found + 1, \"E201 whitespace after '%s'\" % char\n        elif line[found - 1] != ',':\n            code = ('E202' if char in '}])' else 'E203')  # if char in ',;:'\n            yield found, \"%s whitespace before '%s'\" % (code, char)\n\n\ndef whitespace_around_keywords(logical_line):\n    r\"\"\"\n    Avoid extraneous whitespace around keywords.\n\n    Okay: True and False\n    E271: True and  False\n    E272: True  and False\n    E273: True and\\tFalse\n    E274: True\\tand False\n    \"\"\"\n    for match in KEYWORD_REGEX.finditer(logical_line):\n        before, after = match.groups()\n\n        if '\\t' in before:\n            yield match.start(1), \"E274 tab before keyword\"\n        elif len(before) > 1:\n            yield match.start(1), \"E272 multiple spaces before keyword\"\n\n        if '\\t' in after:\n            yield match.start(2), \"E273 tab after keyword\"\n        elif len(after) > 1:\n            yield match.start(2), \"E271 multiple spaces after keyword\"\n\n\ndef missing_whitespace(logical_line):\n    \"\"\"\n    JCR: Each comma, semicolon or colon should be followed by whitespace.\n\n    Okay: [a, b]\n    Okay: (3,)\n    Okay: a[1:4]\n    Okay: a[:4]\n    Okay: a[1:]\n    Okay: a[1:4:2]\n    E231: ['a','b']\n    E231: foo(bar,baz)\n    E231: [{'a':'b'}]\n    \"\"\"\n    line = logical_line\n    for index in range(len(line) - 1):\n        char = line[index]\n        if char in ',;:' and line[index + 1] not in WHITESPACE:\n            before = line[:index]\n            if char == ':' and before.count('[') > before.count(']') and \\\n                    before.rfind('{') < before.rfind('['):\n                continue  # Slice syntax, no space required\n            if char == ',' and line[index + 1] == ')':\n                continue  # Allow tuple with only one element: (3,)\n            yield index, \"E231 missing whitespace after '%s'\" % char\n\n\ndef indentation(logical_line, previous_logical, indent_char,\n                indent_level, previous_indent_level):\n    r\"\"\"\n    Use 4 spaces per indentation level.\n\n    For really old code that you don't want to mess up, you can continue to\n    use 8-space tabs.\n\n    Okay: a = 1\n    Okay: if a == 0:\\n    a = 1\n    E111:   a = 1\n\n    Okay: for item in items:\\n    pass\n    E112: for item in items:\\npass\n\n    Okay: a = 1\\nb = 2\n    E113: a = 1\\n    b = 2\n    \"\"\"\n    if indent_char == ' ' and indent_level % 4:\n        yield 0, \"E111 indentation is not a multiple of four\"\n    indent_expect = previous_logical.endswith(':')\n    if indent_expect and indent_level <= previous_indent_level:\n        yield 0, \"E112 expected an indented block\"\n    if indent_level > previous_indent_level and not indent_expect:\n        yield 0, \"E113 unexpected indentation\"\n\n\ndef continued_indentation(logical_line, tokens, indent_level, hang_closing,\n                          noqa, verbose):\n    r\"\"\"\n    Continuation lines should align wrapped elements either vertically using\n    Python's implicit line joining inside parentheses, brackets and braces, or\n    using a hanging indent.\n\n    When using a hanging indent the following considerations should be applied:\n\n    - there should be no arguments on the first line, and\n\n    - further indentation should be used to clearly distinguish itself as a\n      continuation line.\n\n    Okay: a = (\\n)\n    E123: a = (\\n    )\n\n    Okay: a = (\\n    42)\n    E121: a = (\\n   42)\n    E122: a = (\\n42)\n    E123: a = (\\n    42\\n    )\n    E124: a = (24,\\n     42\\n)\n    E125: if (a or\\n    b):\\n    pass\n    E126: a = (\\n        42)\n    E127: a = (24,\\n      42)\n    E128: a = (24,\\n    42)\n    \"\"\"\n    first_row = tokens[0][2][0]\n    nrows = 1 + tokens[-1][2][0] - first_row\n    if noqa or nrows == 1:\n        return\n\n    # indent_next tells us whether the next block is indented; assuming\n    # that it is indented by 4 spaces, then we should not allow 4-space\n    # indents on the final continuation line; in turn, some other\n    # indents are allowed to have an extra 4 spaces.\n    indent_next = logical_line.endswith(':')\n\n    row = depth = 0\n    # remember how many brackets were opened on each line\n    parens = [0] * nrows\n    # relative indents of physical lines\n    rel_indent = [0] * nrows\n    # visual indents\n    indent_chances = {}\n    last_indent = tokens[0][2]\n    indent = [last_indent[1]]\n    if verbose >= 3:\n        print(\">>> \" + tokens[0][4].rstrip())\n\n    for token_type, text, start, end, line in tokens:\n\n        newline = row < start[0] - first_row\n        if newline:\n            row = start[0] - first_row\n            newline = (not last_token_multiline and\n                       token_type not in (tokenize.NL, tokenize.NEWLINE))\n\n        if newline:\n            # this is the beginning of a continuation line.\n            last_indent = start\n            if verbose >= 3:\n                print(\"... \" + line.rstrip())\n\n            # record the initial indent.\n            rel_indent[row] = expand_indent(line) - indent_level\n\n            if depth:\n                # a bracket expression in a continuation line.\n                # find the line that it was opened on\n                for open_row in range(row - 1, -1, -1):\n                    if parens[open_row]:\n                        break\n            else:\n                # an unbracketed continuation line (ie, backslash)\n                open_row = 0\n            hang = rel_indent[row] - rel_indent[open_row]\n            close_bracket = (token_type == tokenize.OP and text in ']})')\n            visual_indent = (not close_bracket and hang > 0 and\n                             indent_chances.get(start[1]))\n\n            if close_bracket and indent[depth]:\n                # closing bracket for visual indent\n                if start[1] != indent[depth]:\n                    yield (start, \"E124 closing bracket does not match \"\n                           \"visual indentation\")\n            elif close_bracket and not hang:\n                # closing bracket matches indentation of opening bracket's line\n                if hang_closing:\n                    yield start, \"E133 closing bracket is missing indentation\"\n            elif visual_indent is True:\n                # visual indent is verified\n                if not indent[depth]:\n                    indent[depth] = start[1]\n            elif visual_indent in (text, str):\n                # ignore token lined up with matching one from a previous line\n                pass\n            elif indent[depth] and start[1] < indent[depth]:\n                # visual indent is broken\n                yield (start, \"E128 continuation line \"\n                       \"under-indented for visual indent\")\n            elif hang == 4 or (indent_next and rel_indent[row] == 8):\n                # hanging indent is verified\n                if close_bracket and not hang_closing:\n                    yield (start, \"E123 closing bracket does not match \"\n                           \"indentation of opening bracket's line\")\n            else:\n                # indent is broken\n                if hang <= 0:\n                    error = \"E122\", \"missing indentation or outdented\"\n                elif indent[depth]:\n                    error = \"E127\", \"over-indented for visual indent\"\n                elif hang % 4:\n                    error = \"E121\", \"indentation is not a multiple of four\"\n                else:\n                    error = \"E126\", \"over-indented for hanging indent\"\n                yield start, \"%s continuation line %s\" % error\n\n        # look for visual indenting\n        if (parens[row] and token_type not in (tokenize.NL, tokenize.COMMENT)\n                and not indent[depth]):\n            indent[depth] = start[1]\n            indent_chances[start[1]] = True\n            if verbose >= 4:\n                print(\"bracket depth %s indent to %s\" % (depth, start[1]))\n        # deal with implicit string concatenation\n        elif (token_type in (tokenize.STRING, tokenize.COMMENT) or\n              text in ('u', 'ur', 'b', 'br')):\n            indent_chances[start[1]] = str\n        # special case for the \"if\" statement because len(\"if (\") == 4\n        elif not indent_chances and not row and not depth and text == 'if':\n            indent_chances[end[1] + 1] = True\n\n        # keep track of bracket depth\n        if token_type == tokenize.OP:\n            if text in '([{':\n                depth += 1\n                indent.append(0)\n                parens[row] += 1\n                if verbose >= 4:\n                    print(\"bracket depth %s seen, col %s, visual min = %s\" %\n                          (depth, start[1], indent[depth]))\n            elif text in ')]}' and depth > 0:\n                # parent indents should not be more than this one\n                prev_indent = indent.pop() or last_indent[1]\n                for d in range(depth):\n                    if indent[d] > prev_indent:\n                        indent[d] = 0\n                for ind in list(indent_chances):\n                    if ind >= prev_indent:\n                        del indent_chances[ind]\n                depth -= 1\n                if depth:\n                    indent_chances[indent[depth]] = True\n                for idx in range(row, -1, -1):\n                    if parens[idx]:\n                        parens[idx] -= 1\n                        rel_indent[row] = rel_indent[idx]\n                        break\n            assert len(indent) == depth + 1\n            if start[1] not in indent_chances:\n                # allow to line up tokens\n                indent_chances[start[1]] = text\n\n        last_token_multiline = (start[0] != end[0])\n\n    if indent_next and expand_indent(line) == indent_level + 4:\n        yield (last_indent, \"E125 continuation line does not distinguish \"\n               \"itself from next logical line\")\n\n\ndef whitespace_before_parameters(logical_line, tokens):\n    \"\"\"\n    Avoid extraneous whitespace in the following situations:\n\n    - Immediately before the open parenthesis that starts the argument\n      list of a function call.\n\n    - Immediately before the open parenthesis that starts an indexing or\n      slicing.\n\n    Okay: spam(1)\n    E211: spam (1)\n\n    Okay: dict['key'] = list[index]\n    E211: dict ['key'] = list[index]\n    E211: dict['key'] = list [index]\n    \"\"\"\n    prev_type, prev_text, __, prev_end, __ = tokens[0]\n    for index in range(1, len(tokens)):\n        token_type, text, start, end, __ = tokens[index]\n        if (token_type == tokenize.OP and\n            text in '([' and\n            start != prev_end and\n            (prev_type == tokenize.NAME or prev_text in '}])') and\n            # Syntax \"class A (B):\" is allowed, but avoid it\n            (index < 2 or tokens[index - 2][1] != 'class') and\n                # Allow \"return (a.foo for a in range(5))\"\n                not keyword.iskeyword(prev_text)):\n            yield prev_end, \"E211 whitespace before '%s'\" % text\n        prev_type = token_type\n        prev_text = text\n        prev_end = end\n\n\ndef whitespace_around_operator(logical_line):\n    r\"\"\"\n    Avoid extraneous whitespace in the following situations:\n\n    - More than one space around an assignment (or other) operator to\n      align it with another.\n\n    Okay: a = 12 + 3\n    E221: a = 4  + 5\n    E222: a = 4 +  5\n    E223: a = 4\\t+ 5\n    E224: a = 4 +\\t5\n    \"\"\"\n    for match in OPERATOR_REGEX.finditer(logical_line):\n        before, after = match.groups()\n\n        if '\\t' in before:\n            yield match.start(1), \"E223 tab before operator\"\n        elif len(before) > 1:\n            yield match.start(1), \"E221 multiple spaces before operator\"\n\n        if '\\t' in after:\n            yield match.start(2), \"E224 tab after operator\"\n        elif len(after) > 1:\n            yield match.start(2), \"E222 multiple spaces after operator\"\n\n\ndef missing_whitespace_around_operator(logical_line, tokens):\n    r\"\"\"\n    - Always surround these binary operators with a single space on\n      either side: assignment (=), augmented assignment (+=, -= etc.),\n      comparisons (==, <, >, !=, <>, <=, >=, in, not in, is, is not),\n      Booleans (and, or, not).\n\n    - Use spaces around arithmetic operators.\n\n    Okay: i = i + 1\n    Okay: submitted += 1\n    Okay: x = x * 2 - 1\n    Okay: hypot2 = x * x + y * y\n    Okay: c = (a + b) * (a - b)\n    Okay: foo(bar, key='word', *args, **kwargs)\n    Okay: alpha[:-i]\n\n    E225: i=i+1\n    E225: submitted +=1\n    E225: x = x /2 - 1\n    E225: z = x **y\n    E226: c = (a+b) * (a-b)\n    E226: hypot2 = x*x + y*y\n    E227: c = a|b\n    E228: msg = fmt%(errno, errmsg)\n    \"\"\"\n    parens = 0\n    need_space = False\n    prev_type = tokenize.OP\n    prev_text = prev_end = None\n    for token_type, text, start, end, line in tokens:\n        if token_type in (tokenize.NL, tokenize.NEWLINE, tokenize.ERRORTOKEN):\n            # ERRORTOKEN is triggered by backticks in Python 3\n            continue\n        if text in ('(', 'lambda'):\n            parens += 1\n        elif text == ')':\n            parens -= 1\n        if need_space:\n            if start != prev_end:\n                # Found a (probably) needed space\n                if need_space is not True and not need_space[1]:\n                    yield (need_space[0],\n                           \"E225 missing whitespace around operator\")\n                need_space = False\n            elif text == '>' and prev_text in ('<', '-'):\n                # Tolerate the \"<>\" operator, even if running Python 3\n                # Deal with Python 3's annotated return value \"->\"\n                pass\n            else:\n                if need_space is True or need_space[1]:\n                    # A needed trailing space was not found\n                    yield prev_end, \"E225 missing whitespace around operator\"\n                else:\n                    code, optype = 'E226', 'arithmetic'\n                    if prev_text == '%':\n                        code, optype = 'E228', 'modulo'\n                    elif prev_text not in ARITHMETIC_OP:\n                        code, optype = 'E227', 'bitwise or shift'\n                    yield (need_space[0], \"%s missing whitespace \"\n                           \"around %s operator\" % (code, optype))\n                need_space = False\n        elif token_type == tokenize.OP and prev_end is not None:\n            if text == '=' and parens:\n                # Allow keyword args or defaults: foo(bar=None).\n                pass\n            elif text in WS_NEEDED_OPERATORS:\n                need_space = True\n            elif text in UNARY_OPERATORS:\n                # Check if the operator is being used as a binary operator\n                # Allow unary operators: -123, -x, +1.\n                # Allow argument unpacking: foo(*args, **kwargs).\n                if prev_type == tokenize.OP:\n                    binary_usage = (prev_text in '}])')\n                elif prev_type == tokenize.NAME:\n                    binary_usage = (prev_text not in KEYWORDS)\n                else:\n                    binary_usage = (prev_type not in SKIP_TOKENS)\n\n                if binary_usage:\n                    need_space = None\n            elif text in WS_OPTIONAL_OPERATORS:\n                need_space = None\n\n            if need_space is None:\n                # Surrounding space is optional, but ensure that\n                # trailing space matches opening space\n                need_space = (prev_end, start != prev_end)\n            elif need_space and start == prev_end:\n                # A needed opening space was not found\n                yield prev_end, \"E225 missing whitespace around operator\"\n                need_space = False\n        prev_type = token_type\n        prev_text = text\n        prev_end = end\n\n\ndef whitespace_around_comma(logical_line):\n    r\"\"\"\n    Avoid extraneous whitespace in the following situations:\n\n    - More than one space around an assignment (or other) operator to\n      align it with another.\n\n    Note: these checks are disabled by default\n\n    Okay: a = (1, 2)\n    E241: a = (1,  2)\n    E242: a = (1,\\t2)\n    \"\"\"\n    line = logical_line\n    for m in WHITESPACE_AFTER_COMMA_REGEX.finditer(line):\n        found = m.start() + 1\n        if '\\t' in m.group():\n            yield found, \"E242 tab after '%s'\" % m.group()[0]\n        else:\n            yield found, \"E241 multiple spaces after '%s'\" % m.group()[0]\n\n\ndef whitespace_around_named_parameter_equals(logical_line, tokens):\n    \"\"\"\n    Don't use spaces around the '=' sign when used to indicate a\n    keyword argument or a default parameter value.\n\n    Okay: def complex(real, imag=0.0):\n    Okay: return magic(r=real, i=imag)\n    Okay: boolean(a == b)\n    Okay: boolean(a != b)\n    Okay: boolean(a <= b)\n    Okay: boolean(a >= b)\n\n    E251: def complex(real, imag = 0.0):\n    E251: return magic(r = real, i = imag)\n    \"\"\"\n    parens = 0\n    no_space = False\n    prev_end = None\n    message = \"E251 unexpected spaces around keyword / parameter equals\"\n    for token_type, text, start, end, line in tokens:\n        if no_space:\n            no_space = False\n            if start != prev_end:\n                yield (prev_end, message)\n        elif token_type == tokenize.OP:\n            if text == '(':\n                parens += 1\n            elif text == ')':\n                parens -= 1\n            elif parens and text == '=':\n                no_space = True\n                if start != prev_end:\n                    yield (prev_end, message)\n        prev_end = end\n\n\ndef whitespace_before_inline_comment(logical_line, tokens):\n    \"\"\"\n    Separate inline comments by at least two spaces.\n\n    An inline comment is a comment on the same line as a statement.  Inline\n    comments should be separated by at least two spaces from the statement.\n    They should start with a # and a single space.\n\n    Okay: x = x + 1  # Increment x\n    Okay: x = x + 1    # Increment x\n    E261: x = x + 1 # Increment x\n    E262: x = x + 1  #Increment x\n    E262: x = x + 1  #  Increment x\n    \"\"\"\n    prev_end = (0, 0)\n    for token_type, text, start, end, line in tokens:\n        if token_type == tokenize.COMMENT:\n            if not line[:start[1]].strip():\n                continue\n            if prev_end[0] == start[0] and start[1] < prev_end[1] + 2:\n                yield (prev_end,\n                       \"E261 at least two spaces before inline comment\")\n            symbol, sp, comment = text.partition(' ')\n            if symbol not in ('#', '#:') or comment[:1].isspace():\n                yield start, \"E262 inline comment should start with '# '\"\n        elif token_type != tokenize.NL:\n            prev_end = end\n\n\ndef imports_on_separate_lines(logical_line):\n    r\"\"\"\n    Imports should usually be on separate lines.\n\n    Okay: import os\\nimport sys\n    E401: import sys, os\n\n    Okay: from subprocess import Popen, PIPE\n    Okay: from myclas import MyClass\n    Okay: from foo.bar.yourclass import YourClass\n    Okay: import myclass\n    Okay: import foo.bar.yourclass\n    \"\"\"\n    line = logical_line\n    if line.startswith('import '):\n        found = line.find(',')\n        if -1 < found and ';' not in line[:found]:\n            yield found, \"E401 multiple imports on one line\"\n\n\ndef compound_statements(logical_line):\n    r\"\"\"\n    Compound statements (multiple statements on the same line) are\n    generally discouraged.\n\n    While sometimes it's okay to put an if/for/while with a small body\n    on the same line, never do this for multi-clause statements. Also\n    avoid folding such long lines!\n\n    Okay: if foo == 'blah':\\n    do_blah_thing()\n    Okay: do_one()\n    Okay: do_two()\n    Okay: do_three()\n\n    E701: if foo == 'blah': do_blah_thing()\n    E701: for x in lst: total += x\n    E701: while t < 10: t = delay()\n    E701: if foo == 'blah': do_blah_thing()\n    E701: else: do_non_blah_thing()\n    E701: try: something()\n    E701: finally: cleanup()\n    E701: if foo == 'blah': one(); two(); three()\n\n    E702: do_one(); do_two(); do_three()\n    E703: do_four();  # useless semicolon\n    \"\"\"\n    line = logical_line\n    last_char = len(line) - 1\n    found = line.find(':')\n    while -1 < found < last_char:\n        before = line[:found]\n        if (before.count('{') <= before.count('}') and  # {'a': 1} (dict)\n            before.count('[') <= before.count(']') and  # [1:2] (slice)\n            before.count('(') <= before.count(')') and  # (Python 3 annotation)\n                not LAMBDA_REGEX.search(before)):       # lambda x: x\n            yield found, \"E701 multiple statements on one line (colon)\"\n        found = line.find(':', found + 1)\n    found = line.find(';')\n    while -1 < found:\n        if found < last_char:\n            yield found, \"E702 multiple statements on one line (semicolon)\"\n        else:\n            yield found, \"E703 statement ends with a semicolon\"\n        found = line.find(';', found + 1)\n\n\ndef explicit_line_join(logical_line, tokens):\n    r\"\"\"\n    Avoid explicit line join between brackets.\n\n    The preferred way of wrapping long lines is by using Python's implied line\n    continuation inside parentheses, brackets and braces.  Long lines can be\n    broken over multiple lines by wrapping expressions in parentheses.  These\n    should be used in preference to using a backslash for line continuation.\n\n    E502: aaa = [123, \\\\n       123]\n    E502: aaa = (\"bbb \" \\\\n       \"ccc\")\n\n    Okay: aaa = [123,\\n       123]\n    Okay: aaa = (\"bbb \"\\n       \"ccc\")\n    Okay: aaa = \"bbb \" \\\\n    \"ccc\"\n    \"\"\"\n    prev_start = prev_end = parens = 0\n    for token_type, text, start, end, line in tokens:\n        if start[0] != prev_start and parens and backslash:\n            yield backslash, \"E502 the backslash is redundant between brackets\"\n        if end[0] != prev_end:\n            if line.rstrip('\\r\\n').endswith('\\\\'):\n                backslash = (end[0], len(line.splitlines()[-1]) - 1)\n            else:\n                backslash = None\n            prev_start = prev_end = end[0]\n        else:\n            prev_start = start[0]\n        if token_type == tokenize.OP:\n            if text in '([{':\n                parens += 1\n            elif text in ')]}':\n                parens -= 1\n\n\ndef comparison_to_singleton(logical_line, noqa):\n    \"\"\"\n    Comparisons to singletons like None should always be done\n    with \"is\" or \"is not\", never the equality operators.\n\n    Okay: if arg is not None:\n    E711: if arg != None:\n    E712: if arg == True:\n\n    Also, beware of writing if x when you really mean if x is not None --\n    e.g. when testing whether a variable or argument that defaults to None was\n    set to some other value.  The other value might have a type (such as a\n    container) that could be false in a boolean context!\n    \"\"\"\n    match = not noqa and COMPARE_SINGLETON_REGEX.search(logical_line)\n    if match:\n        same = (match.group(1) == '==')\n        singleton = match.group(2)\n        msg = \"'if cond is %s:'\" % (('' if same else 'not ') + singleton)\n        if singleton in ('None',):\n            code = 'E711'\n        else:\n            code = 'E712'\n            nonzero = ((singleton == 'True' and same) or\n                       (singleton == 'False' and not same))\n            msg += \" or 'if %scond:'\" % ('' if nonzero else 'not ')\n        yield match.start(1), (\"%s comparison to %s should be %s\" %\n                               (code, singleton, msg))\n\n\ndef comparison_type(logical_line):\n    \"\"\"\n    Object type comparisons should always use isinstance() instead of\n    comparing types directly.\n\n    Okay: if isinstance(obj, int):\n    E721: if type(obj) is type(1):\n\n    When checking if an object is a string, keep in mind that it might be a\n    unicode string too! In Python 2.3, str and unicode have a common base\n    class, basestring, so you can do:\n\n    Okay: if isinstance(obj, basestring):\n    Okay: if type(a1) is type(b1):\n    \"\"\"\n    match = COMPARE_TYPE_REGEX.search(logical_line)\n    if match:\n        inst = match.group(1)\n        if inst and isidentifier(inst) and inst not in SINGLETONS:\n            return  # Allow comparison for types which are not obvious\n        yield match.start(), \"E721 do not compare types, use 'isinstance()'\"\n\n\ndef python_3000_has_key(logical_line):\n    r\"\"\"\n    The {}.has_key() method is removed in the Python 3.\n    Use the 'in' operation instead.\n\n    Okay: if \"alph\" in d:\\n    print d[\"alph\"]\n    W601: assert d.has_key('alph')\n    \"\"\"\n    pos = logical_line.find('.has_key(')\n    if pos > -1:\n        yield pos, \"W601 .has_key() is deprecated, use 'in'\"\n\n\ndef python_3000_raise_comma(logical_line):\n    \"\"\"\n    When raising an exception, use \"raise ValueError('message')\"\n    instead of the older form \"raise ValueError, 'message'\".\n\n    The paren-using form is preferred because when the exception arguments\n    are long or include string formatting, you don't need to use line\n    continuation characters thanks to the containing parentheses.  The older\n    form is removed in Python 3.\n\n    Okay: raise DummyError(\"Message\")\n    W602: raise DummyError, \"Message\"\n    \"\"\"\n    match = RAISE_COMMA_REGEX.match(logical_line)\n    if match and not RERAISE_COMMA_REGEX.match(logical_line):\n        yield match.end() - 1, \"W602 deprecated form of raising exception\"\n\n\ndef python_3000_not_equal(logical_line):\n    \"\"\"\n    != can also be written <>, but this is an obsolete usage kept for\n    backwards compatibility only. New code should always use !=.\n    The older syntax is removed in Python 3.\n\n    Okay: if a != 'no':\n    W603: if a <> 'no':\n    \"\"\"\n    pos = logical_line.find('<>')\n    if pos > -1:\n        yield pos, \"W603 '<>' is deprecated, use '!='\"\n\n\ndef python_3000_backticks(logical_line):\n    \"\"\"\n    Backticks are removed in Python 3.\n    Use repr() instead.\n\n    Okay: val = repr(1 + 2)\n    W604: val = `1 + 2`\n    \"\"\"\n    pos = logical_line.find('`')\n    if pos > -1:\n        yield pos, \"W604 backticks are deprecated, use 'repr()'\"\n\n\n##############################################################################\n# Helper functions\n##############################################################################\n\n\nif '' == ''.encode():\n    # Python 2: implicit encoding.\n    def readlines(filename):\n        f = open(filename)\n        try:\n            return f.readlines()\n        finally:\n            f.close()\n    isidentifier = re.compile(r'[a-zA-Z_]\\w*').match\n    stdin_get_value = sys.stdin.read\nelse:\n    # Python 3\n    def readlines(filename):\n        f = open(filename, 'rb')\n        try:\n            coding, lines = tokenize.detect_encoding(f.readline)\n            f = TextIOWrapper(f, coding, line_buffering=True)\n            return [l.decode(coding) for l in lines] + f.readlines()\n        except (LookupError, SyntaxError, UnicodeError):\n            f.close()\n            # Fall back if files are improperly declared\n            f = open(filename, encoding='latin-1')\n            return f.readlines()\n        finally:\n            f.close()\n    isidentifier = str.isidentifier\n\n    def stdin_get_value():\n        return TextIOWrapper(sys.stdin.buffer, errors='ignore').read()\nreadlines.__doc__ = \"    Read the source code.\"\nnoqa = re.compile(r'# no(?:qa|pep8)\\b', re.I).search\n\n\ndef expand_indent(line):\n    r\"\"\"\n    Return the amount of indentation.\n    Tabs are expanded to the next multiple of 8.\n\n    >>> expand_indent('    ')\n    4\n    >>> expand_indent('\\t')\n    8\n    >>> expand_indent('    \\t')\n    8\n    >>> expand_indent('       \\t')\n    8\n    >>> expand_indent('        \\t')\n    16\n    \"\"\"\n    if '\\t' not in line:\n        return len(line) - len(line.lstrip())\n    result = 0\n    for char in line:\n        if char == '\\t':\n            result = result // 8 * 8 + 8\n        elif char == ' ':\n            result += 1\n        else:\n            break\n    return result\n\n\ndef mute_string(text):\n    \"\"\"\n    Replace contents with 'xxx' to prevent syntax matching.\n\n    >>> mute_string('\"abc\"')\n    '\"xxx\"'\n    >>> mute_string(\"'''abc'''\")\n    \"'''xxx'''\"\n    >>> mute_string(\"r'abc'\")\n    \"r'xxx'\"\n    \"\"\"\n    # String modifiers (e.g. u or r)\n    start = text.index(text[-1]) + 1\n    end = len(text) - 1\n    # Triple quotes\n    if text[-3:] in ('\"\"\"', \"'''\"):\n        start += 2\n        end -= 2\n    return text[:start] + 'x' * (end - start) + text[end:]\n\n\ndef parse_udiff(diff, patterns=None, parent='.'):\n    \"\"\"Return a dictionary of matching lines.\"\"\"\n    # For each file of the diff, the entry key is the filename,\n    # and the value is a set of row numbers to consider.\n    rv = {}\n    path = nrows = None\n    for line in diff.splitlines():\n        if nrows:\n            if line[:1] != '-':\n                nrows -= 1\n            continue\n        if line[:3] == '@@ ':\n            hunk_match = HUNK_REGEX.match(line)\n            row, nrows = [int(g or '1') for g in hunk_match.groups()]\n            rv[path].update(range(row, row + nrows))\n        elif line[:3] == '+++':\n            path = line[4:].split('\\t', 1)[0]\n            if path[:2] == 'b/':\n                path = path[2:]\n            rv[path] = set()\n    return dict([(os.path.join(parent, path), rows)\n                 for (path, rows) in rv.items()\n                 if rows and filename_match(path, patterns)])\n\n\ndef filename_match(filename, patterns, default=True):\n    \"\"\"\n    Check if patterns contains a pattern that matches filename.\n    If patterns is unspecified, this always returns True.\n    \"\"\"\n    if not patterns:\n        return default\n    return any(fnmatch(filename, pattern) for pattern in patterns)\n\n\n##############################################################################\n# Framework to run all checks\n##############################################################################\n\n\n_checks = {'physical_line': {}, 'logical_line': {}, 'tree': {}}\n\n\ndef register_check(check, codes=None):\n    \"\"\"\n    Register a new check object.\n    \"\"\"\n    def _add_check(check, kind, codes, args):\n        if check in _checks[kind]:\n            _checks[kind][check][0].extend(codes or [])\n        else:\n            _checks[kind][check] = (codes or [''], args)\n    if inspect.isfunction(check):\n        args = inspect.getargspec(check)[0]\n        if args and args[0] in ('physical_line', 'logical_line'):\n            if codes is None:\n                codes = ERRORCODE_REGEX.findall(check.__doc__ or '')\n            _add_check(check, args[0], codes, args)\n    elif inspect.isclass(check):\n        if inspect.getargspec(check.__init__)[0][:2] == ['self', 'tree']:\n            _add_check(check, 'tree', codes, None)\n\n\ndef init_checks_registry():\n    \"\"\"\n    Register all globally visible functions where the first argument name\n    is 'physical_line' or 'logical_line'.\n    \"\"\"\n    mod = inspect.getmodule(register_check)\n    for (name, function) in inspect.getmembers(mod, inspect.isfunction):\n        register_check(function)\ninit_checks_registry()\n\n\nclass Checker(object):\n    \"\"\"\n    Load a Python source file, tokenize it, check coding style.\n    \"\"\"\n\n    def __init__(self, filename=None, lines=None,\n                 options=None, report=None, **kwargs):\n        if options is None:\n            options = StyleGuide(kwargs).options\n        else:\n            assert not kwargs\n        self._io_error = None\n        self._physical_checks = options.physical_checks\n        self._logical_checks = options.logical_checks\n        self._ast_checks = options.ast_checks\n        self.max_line_length = options.max_line_length\n        self.hang_closing = options.hang_closing\n        self.verbose = options.verbose\n        self.filename = filename\n        if filename is None:\n            self.filename = 'stdin'\n            self.lines = lines or []\n        elif filename == '-':\n            self.filename = 'stdin'\n            self.lines = stdin_get_value().splitlines(True)\n        elif lines is None:\n            try:\n                self.lines = readlines(filename)\n            except IOError:\n                exc_type, exc = sys.exc_info()[:2]\n                self._io_error = '%s: %s' % (exc_type.__name__, exc)\n                self.lines = []\n        else:\n            self.lines = lines\n        if self.lines:\n            ord0 = ord(self.lines[0][0])\n            if ord0 in (0xef, 0xfeff):  # Strip the UTF-8 BOM\n                if ord0 == 0xfeff:\n                    self.lines[0] = self.lines[0][1:]\n                elif self.lines[0][:3] == '\\xef\\xbb\\xbf':\n                    self.lines[0] = self.lines[0][3:]\n        self.report = report or options.report\n        self.report_error = self.report.error\n\n    def report_invalid_syntax(self):\n        exc_type, exc = sys.exc_info()[:2]\n        if len(exc.args) > 1:\n            offset = exc.args[1]\n            if len(offset) > 2:\n                offset = offset[1:3]\n        else:\n            offset = (1, 0)\n        self.report_error(offset[0], offset[1] or 0,\n                          'E901 %s: %s' % (exc_type.__name__, exc.args[0]),\n                          self.report_invalid_syntax)\n    report_invalid_syntax.__doc__ = \"    Check if the syntax is valid.\"\n\n    def readline(self):\n        \"\"\"\n        Get the next line from the input buffer.\n        \"\"\"\n        self.line_number += 1\n        if self.line_number > len(self.lines):\n            return ''\n        return self.lines[self.line_number - 1]\n\n    def readline_check_physical(self):\n        \"\"\"\n        Check and return the next physical line. This method can be\n        used to feed tokenize.generate_tokens.\n        \"\"\"\n        line = self.readline()\n        if line:\n            self.check_physical(line)\n        return line\n\n    def run_check(self, check, argument_names):\n        \"\"\"\n        Run a check plugin.\n        \"\"\"\n        arguments = []\n        for name in argument_names:\n            arguments.append(getattr(self, name))\n        return check(*arguments)\n\n    def check_physical(self, line):\n        \"\"\"\n        Run all physical checks on a raw input line.\n        \"\"\"\n        self.physical_line = line\n        if self.indent_char is None and line[:1] in WHITESPACE:\n            self.indent_char = line[0]\n        for name, check, argument_names in self._physical_checks:\n            result = self.run_check(check, argument_names)\n            if result is not None:\n                offset, text = result\n                self.report_error(self.line_number, offset, text, check)\n\n    def build_tokens_line(self):\n        \"\"\"\n        Build a logical line from tokens.\n        \"\"\"\n        self.mapping = []\n        logical = []\n        comments = []\n        length = 0\n        previous = None\n        for token in self.tokens:\n            token_type, text = token[0:2]\n            if token_type == tokenize.COMMENT:\n                comments.append(text)\n                continue\n            if token_type in SKIP_TOKENS:\n                continue\n            if token_type == tokenize.STRING:\n                text = mute_string(text)\n            if previous:\n                end_row, end = previous[3]\n                start_row, start = token[2]\n                if end_row != start_row:    # different row\n                    prev_text = self.lines[end_row - 1][end - 1]\n                    if prev_text == ',' or (prev_text not in '{[('\n                                            and text not in '}])'):\n                        logical.append(' ')\n                        length += 1\n                elif end != start:  # different column\n                    fill = self.lines[end_row - 1][end:start]\n                    logical.append(fill)\n                    length += len(fill)\n            self.mapping.append((length, token))\n            logical.append(text)\n            length += len(text)\n            previous = token\n        self.logical_line = ''.join(logical)\n        self.noqa = comments and noqa(''.join(comments))\n        # With Python 2, if the line ends with '\\r\\r\\n' the assertion fails\n        # assert self.logical_line.strip() == self.logical_line\n\n    def check_logical(self):\n        \"\"\"\n        Build a line from tokens and run all logical checks on it.\n        \"\"\"\n        self.build_tokens_line()\n        self.report.increment_logical_line()\n        first_line = self.lines[self.mapping[0][1][2][0] - 1]\n        indent = first_line[:self.mapping[0][1][2][1]]\n        self.previous_indent_level = self.indent_level\n        self.indent_level = expand_indent(indent)\n        if self.verbose >= 2:\n            print(self.logical_line[:80].rstrip())\n        for name, check, argument_names in self._logical_checks:\n            if self.verbose >= 4:\n                print('   ' + name)\n            for result in self.run_check(check, argument_names):\n                offset, text = result\n                if isinstance(offset, tuple):\n                    orig_number, orig_offset = offset\n                else:\n                    for token_offset, token in self.mapping:\n                        if offset >= token_offset:\n                            orig_number = token[2][0]\n                            orig_offset = (token[2][1] + offset - token_offset)\n                self.report_error(orig_number, orig_offset, text, check)\n        self.previous_logical = self.logical_line\n\n    def check_ast(self):\n        try:\n            tree = compile(''.join(self.lines), '', 'exec', PyCF_ONLY_AST)\n        except (SyntaxError, TypeError):\n            return self.report_invalid_syntax()\n        for name, cls, _ in self._ast_checks:\n            checker = cls(tree, self.filename)\n            for lineno, offset, text, check in checker.run():\n                if not noqa(self.lines[lineno - 1]):\n                    self.report_error(lineno, offset, text, check)\n\n    def generate_tokens(self):\n        if self._io_error:\n            self.report_error(1, 0, 'E902 %s' % self._io_error, readlines)\n        tokengen = tokenize.generate_tokens(self.readline_check_physical)\n        try:\n            for token in tokengen:\n                yield token\n        except (SyntaxError, tokenize.TokenError):\n            self.report_invalid_syntax()\n\n    def check_all(self, expected=None, line_offset=0):\n        \"\"\"\n        Run all checks on the input file.\n        \"\"\"\n        self.report.init_file(self.filename, self.lines, expected, line_offset)\n        if self._ast_checks:\n            self.check_ast()\n        self.line_number = 0\n        self.indent_char = None\n        self.indent_level = 0\n        self.previous_logical = ''\n        self.tokens = []\n        self.blank_lines = blank_lines_before_comment = 0\n        parens = 0\n        for token in self.generate_tokens():\n            self.tokens.append(token)\n            token_type, text = token[0:2]\n            if self.verbose >= 3:\n                if token[2][0] == token[3][0]:\n                    pos = '[%s:%s]' % (token[2][1] or '', token[3][1])\n                else:\n                    pos = 'l.%s' % token[3][0]\n                print('l.%s\\t%s\\t%s\\t%r' %\n                      (token[2][0], pos, tokenize.tok_name[token[0]], text))\n            if token_type == tokenize.OP:\n                if text in '([{':\n                    parens += 1\n                elif text in '}])':\n                    parens -= 1\n            elif not parens:\n                if token_type == tokenize.NEWLINE:\n                    if self.blank_lines < blank_lines_before_comment:\n                        self.blank_lines = blank_lines_before_comment\n                    self.check_logical()\n                    self.tokens = []\n                    self.blank_lines = blank_lines_before_comment = 0\n                elif token_type == tokenize.NL:\n                    if len(self.tokens) == 1:\n                        # The physical line contains only this token.\n                        self.blank_lines += 1\n                    self.tokens = []\n                elif token_type == tokenize.COMMENT and len(self.tokens) == 1:\n                    if blank_lines_before_comment < self.blank_lines:\n                        blank_lines_before_comment = self.blank_lines\n                    self.blank_lines = 0\n                    if COMMENT_WITH_NL:\n                        # The comment also ends a physical line\n                        self.tokens = []\n        return self.report.get_file_results()\n\n\nclass BaseReport(object):\n    \"\"\"Collect the results of the checks.\"\"\"\n    print_filename = False\n\n    def __init__(self, options):\n        self._benchmark_keys = options.benchmark_keys\n        self._ignore_code = options.ignore_code\n        # Results\n        self.elapsed = 0\n        self.total_errors = 0\n        self.counters = dict.fromkeys(self._benchmark_keys, 0)\n        self.messages = {}\n\n    def start(self):\n        \"\"\"Start the timer.\"\"\"\n        self._start_time = time.time()\n\n    def stop(self):\n        \"\"\"Stop the timer.\"\"\"\n        self.elapsed = time.time() - self._start_time\n\n    def init_file(self, filename, lines, expected, line_offset):\n        \"\"\"Signal a new file.\"\"\"\n        self.filename = filename\n        self.lines = lines\n        self.expected = expected or ()\n        self.line_offset = line_offset\n        self.file_errors = 0\n        self.counters['files'] += 1\n        self.counters['physical lines'] += len(lines)\n\n    def increment_logical_line(self):\n        \"\"\"Signal a new logical line.\"\"\"\n        self.counters['logical lines'] += 1\n\n    def error(self, line_number, offset, text, check):\n        \"\"\"Report an error, according to options.\"\"\"\n        code = text[:4]\n        if self._ignore_code(code):\n            return\n        if code in self.counters:\n            self.counters[code] += 1\n        else:\n            self.counters[code] = 1\n            self.messages[code] = text[5:]\n        # Don't care about expected errors or warnings\n        if code in self.expected:\n            return\n        if self.print_filename and not self.file_errors:\n            print(self.filename)\n        self.file_errors += 1\n        self.total_errors += 1\n        return code\n\n    def get_file_results(self):\n        \"\"\"Return the count of errors and warnings for this file.\"\"\"\n        return self.file_errors\n\n    def get_count(self, prefix=''):\n        \"\"\"Return the total count of errors and warnings.\"\"\"\n        return sum([self.counters[key]\n                    for key in self.messages if key.startswith(prefix)])\n\n    def get_statistics(self, prefix=''):\n        \"\"\"\n        Get statistics for message codes that start with the prefix.\n\n        prefix='' matches all errors and warnings\n        prefix='E' matches all errors\n        prefix='W' matches all warnings\n        prefix='E4' matches all errors that have to do with imports\n        \"\"\"\n        return ['%-7s %s %s' % (self.counters[key], key, self.messages[key])\n                for key in sorted(self.messages) if key.startswith(prefix)]\n\n    def print_statistics(self, prefix=''):\n        \"\"\"Print overall statistics (number of errors and warnings).\"\"\"\n        for line in self.get_statistics(prefix):\n            print(line)\n\n    def print_benchmark(self):\n        \"\"\"Print benchmark numbers.\"\"\"\n        print('%-7.2f %s' % (self.elapsed, 'seconds elapsed'))\n        if self.elapsed:\n            for key in self._benchmark_keys:\n                print('%-7d %s per second (%d total)' %\n                      (self.counters[key] / self.elapsed, key,\n                       self.counters[key]))\n\n\nclass FileReport(BaseReport):\n    \"\"\"Collect the results of the checks and print only the filenames.\"\"\"\n    print_filename = True\n\n\nclass StandardReport(BaseReport):\n    \"\"\"Collect and print the results of the checks.\"\"\"\n\n    def __init__(self, options):\n        super(StandardReport, self).__init__(options)\n        self._fmt = REPORT_FORMAT.get(options.format.lower(),\n                                      options.format)\n        self._repeat = options.repeat\n        self._show_source = options.show_source\n        self._show_pep8 = options.show_pep8\n\n    def init_file(self, filename, lines, expected, line_offset):\n        \"\"\"Signal a new file.\"\"\"\n        self._deferred_print = []\n        return super(StandardReport, self).init_file(\n            filename, lines, expected, line_offset)\n\n    def error(self, line_number, offset, text, check):\n        \"\"\"Report an error, according to options.\"\"\"\n        code = super(StandardReport, self).error(line_number, offset,\n                                                 text, check)\n        if code and (self.counters[code] == 1 or self._repeat):\n            self._deferred_print.append(\n                (line_number, offset, code, text[5:], check.__doc__))\n        return code\n\n    def get_file_results(self):\n        \"\"\"Print the result and return the overall count for this file.\"\"\"\n        self._deferred_print.sort()\n        for line_number, offset, code, text, doc in self._deferred_print:\n            print(self._fmt % {\n                'path': self.filename,\n                'row': self.line_offset + line_number, 'col': offset + 1,\n                'code': code, 'text': text,\n            })\n            if self._show_source:\n                if line_number > len(self.lines):\n                    line = ''\n                else:\n                    line = self.lines[line_number - 1]\n                print(line.rstrip())\n                print(' ' * offset + '^')\n            if self._show_pep8 and doc:\n                print(doc.lstrip('\\n').rstrip())\n        return self.file_errors\n\n\nclass DiffReport(StandardReport):\n    \"\"\"Collect and print the results for the changed lines only.\"\"\"\n\n    def __init__(self, options):\n        super(DiffReport, self).__init__(options)\n        self._selected = options.selected_lines\n\n    def error(self, line_number, offset, text, check):\n        if line_number not in self._selected[self.filename]:\n            return\n        return super(DiffReport, self).error(line_number, offset, text, check)\n\n\nclass StyleGuide(object):\n    \"\"\"Initialize a PEP-8 instance with few options.\"\"\"\n\n    def __init__(self, *args, **kwargs):\n        # build options from the command line\n        self.checker_class = kwargs.pop('checker_class', Checker)\n        parse_argv = kwargs.pop('parse_argv', False)\n        config_file = kwargs.pop('config_file', None)\n        parser = kwargs.pop('parser', None)\n        options, self.paths = process_options(\n            parse_argv=parse_argv, config_file=config_file, parser=parser)\n        if args or kwargs:\n            # build options from dict\n            options_dict = dict(*args, **kwargs)\n            options.__dict__.update(options_dict)\n            if 'paths' in options_dict:\n                self.paths = options_dict['paths']\n\n        self.runner = self.input_file\n        self.options = options\n\n        if not options.reporter:\n            options.reporter = BaseReport if options.quiet else StandardReport\n\n        for index, value in enumerate(options.exclude):\n            options.exclude[index] = value.rstrip('/')\n        options.select = tuple(options.select or ())\n        if not (options.select or options.ignore or\n                options.testsuite or options.doctest) and DEFAULT_IGNORE:\n            # The default choice: ignore controversial checks\n            options.ignore = tuple(DEFAULT_IGNORE.split(','))\n        else:\n            # Ignore all checks which are not explicitly selected\n            options.ignore = ('',) if options.select else tuple(options.ignore)\n        options.benchmark_keys = BENCHMARK_KEYS[:]\n        options.ignore_code = self.ignore_code\n        options.physical_checks = self.get_checks('physical_line')\n        options.logical_checks = self.get_checks('logical_line')\n        options.ast_checks = self.get_checks('tree')\n        self.init_report()\n\n    def init_report(self, reporter=None):\n        \"\"\"Initialize the report instance.\"\"\"\n        self.options.report = (reporter or self.options.reporter)(self.options)\n        return self.options.report\n\n    def check_files(self, paths=None):\n        \"\"\"Run all checks on the paths.\"\"\"\n        if paths is None:\n            paths = self.paths\n        report = self.options.report\n        runner = self.runner\n        report.start()\n        try:\n            for path in paths:\n                if os.path.isdir(path):\n                    self.input_dir(path)\n                elif not self.excluded(path):\n                    runner(path)\n        except KeyboardInterrupt:\n            print('... stopped')\n        report.stop()\n        return report\n\n    def input_file(self, filename, lines=None, expected=None, line_offset=0):\n        \"\"\"Run all checks on a Python source file.\"\"\"\n        if self.options.verbose:\n            print('checking %s' % filename)\n        fchecker = self.checker_class(\n            filename, lines=lines, options=self.options)\n        return fchecker.check_all(expected=expected, line_offset=line_offset)\n\n    def input_dir(self, dirname):\n        \"\"\"Check all files in this directory and all subdirectories.\"\"\"\n        dirname = dirname.rstrip('/')\n        if self.excluded(dirname):\n            return 0\n        counters = self.options.report.counters\n        verbose = self.options.verbose\n        filepatterns = self.options.filename\n        runner = self.runner\n        for root, dirs, files in os.walk(dirname):\n            if verbose:\n                print('directory ' + root)\n            counters['directories'] += 1\n            for subdir in sorted(dirs):\n                if self.excluded(subdir, root):\n                    dirs.remove(subdir)\n            for filename in sorted(files):\n                # contain a pattern that matches?\n                if ((filename_match(filename, filepatterns) and\n                     not self.excluded(filename, root))):\n                    runner(os.path.join(root, filename))\n\n    def excluded(self, filename, parent=None):\n        \"\"\"\n        Check if options.exclude contains a pattern that matches filename.\n        \"\"\"\n        if not self.options.exclude:\n            return False\n        basename = os.path.basename(filename)\n        if filename_match(basename, self.options.exclude):\n            return True\n        if parent:\n            filename = os.path.join(parent, filename)\n        return filename_match(filename, self.options.exclude)\n\n    def ignore_code(self, code):\n        \"\"\"\n        Check if the error code should be ignored.\n\n        If 'options.select' contains a prefix of the error code,\n        return False.  Else, if 'options.ignore' contains a prefix of\n        the error code, return True.\n        \"\"\"\n        return (code.startswith(self.options.ignore) and\n                not code.startswith(self.options.select))\n\n    def get_checks(self, argument_name):\n        \"\"\"\n        Find all globally visible functions where the first argument name\n        starts with argument_name and which contain selected tests.\n        \"\"\"\n        checks = []\n        for check, attrs in _checks[argument_name].items():\n            (codes, args) = attrs\n            if any(not (code and self.ignore_code(code)) for code in codes):\n                checks.append((check.__name__, check, args))\n        return sorted(checks)\n\n\ndef get_parser(prog='pep8', version=__version__):\n    parser = OptionParser(prog=prog, version=version,\n                          usage=\"%prog [options] input ...\")\n    parser.config_options = [\n        'exclude', 'filename', 'select', 'ignore', 'max-line-length',\n        'hang-closing', 'count', 'format', 'quiet', 'show-pep8',\n        'show-source', 'statistics', 'verbose']\n    parser.add_option('-v', '--verbose', default=0, action='count',\n                      help=\"print status messages, or debug with -vv\")\n    parser.add_option('-q', '--quiet', default=0, action='count',\n                      help=\"report only file names, or nothing with -qq\")\n    parser.add_option('-r', '--repeat', default=True, action='store_true',\n                      help=\"(obsolete) show all occurrences of the same error\")\n    parser.add_option('--first', action='store_false', dest='repeat',\n                      help=\"show first occurrence of each error\")\n    parser.add_option('--exclude', metavar='patterns', default=DEFAULT_EXCLUDE,\n                      help=\"exclude files or directories which match these \"\n                           \"comma separated patterns (default: %default)\")\n    parser.add_option('--filename', metavar='patterns', default='*.py',\n                      help=\"when parsing directories, only check filenames \"\n                           \"matching these comma separated patterns \"\n                           \"(default: %default)\")\n    parser.add_option('--select', metavar='errors', default='',\n                      help=\"select errors and warnings (e.g. E,W6)\")\n    parser.add_option('--ignore', metavar='errors', default='',\n                      help=\"skip errors and warnings (e.g. E4,W)\")\n    parser.add_option('--show-source', action='store_true',\n                      help=\"show source code for each error\")\n    parser.add_option('--show-pep8', action='store_true',\n                      help=\"show text of PEP 8 for each error \"\n                           \"(implies --first)\")\n    parser.add_option('--statistics', action='store_true',\n                      help=\"count errors and warnings\")\n    parser.add_option('--count', action='store_true',\n                      help=\"print total number of errors and warnings \"\n                           \"to standard error and set exit code to 1 if \"\n                           \"total is not null\")\n    parser.add_option('--max-line-length', type='int', metavar='n',\n                      default=MAX_LINE_LENGTH,\n                      help=\"set maximum allowed line length \"\n                           \"(default: %default)\")\n    parser.add_option('--hang-closing', action='store_true',\n                      help=\"hang closing bracket instead of matching \"\n                           \"indentation of opening bracket's line\")\n    parser.add_option('--format', metavar='format', default='default',\n                      help=\"set the error format [default|pylint|<custom>]\")\n    parser.add_option('--diff', action='store_true',\n                      help=\"report only lines changed according to the \"\n                           \"unified diff received on STDIN\")\n    group = parser.add_option_group(\"Testing Options\")\n    if os.path.exists(TESTSUITE_PATH):\n        group.add_option('--testsuite', metavar='dir',\n                         help=\"run regression tests from dir\")\n        group.add_option('--doctest', action='store_true',\n                         help=\"run doctest on myself\")\n    group.add_option('--benchmark', action='store_true',\n                     help=\"measure processing speed\")\n    return parser\n\n\ndef read_config(options, args, arglist, parser):\n    \"\"\"Read both user configuration and local configuration.\"\"\"\n    config = RawConfigParser()\n\n    user_conf = options.config\n    if user_conf and os.path.isfile(user_conf):\n        if options.verbose:\n            print('user configuration: %s' % user_conf)\n        config.read(user_conf)\n\n    parent = tail = args and os.path.abspath(os.path.commonprefix(args))\n    while tail:\n        if config.read([os.path.join(parent, fn) for fn in PROJECT_CONFIG]):\n            if options.verbose:\n                print('local configuration: in %s' % parent)\n            break\n        parent, tail = os.path.split(parent)\n\n    pep8_section = parser.prog\n    if config.has_section(pep8_section):\n        option_list = dict([(o.dest, o.type or o.action)\n                            for o in parser.option_list])\n\n        # First, read the default values\n        new_options, _ = parser.parse_args([])\n\n        # Second, parse the configuration\n        for opt in config.options(pep8_section):\n            if options.verbose > 1:\n                print(\"  %s = %s\" % (opt, config.get(pep8_section, opt)))\n            if opt.replace('_', '-') not in parser.config_options:\n                print(\"Unknown option: '%s'\\n  not in [%s]\" %\n                      (opt, ' '.join(parser.config_options)))\n                sys.exit(1)\n            normalized_opt = opt.replace('-', '_')\n            opt_type = option_list[normalized_opt]\n            if opt_type in ('int', 'count'):\n                value = config.getint(pep8_section, opt)\n            elif opt_type == 'string':\n                value = config.get(pep8_section, opt)\n            else:\n                assert opt_type in ('store_true', 'store_false')\n                value = config.getboolean(pep8_section, opt)\n            setattr(new_options, normalized_opt, value)\n\n        # Third, overwrite with the command-line options\n        options, _ = parser.parse_args(arglist, values=new_options)\n    options.doctest = options.testsuite = False\n    return options\n\n\ndef process_options(arglist=None, parse_argv=False, config_file=None,\n                    parser=None):\n    \"\"\"Process options passed either via arglist or via command line args.\"\"\"\n    if not arglist and not parse_argv:\n        # Don't read the command line if the module is used as a library.\n        arglist = []\n    if not parser:\n        parser = get_parser()\n    if not parser.has_option('--config'):\n        if config_file is True:\n            config_file = DEFAULT_CONFIG\n        group = parser.add_option_group(\"Configuration\", description=(\n            \"The project options are read from the [%s] section of the \"\n            \"tox.ini file or the setup.cfg file located in any parent folder \"\n            \"of the path(s) being processed.  Allowed options are: %s.\" %\n            (parser.prog, ', '.join(parser.config_options))))\n        group.add_option('--config', metavar='path', default=config_file,\n                         help=\"user config file location (default: %default)\")\n    options, args = parser.parse_args(arglist)\n    options.reporter = None\n\n    if options.ensure_value('testsuite', False):\n        args.append(options.testsuite)\n    elif not options.ensure_value('doctest', False):\n        if parse_argv and not args:\n            if options.diff or any(os.path.exists(name)\n                                   for name in PROJECT_CONFIG):\n                args = ['.']\n            else:\n                parser.error('input not specified')\n        options = read_config(options, args, arglist, parser)\n        options.reporter = parse_argv and options.quiet == 1 and FileReport\n\n    options.filename = options.filename and options.filename.split(',')\n    options.exclude = options.exclude.split(',')\n    options.select = options.select and options.select.split(',')\n    options.ignore = options.ignore and options.ignore.split(',')\n\n    if options.diff:\n        options.reporter = DiffReport\n        stdin = stdin_get_value()\n        options.selected_lines = parse_udiff(stdin, options.filename, args[0])\n        args = sorted(options.selected_lines)\n\n    return options, args\n\n\ndef _main():\n    \"\"\"Parse options and run checks on Python source.\"\"\"\n    pep8style = StyleGuide(parse_argv=True, config_file=True)\n    options = pep8style.options\n    if options.doctest or options.testsuite:\n        from testsuite.support import run_tests\n        report = run_tests(pep8style)\n    else:\n        report = pep8style.check_files()\n    if options.statistics:\n        report.print_statistics()\n    if options.benchmark:\n        report.print_benchmark()\n    if options.testsuite and not options.quiet:\n        report.print_results()\n    if report.total_errors:\n        if options.count:\n            sys.stderr.write(str(report.total_errors) + '\\n')\n        sys.exit(1)\n\nif __name__ == '__main__':\n    _main()\n"
  },
  {
    "path": "sublimelinter/modules/libs/pyflakes/__init__.py",
    "content": "\n__version__ = '0.8.1'\n"
  },
  {
    "path": "sublimelinter/modules/libs/pyflakes/__main__.py",
    "content": "from pyflakes.api import main\n\n# python -m pyflakes (with Python >= 2.7)\nif __name__ == '__main__':\n    main(prog='pyflakes')\n"
  },
  {
    "path": "sublimelinter/modules/libs/pyflakes/api.py",
    "content": "\"\"\"\nAPI for the command-line I{pyflakes} tool.\n\"\"\"\nfrom __future__ import with_statement\n\nimport sys\nimport os\nimport _ast\nfrom optparse import OptionParser\n\nfrom pyflakes import checker, __version__\nfrom pyflakes import reporter as modReporter\n\n__all__ = ['check', 'checkPath', 'checkRecursive', 'iterSourceCode', 'main']\n\n\ndef check(codeString, filename, reporter=None):\n    \"\"\"\n    Check the Python source given by C{codeString} for flakes.\n\n    @param codeString: The Python source to check.\n    @type codeString: C{str}\n\n    @param filename: The name of the file the source came from, used to report\n        errors.\n    @type filename: C{str}\n\n    @param reporter: A L{Reporter} instance, where errors and warnings will be\n        reported.\n\n    @return: The number of warnings emitted.\n    @rtype: C{int}\n    \"\"\"\n    if reporter is None:\n        reporter = modReporter._makeDefaultReporter()\n    # First, compile into an AST and handle syntax errors.\n    try:\n        tree = compile(codeString, filename, \"exec\", _ast.PyCF_ONLY_AST)\n    except SyntaxError:\n        value = sys.exc_info()[1]\n        msg = value.args[0]\n\n        (lineno, offset, text) = value.lineno, value.offset, value.text\n\n        # If there's an encoding problem with the file, the text is None.\n        if text is None:\n            # Avoid using msg, since for the only known case, it contains a\n            # bogus message that claims the encoding the file declared was\n            # unknown.\n            reporter.unexpectedError(filename, 'problem decoding source')\n        else:\n            reporter.syntaxError(filename, msg, lineno, offset, text)\n        return 1\n    except Exception:\n        reporter.unexpectedError(filename, 'problem decoding source')\n        return 1\n    # Okay, it's syntactically valid.  Now check it.\n    w = checker.Checker(tree, filename)\n    w.messages.sort(key=lambda m: m.lineno)\n    for warning in w.messages:\n        reporter.flake(warning)\n    return len(w.messages)\n\n\ndef checkPath(filename, reporter=None):\n    \"\"\"\n    Check the given path, printing out any warnings detected.\n\n    @param reporter: A L{Reporter} instance, where errors and warnings will be\n        reported.\n\n    @return: the number of warnings printed\n    \"\"\"\n    if reporter is None:\n        reporter = modReporter._makeDefaultReporter()\n    try:\n        with open(filename, 'rb') as f:\n            codestr = f.read()\n        if sys.version_info < (2, 7):\n            codestr += '\\n'     # Work around for Python <= 2.6\n    except UnicodeError:\n        reporter.unexpectedError(filename, 'problem decoding source')\n        return 1\n    except IOError:\n        msg = sys.exc_info()[1]\n        reporter.unexpectedError(filename, msg.args[1])\n        return 1\n    return check(codestr, filename, reporter)\n\n\ndef iterSourceCode(paths):\n    \"\"\"\n    Iterate over all Python source files in C{paths}.\n\n    @param paths: A list of paths.  Directories will be recursed into and\n        any .py files found will be yielded.  Any non-directories will be\n        yielded as-is.\n    \"\"\"\n    for path in paths:\n        if os.path.isdir(path):\n            for dirpath, dirnames, filenames in os.walk(path):\n                for filename in filenames:\n                    if filename.endswith('.py'):\n                        yield os.path.join(dirpath, filename)\n        else:\n            yield path\n\n\ndef checkRecursive(paths, reporter):\n    \"\"\"\n    Recursively check all source files in C{paths}.\n\n    @param paths: A list of paths to Python source files and directories\n        containing Python source files.\n    @param reporter: A L{Reporter} where all of the warnings and errors\n        will be reported to.\n    @return: The number of warnings found.\n    \"\"\"\n    warnings = 0\n    for sourcePath in iterSourceCode(paths):\n        warnings += checkPath(sourcePath, reporter)\n    return warnings\n\n\ndef main(prog=None):\n    parser = OptionParser(prog=prog, version=__version__)\n    (__, args) = parser.parse_args()\n    reporter = modReporter._makeDefaultReporter()\n    if args:\n        warnings = checkRecursive(args, reporter)\n    else:\n        warnings = check(sys.stdin.read(), '<stdin>', reporter)\n    raise SystemExit(warnings > 0)\n"
  },
  {
    "path": "sublimelinter/modules/libs/pyflakes/checker.py",
    "content": "\"\"\"\nMain module.\n\nImplement the central Checker class.\nAlso, it models the Bindings and Scopes.\n\"\"\"\nimport doctest\nimport os\nimport sys\n\nPY2 = sys.version_info < (3, 0)\nPY32 = sys.version_info < (3, 3)    # Python 2.5 to 3.2\nPY33 = sys.version_info < (3, 4)    # Python 2.5 to 3.3\nbuiltin_vars = dir(__import__('__builtin__' if PY2 else 'builtins'))\n\ntry:\n    import ast\nexcept ImportError:     # Python 2.5\n    import _ast as ast\n\n    if 'decorator_list' not in ast.ClassDef._fields:\n        # Patch the missing attribute 'decorator_list'\n        ast.ClassDef.decorator_list = ()\n        ast.FunctionDef.decorator_list = property(lambda s: s.decorators)\n\nfrom pyflakes import messages\n\n\nif PY2:\n    def getNodeType(node_class):\n        # workaround str.upper() which is locale-dependent\n        return str(unicode(node_class.__name__).upper())\nelse:\n    def getNodeType(node_class):\n        return node_class.__name__.upper()\n\n# Python >= 3.3 uses ast.Try instead of (ast.TryExcept + ast.TryFinally)\nif PY32:\n    def getAlternatives(n):\n        if isinstance(n, (ast.If, ast.TryFinally)):\n            return [n.body]\n        if isinstance(n, ast.TryExcept):\n            return [n.body + n.orelse] + [[hdl] for hdl in n.handlers]\nelse:\n    def getAlternatives(n):\n        if isinstance(n, ast.If):\n            return [n.body]\n        if isinstance(n, ast.Try):\n            return [n.body + n.orelse] + [[hdl] for hdl in n.handlers]\n\n\nclass _FieldsOrder(dict):\n    \"\"\"Fix order of AST node fields.\"\"\"\n\n    def _get_fields(self, node_class):\n        # handle iter before target, and generators before element\n        fields = node_class._fields\n        if 'iter' in fields:\n            key_first = 'iter'.find\n        elif 'generators' in fields:\n            key_first = 'generators'.find\n        else:\n            key_first = 'value'.find\n        return tuple(sorted(fields, key=key_first, reverse=True))\n\n    def __missing__(self, node_class):\n        self[node_class] = fields = self._get_fields(node_class)\n        return fields\n\n\ndef iter_child_nodes(node, omit=None, _fields_order=_FieldsOrder()):\n    \"\"\"\n    Yield all direct child nodes of *node*, that is, all fields that\n    are nodes and all items of fields that are lists of nodes.\n    \"\"\"\n    for name in _fields_order[node.__class__]:\n        if name == omit:\n            continue\n        field = getattr(node, name, None)\n        if isinstance(field, ast.AST):\n            yield field\n        elif isinstance(field, list):\n            for item in field:\n                yield item\n\n\nclass Binding(object):\n    \"\"\"\n    Represents the binding of a value to a name.\n\n    The checker uses this to keep track of which names have been bound and\n    which names have not. See L{Assignment} for a special type of binding that\n    is checked with stricter rules.\n\n    @ivar used: pair of (L{Scope}, line-number) indicating the scope and\n                line number that this binding was last used\n    \"\"\"\n\n    def __init__(self, name, source):\n        self.name = name\n        self.source = source\n        self.used = False\n\n    def __str__(self):\n        return self.name\n\n    def __repr__(self):\n        return '<%s object %r from line %r at 0x%x>' % (self.__class__.__name__,\n                                                        self.name,\n                                                        self.source.lineno,\n                                                        id(self))\n\n    def redefines(self, other):\n        return isinstance(other, Definition) and self.name == other.name\n\n\nclass Definition(Binding):\n    \"\"\"\n    A binding that defines a function or a class.\n    \"\"\"\n\n\nclass Importation(Definition):\n    \"\"\"\n    A binding created by an import statement.\n\n    @ivar fullName: The complete name given to the import statement,\n        possibly including multiple dotted components.\n    @type fullName: C{str}\n    \"\"\"\n\n    def __init__(self, name, source):\n        self.fullName = name\n        self.redefined = []\n        name = name.split('.')[0]\n        super(Importation, self).__init__(name, source)\n\n    def redefines(self, other):\n        if isinstance(other, Importation):\n            return self.fullName == other.fullName\n        return isinstance(other, Definition) and self.name == other.name\n\n\nclass Argument(Binding):\n    \"\"\"\n    Represents binding a name as an argument.\n    \"\"\"\n\n\nclass Assignment(Binding):\n    \"\"\"\n    Represents binding a name with an explicit assignment.\n\n    The checker will raise warnings for any Assignment that isn't used. Also,\n    the checker does not consider assignments in tuple/list unpacking to be\n    Assignments, rather it treats them as simple Bindings.\n    \"\"\"\n\n\nclass FunctionDefinition(Definition):\n    pass\n\n\nclass ClassDefinition(Definition):\n    pass\n\n\nclass ExportBinding(Binding):\n    \"\"\"\n    A binding created by an C{__all__} assignment.  If the names in the list\n    can be determined statically, they will be treated as names for export and\n    additional checking applied to them.\n\n    The only C{__all__} assignment that can be recognized is one which takes\n    the value of a literal list containing literal strings.  For example::\n\n        __all__ = [\"foo\", \"bar\"]\n\n    Names which are imported and not otherwise used but appear in the value of\n    C{__all__} will not have an unused import warning reported for them.\n    \"\"\"\n\n    def __init__(self, name, source, scope):\n        if '__all__' in scope and isinstance(source, ast.AugAssign):\n            self.names = list(scope['__all__'].names)\n        else:\n            self.names = []\n        if isinstance(source.value, (ast.List, ast.Tuple)):\n            for node in source.value.elts:\n                if isinstance(node, ast.Str):\n                    self.names.append(node.s)\n        super(ExportBinding, self).__init__(name, source)\n\n\nclass Scope(dict):\n    importStarred = False       # set to True when import * is found\n\n    def __repr__(self):\n        scope_cls = self.__class__.__name__\n        return '<%s at 0x%x %s>' % (scope_cls, id(self), dict.__repr__(self))\n\n\nclass ClassScope(Scope):\n    pass\n\n\nclass FunctionScope(Scope):\n    \"\"\"\n    I represent a name scope for a function.\n\n    @ivar globals: Names declared 'global' in this function.\n    \"\"\"\n    usesLocals = False\n    alwaysUsed = set(['__tracebackhide__',\n                      '__traceback_info__', '__traceback_supplement__'])\n\n    def __init__(self):\n        super(FunctionScope, self).__init__()\n        # Simplify: manage the special locals as globals\n        self.globals = self.alwaysUsed.copy()\n        self.returnValue = None     # First non-empty return\n        self.isGenerator = False    # Detect a generator\n\n    def unusedAssignments(self):\n        \"\"\"\n        Return a generator for the assignments which have not been used.\n        \"\"\"\n        for name, binding in self.items():\n            if (not binding.used and name not in self.globals\n                    and not self.usesLocals\n                    and isinstance(binding, Assignment)):\n                yield name, binding\n\n\nclass GeneratorScope(Scope):\n    pass\n\n\nclass ModuleScope(Scope):\n    pass\n\n\n# Globally defined names which are not attributes of the builtins module, or\n# are only present on some platforms.\n_MAGIC_GLOBALS = ['__file__', '__builtins__', 'WindowsError']\n\n\ndef getNodeName(node):\n    # Returns node.id, or node.name, or None\n    if hasattr(node, 'id'):     # One of the many nodes with an id\n        return node.id\n    if hasattr(node, 'name'):   # a ExceptHandler node\n        return node.name\n\n\nclass Checker(object):\n    \"\"\"\n    I check the cleanliness and sanity of Python code.\n\n    @ivar _deferredFunctions: Tracking list used by L{deferFunction}.  Elements\n        of the list are two-tuples.  The first element is the callable passed\n        to L{deferFunction}.  The second element is a copy of the scope stack\n        at the time L{deferFunction} was called.\n\n    @ivar _deferredAssignments: Similar to C{_deferredFunctions}, but for\n        callables which are deferred assignment checks.\n    \"\"\"\n\n    nodeDepth = 0\n    offset = None\n    traceTree = False\n\n    builtIns = set(builtin_vars).union(_MAGIC_GLOBALS)\n    _customBuiltIns = os.environ.get('PYFLAKES_BUILTINS')\n    if _customBuiltIns:\n        builtIns.update(_customBuiltIns.split(','))\n    del _customBuiltIns\n\n    def __init__(self, tree, filename='(none)', builtins=None,\n                 withDoctest='PYFLAKES_DOCTEST' in os.environ):\n        self._nodeHandlers = {}\n        self._deferredFunctions = []\n        self._deferredAssignments = []\n        self.deadScopes = []\n        self.messages = []\n        self.filename = filename\n        if builtins:\n            self.builtIns = self.builtIns.union(builtins)\n        self.withDoctest = withDoctest\n        self.scopeStack = [ModuleScope()]\n        self.exceptHandlers = [()]\n        self.futuresAllowed = True\n        self.root = tree\n        self.handleChildren(tree)\n        self.runDeferred(self._deferredFunctions)\n        # Set _deferredFunctions to None so that deferFunction will fail\n        # noisily if called after we've run through the deferred functions.\n        self._deferredFunctions = None\n        self.runDeferred(self._deferredAssignments)\n        # Set _deferredAssignments to None so that deferAssignment will fail\n        # noisily if called after we've run through the deferred assignments.\n        self._deferredAssignments = None\n        del self.scopeStack[1:]\n        self.popScope()\n        self.checkDeadScopes()\n\n    def deferFunction(self, callable):\n        \"\"\"\n        Schedule a function handler to be called just before completion.\n\n        This is used for handling function bodies, which must be deferred\n        because code later in the file might modify the global scope. When\n        `callable` is called, the scope at the time this is called will be\n        restored, however it will contain any new bindings added to it.\n        \"\"\"\n        self._deferredFunctions.append((callable, self.scopeStack[:], self.offset))\n\n    def deferAssignment(self, callable):\n        \"\"\"\n        Schedule an assignment handler to be called just after deferred\n        function handlers.\n        \"\"\"\n        self._deferredAssignments.append((callable, self.scopeStack[:], self.offset))\n\n    def runDeferred(self, deferred):\n        \"\"\"\n        Run the callables in C{deferred} using their associated scope stack.\n        \"\"\"\n        for handler, scope, offset in deferred:\n            self.scopeStack = scope\n            self.offset = offset\n            handler()\n\n    @property\n    def scope(self):\n        return self.scopeStack[-1]\n\n    def popScope(self):\n        self.deadScopes.append(self.scopeStack.pop())\n\n    def checkDeadScopes(self):\n        \"\"\"\n        Look at scopes which have been fully examined and report names in them\n        which were imported but unused.\n        \"\"\"\n        for scope in self.deadScopes:\n            if isinstance(scope.get('__all__'), ExportBinding):\n                all_names = set(scope['__all__'].names)\n                if not scope.importStarred and \\\n                   os.path.basename(self.filename) != '__init__.py':\n                    # Look for possible mistakes in the export list\n                    undefined = all_names.difference(scope)\n                    for name in undefined:\n                        self.report(messages.UndefinedExport,\n                                    scope['__all__'].source, name)\n            else:\n                all_names = []\n\n            # Look for imported names that aren't used.\n            for value in scope.values():\n                if isinstance(value, Importation):\n                    used = value.used or value.name in all_names\n                    if not used:\n                        messg = messages.UnusedImport\n                        self.report(messg, value.source, value.name)\n                    for node in value.redefined:\n                        if isinstance(self.getParent(node), ast.For):\n                            messg = messages.ImportShadowedByLoopVar\n                        elif used:\n                            continue\n                        else:\n                            messg = messages.RedefinedWhileUnused\n                        self.report(messg, node, value.name, value.source)\n\n    def pushScope(self, scopeClass=FunctionScope):\n        self.scopeStack.append(scopeClass())\n\n    def report(self, messageClass, *args, **kwargs):\n        self.messages.append(messageClass(self.filename, *args, **kwargs))\n\n    def getParent(self, node):\n        # Lookup the first parent which is not Tuple, List or Starred\n        while True:\n            node = node.parent\n            if not hasattr(node, 'elts') and not hasattr(node, 'ctx'):\n                return node\n\n    def getCommonAncestor(self, lnode, rnode, stop):\n        if stop in (lnode, rnode) or not (hasattr(lnode, 'parent') and\n                                          hasattr(rnode, 'parent')):\n            return None\n        if lnode is rnode:\n            return lnode\n\n        if (lnode.depth > rnode.depth):\n            return self.getCommonAncestor(lnode.parent, rnode, stop)\n        if (lnode.depth < rnode.depth):\n            return self.getCommonAncestor(lnode, rnode.parent, stop)\n        return self.getCommonAncestor(lnode.parent, rnode.parent, stop)\n\n    def descendantOf(self, node, ancestors, stop):\n        for a in ancestors:\n            if self.getCommonAncestor(node, a, stop):\n                return True\n        return False\n\n    def differentForks(self, lnode, rnode):\n        \"\"\"True, if lnode and rnode are located on different forks of IF/TRY\"\"\"\n        ancestor = self.getCommonAncestor(lnode, rnode, self.root)\n        parts = getAlternatives(ancestor)\n        if parts:\n            for items in parts:\n                if self.descendantOf(lnode, items, ancestor) ^ \\\n                   self.descendantOf(rnode, items, ancestor):\n                    return True\n        return False\n\n    def addBinding(self, node, value):\n        \"\"\"\n        Called when a binding is altered.\n\n        - `node` is the statement responsible for the change\n        - `value` is the new value, a Binding instance\n        \"\"\"\n        # assert value.source in (node, node.parent):\n        for scope in self.scopeStack[::-1]:\n            if value.name in scope:\n                break\n        existing = scope.get(value.name)\n\n        if existing and not self.differentForks(node, existing.source):\n\n            parent_stmt = self.getParent(value.source)\n            if isinstance(existing, Importation) and isinstance(parent_stmt, ast.For):\n                self.report(messages.ImportShadowedByLoopVar,\n                            node, value.name, existing.source)\n\n            elif scope is self.scope:\n                if (isinstance(parent_stmt, ast.comprehension) and\n                        not isinstance(self.getParent(existing.source),\n                                       (ast.For, ast.comprehension))):\n                    self.report(messages.RedefinedInListComp,\n                                node, value.name, existing.source)\n                elif not existing.used and value.redefines(existing):\n                    self.report(messages.RedefinedWhileUnused,\n                                node, value.name, existing.source)\n\n            elif isinstance(existing, Importation) and value.redefines(existing):\n                existing.redefined.append(node)\n\n        self.scope[value.name] = value\n\n    def getNodeHandler(self, node_class):\n        try:\n            return self._nodeHandlers[node_class]\n        except KeyError:\n            nodeType = getNodeType(node_class)\n        self._nodeHandlers[node_class] = handler = getattr(self, nodeType)\n        return handler\n\n    def handleNodeLoad(self, node):\n        name = getNodeName(node)\n        if not name:\n            return\n        # try local scope\n        try:\n            self.scope[name].used = (self.scope, node)\n        except KeyError:\n            pass\n        else:\n            return\n\n        scopes = [scope for scope in self.scopeStack[:-1]\n                  if isinstance(scope, (FunctionScope, ModuleScope))]\n        if isinstance(self.scope, GeneratorScope) and scopes[-1] != self.scopeStack[-2]:\n            scopes.append(self.scopeStack[-2])\n\n        # try enclosing function scopes and global scope\n        importStarred = self.scope.importStarred\n        for scope in reversed(scopes):\n            importStarred = importStarred or scope.importStarred\n            try:\n                scope[name].used = (self.scope, node)\n            except KeyError:\n                pass\n            else:\n                return\n\n        # look in the built-ins\n        if importStarred or name in self.builtIns:\n            return\n        if name == '__path__' and os.path.basename(self.filename) == '__init__.py':\n            # the special name __path__ is valid only in packages\n            return\n\n        # protected with a NameError handler?\n        if 'NameError' not in self.exceptHandlers[-1]:\n            self.report(messages.UndefinedName, node, name)\n\n    def handleNodeStore(self, node):\n        name = getNodeName(node)\n        if not name:\n            return\n        # if the name hasn't already been defined in the current scope\n        if isinstance(self.scope, FunctionScope) and name not in self.scope:\n            # for each function or module scope above us\n            for scope in self.scopeStack[:-1]:\n                if not isinstance(scope, (FunctionScope, ModuleScope)):\n                    continue\n                # if the name was defined in that scope, and the name has\n                # been accessed already in the current scope, and hasn't\n                # been declared global\n                used = name in scope and scope[name].used\n                if used and used[0] is self.scope and name not in self.scope.globals:\n                    # then it's probably a mistake\n                    self.report(messages.UndefinedLocal,\n                                scope[name].used[1], name, scope[name].source)\n                    break\n\n        parent_stmt = self.getParent(node)\n        if isinstance(parent_stmt, (ast.For, ast.comprehension)) or (\n                parent_stmt != node.parent and\n                not self.isLiteralTupleUnpacking(parent_stmt)):\n            binding = Binding(name, node)\n        elif name == '__all__' and isinstance(self.scope, ModuleScope):\n            binding = ExportBinding(name, node.parent, self.scope)\n        else:\n            binding = Assignment(name, node)\n        if name in self.scope:\n            binding.used = self.scope[name].used\n        self.addBinding(node, binding)\n\n    def handleNodeDelete(self, node):\n        name = getNodeName(node)\n        if not name:\n            return\n        if isinstance(self.scope, FunctionScope) and name in self.scope.globals:\n            self.scope.globals.remove(name)\n        else:\n            try:\n                del self.scope[name]\n            except KeyError:\n                self.report(messages.UndefinedName, node, name)\n\n    def handleChildren(self, tree, omit=None):\n        for node in iter_child_nodes(tree, omit=omit):\n            self.handleNode(node, tree)\n\n    def isLiteralTupleUnpacking(self, node):\n        if isinstance(node, ast.Assign):\n            for child in node.targets + [node.value]:\n                if not hasattr(child, 'elts'):\n                    return False\n            return True\n\n    def isDocstring(self, node):\n        \"\"\"\n        Determine if the given node is a docstring, as long as it is at the\n        correct place in the node tree.\n        \"\"\"\n        return isinstance(node, ast.Str) or (isinstance(node, ast.Expr) and\n                                             isinstance(node.value, ast.Str))\n\n    def getDocstring(self, node):\n        if isinstance(node, ast.Expr):\n            node = node.value\n        if not isinstance(node, ast.Str):\n            return (None, None)\n        # Computed incorrectly if the docstring has backslash\n        doctest_lineno = node.lineno - node.s.count('\\n') - 1\n        return (node.s, doctest_lineno)\n\n    def handleNode(self, node, parent):\n        if node is None:\n            return\n        if self.offset and getattr(node, 'lineno', None) is not None:\n            node.lineno += self.offset[0]\n            node.col_offset += self.offset[1]\n        if self.traceTree:\n            print('  ' * self.nodeDepth + node.__class__.__name__)\n        if self.futuresAllowed and not (isinstance(node, ast.ImportFrom) or\n                                        self.isDocstring(node)):\n            self.futuresAllowed = False\n        self.nodeDepth += 1\n        node.depth = self.nodeDepth\n        node.parent = parent\n        try:\n            handler = self.getNodeHandler(node.__class__)\n            handler(node)\n        finally:\n            self.nodeDepth -= 1\n        if self.traceTree:\n            print('  ' * self.nodeDepth + 'end ' + node.__class__.__name__)\n\n    _getDoctestExamples = doctest.DocTestParser().get_examples\n\n    def handleDoctests(self, node):\n        try:\n            (docstring, node_lineno) = self.getDocstring(node.body[0])\n            examples = docstring and self._getDoctestExamples(docstring)\n        except (ValueError, IndexError):\n            # e.g. line 6 of the docstring for <string> has inconsistent\n            # leading whitespace: ...\n            return\n        if not examples:\n            return\n        node_offset = self.offset or (0, 0)\n        self.pushScope()\n        underscore_in_builtins = '_' in self.builtIns\n        if not underscore_in_builtins:\n            self.builtIns.add('_')\n        for example in examples:\n            try:\n                tree = compile(example.source, \"<doctest>\", \"exec\", ast.PyCF_ONLY_AST)\n            except SyntaxError:\n                e = sys.exc_info()[1]\n                position = (node_lineno + example.lineno + e.lineno,\n                            example.indent + 4 + (e.offset or 0))\n                self.report(messages.DoctestSyntaxError, node, position)\n            else:\n                self.offset = (node_offset[0] + node_lineno + example.lineno,\n                               node_offset[1] + example.indent + 4)\n                self.handleChildren(tree)\n                self.offset = node_offset\n        if not underscore_in_builtins:\n            self.builtIns.remove('_')\n        self.popScope()\n\n    def ignore(self, node):\n        pass\n\n    # \"stmt\" type nodes\n    DELETE = PRINT = FOR = WHILE = IF = WITH = WITHITEM = RAISE = \\\n        TRYFINALLY = ASSERT = EXEC = EXPR = ASSIGN = handleChildren\n\n    CONTINUE = BREAK = PASS = ignore\n\n    # \"expr\" type nodes\n    BOOLOP = BINOP = UNARYOP = IFEXP = DICT = SET = \\\n        COMPARE = CALL = REPR = ATTRIBUTE = SUBSCRIPT = LIST = TUPLE = \\\n        STARRED = NAMECONSTANT = handleChildren\n\n    NUM = STR = BYTES = ELLIPSIS = ignore\n\n    # \"slice\" type nodes\n    SLICE = EXTSLICE = INDEX = handleChildren\n\n    # expression contexts are node instances too, though being constants\n    LOAD = STORE = DEL = AUGLOAD = AUGSTORE = PARAM = ignore\n\n    # same for operators\n    AND = OR = ADD = SUB = MULT = DIV = MOD = POW = LSHIFT = RSHIFT = \\\n        BITOR = BITXOR = BITAND = FLOORDIV = INVERT = NOT = UADD = USUB = \\\n        EQ = NOTEQ = LT = LTE = GT = GTE = IS = ISNOT = IN = NOTIN = ignore\n\n    # additional node types\n    LISTCOMP = COMPREHENSION = KEYWORD = handleChildren\n\n    def GLOBAL(self, node):\n        \"\"\"\n        Keep track of globals declarations.\n        \"\"\"\n        if isinstance(self.scope, FunctionScope):\n            self.scope.globals.update(node.names)\n\n    NONLOCAL = GLOBAL\n\n    def GENERATOREXP(self, node):\n        self.pushScope(GeneratorScope)\n        self.handleChildren(node)\n        self.popScope()\n\n    DICTCOMP = SETCOMP = GENERATOREXP\n\n    def NAME(self, node):\n        \"\"\"\n        Handle occurrence of Name (which can be a load/store/delete access.)\n        \"\"\"\n        # Locate the name in locals / function / globals scopes.\n        if isinstance(node.ctx, (ast.Load, ast.AugLoad)):\n            self.handleNodeLoad(node)\n            if (node.id == 'locals' and isinstance(self.scope, FunctionScope)\n                    and isinstance(node.parent, ast.Call)):\n                # we are doing locals() call in current scope\n                self.scope.usesLocals = True\n        elif isinstance(node.ctx, (ast.Store, ast.AugStore)):\n            self.handleNodeStore(node)\n        elif isinstance(node.ctx, ast.Del):\n            self.handleNodeDelete(node)\n        else:\n            # must be a Param context -- this only happens for names in function\n            # arguments, but these aren't dispatched through here\n            raise RuntimeError(\"Got impossible expression context: %r\" % (node.ctx,))\n\n    def RETURN(self, node):\n        if node.value and not self.scope.returnValue:\n            self.scope.returnValue = node.value\n        self.handleNode(node.value, node)\n\n    def YIELD(self, node):\n        self.scope.isGenerator = True\n        self.handleNode(node.value, node)\n\n    YIELDFROM = YIELD\n\n    def FUNCTIONDEF(self, node):\n        for deco in node.decorator_list:\n            self.handleNode(deco, node)\n        self.LAMBDA(node)\n        self.addBinding(node, FunctionDefinition(node.name, node))\n        if self.withDoctest:\n            self.deferFunction(lambda: self.handleDoctests(node))\n\n    def LAMBDA(self, node):\n        args = []\n        annotations = []\n\n        if PY2:\n            def addArgs(arglist):\n                for arg in arglist:\n                    if isinstance(arg, ast.Tuple):\n                        addArgs(arg.elts)\n                    else:\n                        args.append(arg.id)\n            addArgs(node.args.args)\n            defaults = node.args.defaults\n        else:\n            for arg in node.args.args + node.args.kwonlyargs:\n                args.append(arg.arg)\n                annotations.append(arg.annotation)\n            defaults = node.args.defaults + node.args.kw_defaults\n\n        # Only for Python3 FunctionDefs\n        is_py3_func = hasattr(node, 'returns')\n\n        for arg_name in ('vararg', 'kwarg'):\n            wildcard = getattr(node.args, arg_name)\n            if not wildcard:\n                continue\n            args.append(wildcard if PY33 else wildcard.arg)\n            if is_py3_func:\n                if PY33:  # Python 2.5 to 3.3\n                    argannotation = arg_name + 'annotation'\n                    annotations.append(getattr(node.args, argannotation))\n                else:     # Python >= 3.4\n                    annotations.append(wildcard.annotation)\n\n        if is_py3_func:\n            annotations.append(node.returns)\n\n        if len(set(args)) < len(args):\n            for (idx, arg) in enumerate(args):\n                if arg in args[:idx]:\n                    self.report(messages.DuplicateArgument, node, arg)\n\n        for child in annotations + defaults:\n            if child:\n                self.handleNode(child, node)\n\n        def runFunction():\n\n            self.pushScope()\n            for name in args:\n                self.addBinding(node, Argument(name, node))\n            if isinstance(node.body, list):\n                # case for FunctionDefs\n                for stmt in node.body:\n                    self.handleNode(stmt, node)\n            else:\n                # case for Lambdas\n                self.handleNode(node.body, node)\n\n            def checkUnusedAssignments():\n                \"\"\"\n                Check to see if any assignments have not been used.\n                \"\"\"\n                for name, binding in self.scope.unusedAssignments():\n                    self.report(messages.UnusedVariable, binding.source, name)\n            self.deferAssignment(checkUnusedAssignments)\n\n            if PY32:\n                def checkReturnWithArgumentInsideGenerator():\n                    \"\"\"\n                    Check to see if there is any return statement with\n                    arguments but the function is a generator.\n                    \"\"\"\n                    if self.scope.isGenerator and self.scope.returnValue:\n                        self.report(messages.ReturnWithArgsInsideGenerator,\n                                    self.scope.returnValue)\n                self.deferAssignment(checkReturnWithArgumentInsideGenerator)\n            self.popScope()\n\n        self.deferFunction(runFunction)\n\n    def CLASSDEF(self, node):\n        \"\"\"\n        Check names used in a class definition, including its decorators, base\n        classes, and the body of its definition.  Additionally, add its name to\n        the current scope.\n        \"\"\"\n        for deco in node.decorator_list:\n            self.handleNode(deco, node)\n        for baseNode in node.bases:\n            self.handleNode(baseNode, node)\n        if not PY2:\n            for keywordNode in node.keywords:\n                self.handleNode(keywordNode, node)\n        self.pushScope(ClassScope)\n        if self.withDoctest:\n            self.deferFunction(lambda: self.handleDoctests(node))\n        for stmt in node.body:\n            self.handleNode(stmt, node)\n        self.popScope()\n        self.addBinding(node, ClassDefinition(node.name, node))\n\n    def AUGASSIGN(self, node):\n        self.handleNodeLoad(node.target)\n        self.handleNode(node.value, node)\n        self.handleNode(node.target, node)\n\n    def IMPORT(self, node):\n        for alias in node.names:\n            name = alias.asname or alias.name\n            importation = Importation(name, node)\n            self.addBinding(node, importation)\n\n    def IMPORTFROM(self, node):\n        if node.module == '__future__':\n            if not self.futuresAllowed:\n                self.report(messages.LateFutureImport,\n                            node, [n.name for n in node.names])\n        else:\n            self.futuresAllowed = False\n\n        for alias in node.names:\n            if alias.name == '*':\n                self.scope.importStarred = True\n                self.report(messages.ImportStarUsed, node, node.module)\n                continue\n            name = alias.asname or alias.name\n            importation = Importation(name, node)\n            if node.module == '__future__':\n                importation.used = (self.scope, node)\n            self.addBinding(node, importation)\n\n    def TRY(self, node):\n        handler_names = []\n        # List the exception handlers\n        for handler in node.handlers:\n            if isinstance(handler.type, ast.Tuple):\n                for exc_type in handler.type.elts:\n                    handler_names.append(getNodeName(exc_type))\n            elif handler.type:\n                handler_names.append(getNodeName(handler.type))\n        # Memorize the except handlers and process the body\n        self.exceptHandlers.append(handler_names)\n        for child in node.body:\n            self.handleNode(child, node)\n        self.exceptHandlers.pop()\n        # Process the other nodes: \"except:\", \"else:\", \"finally:\"\n        self.handleChildren(node, omit='body')\n\n    TRYEXCEPT = TRY\n\n    def EXCEPTHANDLER(self, node):\n        # 3.x: in addition to handling children, we must handle the name of\n        # the exception, which is not a Name node, but a simple string.\n        if isinstance(node.name, str):\n            self.handleNodeStore(node)\n        self.handleChildren(node)\n"
  },
  {
    "path": "sublimelinter/modules/libs/pyflakes/messages.py",
    "content": "\"\"\"\nProvide the class Message and its subclasses.\n\"\"\"\n\n\nclass Message(object):\n    message = ''\n    message_args = ()\n\n    def __init__(self, filename, loc):\n        self.filename = filename\n        self.lineno = loc.lineno\n        self.col = getattr(loc, 'col_offset', 0)\n\n    def __str__(self):\n        return '%s:%s: %s' % (self.filename, self.lineno,\n                              self.message % self.message_args)\n\n\nclass UnusedImport(Message):\n    message = '%r imported but unused'\n\n    def __init__(self, filename, loc, name):\n        Message.__init__(self, filename, loc)\n        self.message_args = (name,)\n\n\nclass RedefinedWhileUnused(Message):\n    message = 'redefinition of unused %r from line %r'\n\n    def __init__(self, filename, loc, name, orig_loc):\n        Message.__init__(self, filename, loc)\n        self.message_args = (name, orig_loc.lineno)\n\n\nclass RedefinedInListComp(Message):\n    message = 'list comprehension redefines %r from line %r'\n\n    def __init__(self, filename, loc, name, orig_loc):\n        Message.__init__(self, filename, loc)\n        self.message_args = (name, orig_loc.lineno)\n\n\nclass ImportShadowedByLoopVar(Message):\n    message = 'import %r from line %r shadowed by loop variable'\n\n    def __init__(self, filename, loc, name, orig_loc):\n        Message.__init__(self, filename, loc)\n        self.message_args = (name, orig_loc.lineno)\n\n\nclass ImportStarUsed(Message):\n    message = \"'from %s import *' used; unable to detect undefined names\"\n\n    def __init__(self, filename, loc, modname):\n        Message.__init__(self, filename, loc)\n        self.message_args = (modname,)\n\n\nclass UndefinedName(Message):\n    message = 'undefined name %r'\n\n    def __init__(self, filename, loc, name):\n        Message.__init__(self, filename, loc)\n        self.message_args = (name,)\n\n\nclass DoctestSyntaxError(Message):\n    message = 'syntax error in doctest'\n\n    def __init__(self, filename, loc, position=None):\n        Message.__init__(self, filename, loc)\n        if position:\n            (self.lineno, self.col) = position\n        self.message_args = ()\n\n\nclass UndefinedExport(Message):\n    message = 'undefined name %r in __all__'\n\n    def __init__(self, filename, loc, name):\n        Message.__init__(self, filename, loc)\n        self.message_args = (name,)\n\n\nclass UndefinedLocal(Message):\n    message = ('local variable %r (defined in enclosing scope on line %r) '\n               'referenced before assignment')\n\n    def __init__(self, filename, loc, name, orig_loc):\n        Message.__init__(self, filename, loc)\n        self.message_args = (name, orig_loc.lineno)\n\n\nclass DuplicateArgument(Message):\n    message = 'duplicate argument %r in function definition'\n\n    def __init__(self, filename, loc, name):\n        Message.__init__(self, filename, loc)\n        self.message_args = (name,)\n\n\nclass Redefined(Message):\n    message = 'redefinition of %r from line %r'\n\n    def __init__(self, filename, loc, name, orig_loc):\n        Message.__init__(self, filename, loc)\n        self.message_args = (name, orig_loc.lineno)\n\n\nclass LateFutureImport(Message):\n    message = 'future import(s) %r after other statements'\n\n    def __init__(self, filename, loc, names):\n        Message.__init__(self, filename, loc)\n        self.message_args = (names,)\n\n\nclass UnusedVariable(Message):\n    \"\"\"\n    Indicates that a variable has been explicity assigned to but not actually\n    used.\n    \"\"\"\n    message = 'local variable %r is assigned to but never used'\n\n    def __init__(self, filename, loc, names):\n        Message.__init__(self, filename, loc)\n        self.message_args = (names,)\n\n\nclass ReturnWithArgsInsideGenerator(Message):\n    \"\"\"\n    Indicates a return statement with arguments inside a generator.\n    \"\"\"\n    message = '\\'return\\' with argument inside generator'\n"
  },
  {
    "path": "sublimelinter/modules/libs/pyflakes/reporter.py",
    "content": "\"\"\"\nProvide the Reporter class.\n\"\"\"\n\nimport re\nimport sys\n\n\nclass Reporter(object):\n    \"\"\"\n    Formats the results of pyflakes checks to users.\n    \"\"\"\n\n    def __init__(self, warningStream, errorStream):\n        \"\"\"\n        Construct a L{Reporter}.\n\n        @param warningStream: A file-like object where warnings will be\n            written to.  The stream's C{write} method must accept unicode.\n            C{sys.stdout} is a good value.\n        @param errorStream: A file-like object where error output will be\n            written to.  The stream's C{write} method must accept unicode.\n            C{sys.stderr} is a good value.\n        \"\"\"\n        self._stdout = warningStream\n        self._stderr = errorStream\n\n    def unexpectedError(self, filename, msg):\n        \"\"\"\n        An unexpected error occurred trying to process C{filename}.\n\n        @param filename: The path to a file that we could not process.\n        @ptype filename: C{unicode}\n        @param msg: A message explaining the problem.\n        @ptype msg: C{unicode}\n        \"\"\"\n        self._stderr.write(\"%s: %s\\n\" % (filename, msg))\n\n    def syntaxError(self, filename, msg, lineno, offset, text):\n        \"\"\"\n        There was a syntax errror in C{filename}.\n\n        @param filename: The path to the file with the syntax error.\n        @ptype filename: C{unicode}\n        @param msg: An explanation of the syntax error.\n        @ptype msg: C{unicode}\n        @param lineno: The line number where the syntax error occurred.\n        @ptype lineno: C{int}\n        @param offset: The column on which the syntax error occurred, or None.\n        @ptype offset: C{int}\n        @param text: The source code containing the syntax error.\n        @ptype text: C{unicode}\n        \"\"\"\n        line = text.splitlines()[-1]\n        if offset is not None:\n            offset = offset - (len(text) - len(line))\n            self._stderr.write('%s:%d:%d: %s\\n' %\n                               (filename, lineno, offset + 1, msg))\n        else:\n            self._stderr.write('%s:%d: %s\\n' % (filename, lineno, msg))\n        self._stderr.write(line)\n        self._stderr.write('\\n')\n        if offset is not None:\n            self._stderr.write(re.sub(r'\\S', ' ', line[:offset]) +\n                               \"^\\n\")\n\n    def flake(self, message):\n        \"\"\"\n        pyflakes found something wrong with the code.\n\n        @param: A L{pyflakes.messages.Message}.\n        \"\"\"\n        self._stdout.write(str(message))\n        self._stdout.write('\\n')\n\n\ndef _makeDefaultReporter():\n    \"\"\"\n    Make a reporter that can be used when no reporter is specified.\n    \"\"\"\n    return Reporter(sys.stdout, sys.stderr)\n"
  },
  {
    "path": "sublimelinter/modules/lua.py",
    "content": "import re\nfrom base_linter import BaseLinter\n\nCONFIG = {\n    'language': 'Lua',\n    'executable': 'luac',\n    'lint_args': ['-p', '-'],\n}\n\n\nclass Linter(BaseLinter):\n\n    def parse_errors(self, view, errors, lines, errorUnderlines, violationUnderlines, warningUnderlines, errorMessages, violationMessages, warningMessages):\n        for line in errors.splitlines():\n            match = re.match(r'^.+:(?P<line>\\d+):\\s+(?P<error>.+)', line)\n\n            if match:\n                error, line = match.group('error'), match.group('line')\n                self.add_message(int(line), lines, error, errorMessages)\n"
  },
  {
    "path": "sublimelinter/modules/notes.py",
    "content": "'''notes.py\n\nUsed to highlight user-defined \"annotations\" such as TODO, README, etc.,\ndepending user choice.\n'''\n\nimport sublime\n\nfrom base_linter import BaseLinter\n\nCONFIG = {\n    'language': 'Annotations'\n}\n\n\nclass Linter(BaseLinter):\n    DEFAULT_NOTES = [\"TODO\", \"README\", \"FIXME\"]\n\n    def built_in_check(self, view, code, filename):\n        annotations = self.select_annotations(view)\n        regions = []\n\n        for annotation in annotations:\n            regions.extend(self.find_all(code, annotation, view))\n\n        return regions\n\n    def select_annotations(self, view):\n        '''selects the list of annotations to use'''\n        return view.settings().get(\"annotations\", self.DEFAULT_NOTES)\n\n    def extract_annotations(self, code, view, filename):\n        '''extract all lines with annotations'''\n        annotations = self.select_annotations(view)\n        annotation_starts = []\n\n        for annotation in annotations:\n            start = 0\n            length = len(annotation)\n\n            while True:\n                start = code.find(annotation, start)\n\n                if start != -1:\n                    end = start + length\n                    annotation_starts.append(start)\n                    start = end\n                else:\n                    break\n\n        regions_with_notes = set([])\n\n        for point in annotation_starts:\n            regions_with_notes.add(view.extract_scope(point))\n\n        regions_with_notes = sorted(list(regions_with_notes))\n        text = []\n\n        for region in regions_with_notes:\n            row, col = view.rowcol(region.begin())\n            text.append(\"[{0}:{1}]\".format(filename, row + 1))\n            text.append(view.substr(region))\n\n        return '\\n'.join(text)\n\n    def find_all(self, text, string, view):\n        ''' finds all occurences of \"string\" in \"text\" and notes their positions\n            as a sublime Region\n        '''\n        found = []\n        length = len(string)\n        start = 0\n\n        while True:\n            start = text.find(string, start)\n\n            if start != -1:\n                end = start + length\n                found.append(sublime.Region(start, end))\n                start = end\n            else:\n                break\n\n        return found\n"
  },
  {
    "path": "sublimelinter/modules/objective-j.py",
    "content": "# objective-j.py - Lint checking for Objective-J - given filename and contents of the code:\n# It provides a list of line numbers to outline and offsets to highlight.\n#\n# This specific module is part of the SublimeLinter project.\n# It is a fork of the original SublimeLint project,\n# (c) 2011 Ryan Hileman and licensed under the MIT license.\n# URL: http://bochs.info/\n#\n# The original copyright notices for this file/project follows:\n#\n# (c) 2005-2008 Divmod, Inc.\n# See LICENSE file for details\n#\n# The LICENSE file is as follows:\n#\n# Copyright (c) 2005 Divmod, Inc., http://www.divmod.com/\n#\n# Permission is hereby granted, free of charge, to any person obtaining\n# a copy of this software and associated documentation files (the\n# \"Software\"), to deal in the Software without restriction, including\n# without limitation the rights to use, copy, modify, merge, publish,\n# distribute, sublicense, and/or sell copies of the Software, and to\n# permit persons to whom the Software is furnished to do so, subject to\n# the following conditions:\n#\n# The above copyright notice and this permission notice shall be\n# included in all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\n# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n#\n\nfrom capp_lint import LintChecker\nfrom base_linter import BaseLinter\n\nCONFIG = {\n    'language': 'Objective-J'\n}\n\n\nclass Linter(BaseLinter):\n    def built_in_check(self, view, code, filename):\n        checker = LintChecker(view)\n        checker.lint_text(code, filename)\n        return checker.errors\n\n    def parse_errors(self, view, errors, lines, errorUnderlines, violationUnderlines, warningUnderlines, errorMessages, violationMessages, warningMessages):\n        for error in errors:\n            lineno = error['lineNum']\n            self.add_message(lineno, lines, error['message'], errorMessages if type == LintChecker.ERROR_TYPE_ILLEGAL else warningMessages)\n\n            for position in error.get('positions', []):\n                self.underline_range(view, lineno, position, errorUnderlines if type == LintChecker.ERROR_TYPE_ILLEGAL else warningUnderlines)\n"
  },
  {
    "path": "sublimelinter/modules/perl.py",
    "content": "import re\nimport subprocess\n\nfrom base_linter import BaseLinter\n\nCONFIG = {\n    'language': 'Perl'\n}\n\n\nclass Linter(BaseLinter):\n    PERLCRITIC_RE = re.compile(r'\\[(?P<pbp>.+)\\] (?P<error>.+?) at line (?P<line>\\d+), column (?P<column>\\d+).+?')\n    PERL_RE = re.compile(r'(?P<error>.+?) at .+? line (?P<line>\\d+)(, near \"(?P<near>.+?)\")?')\n\n    def __init__(self, config):\n        super(Linter, self).__init__(config)\n        self.linter = None\n\n    def get_executable(self, view):\n        self.linter = view.settings().get('perl_linter', 'perlcritic')\n\n        if self.linter == 'perl':\n            linter_name = 'Perl'\n        else:\n            linter_name = 'Perl::Critic'\n\n        try:\n            path = self.get_mapped_executable(view, self.linter)\n            subprocess.call([path, '--version'], startupinfo=self.get_startupinfo())\n            return (True, path, 'using {0}'.format(linter_name))\n        except OSError:\n            return (False, '', '{0} is required'.format(linter_name))\n\n    def get_lint_args(self, view, code, filename):\n        if self.linter == 'perl':\n            return ['-c']\n        else:\n            return ['--verbose', '8']\n\n    def parse_errors(self, view, errors, lines, errorUnderlines, violationUnderlines, warningUnderlines, errorMessages, violationMessages, warningMessages):\n        for line in errors.splitlines():\n            if self.linter == 'perl':\n                match = self.PERL_RE.match(line)\n            else:\n                match = self.PERLCRITIC_RE.match(line)\n\n            if match:\n                error, line = match.group('error'), match.group('line')\n                lineno = int(line)\n\n                if self.linter == 'perl':\n                    near = match.group('near')\n\n                    if near:\n                        error = '{0}, near \"{1}\"'.format(error, near)\n                        self.underline_regex(view, lineno, '(?P<underline>{0})'.format(re.escape(near)), lines, errorUnderlines)\n                else:\n                    column = match.group('column')\n                    column = int(column) - 1\n                    self.underline_word(view, lineno, column, errorUnderlines)\n\n                self.add_message(lineno, lines, error, errorMessages)\n"
  },
  {
    "path": "sublimelinter/modules/php.py",
    "content": "import re\n\nfrom base_linter import BaseLinter\n\nCONFIG = {\n    'language': 'PHP',\n    'executable': 'php',\n    'lint_args': ['-l', '-d display_errors=On', '-d log_errors=Off']\n}\n\n\nclass Linter(BaseLinter):\n    def parse_errors(self, view, errors, lines, errorUnderlines, violationUnderlines, warningUnderlines, errorMessages, violationMessages, warningMessages):\n        for line in errors.splitlines():\n            match = re.match(r'^Parse error:\\s*(?:\\w+ error,\\s*)?(?P<error>.+?)\\s+in\\s+.+?\\s*line\\s+(?P<line>\\d+)', line)\n\n            if match:\n                error, line = match.group('error'), match.group('line')\n                self.add_message(int(line), lines, error, errorMessages)\n"
  },
  {
    "path": "sublimelinter/modules/puppet-lint.py",
    "content": "# -*- coding: utf-8 -*-\n# puppet-lint.py - sublimelint package for checking puppet files\n# Requires:\n# gem install puppet-lint\n\nimport re\n\nfrom base_linter import BaseLinter, INPUT_METHOD_FILE\n\nCONFIG = {\n    'language': 'puppet-lint',\n    'executable': 'puppet-lint',\n    'lint_args': ['--no-80chars-check', '{filename}'],\n    'test_existence_args': '--version',\n    'input_method': INPUT_METHOD_FILE\n}\n\n\nclass Linter(BaseLinter):\n    def parse_errors(self, view, errors, lines, errorUnderlines, violationUnderlines, warningUnderlines, errorMessages, violationMessages, warningMessages):\n        for line in errors.splitlines():\n            match = re.match(r'[Ee]rr(or)?: (?P<error>.+?(Syntax error at \\'(?P<near>.+?)\\'; expected \\'.+\\')) at /.+?:(?P<line>\\d+)?', line)\n            if not match:\n                match = re.match(r'[Ee]rr(or)?: (?P<error>.+?(Could not match (?P<near>.+?))?) at /.+?:(?P<line>\\d+)?', line)\n                if not match:\n                    match = re.match(r'(ERROR|WARNING): (?P<error>.+?) on line (?P<line>\\d+)?$', line)\n\n            if match:\n                error, line = match.group('error'), match.group('line')\n                lineno = int(line)\n                try:\n                    near = match.group('near')\n                except IndexError:\n                    near = ''\n\n                if near:\n                    error = '{0}, near \"{1}\"'.format(error, near)\n                    self.underline_regex(view, lineno, '(?P<underline>{0})'.format(re.escape(near)), lines, errorUnderlines)\n\n                self.add_message(lineno, lines, error, errorMessages)\n"
  },
  {
    "path": "sublimelinter/modules/puppet.py",
    "content": "import re\n\nfrom base_linter import BaseLinter, INPUT_METHOD_TEMP_FILE\n\nCONFIG = {\n    'language': 'Puppet',\n    'executable': 'puppet',\n    'lint_args': ['parser', 'validate', '--color=false', '{filename}'],\n    'test_existence_args': '-V',\n    'input_method': INPUT_METHOD_TEMP_FILE\n}\n\n\nclass Linter(BaseLinter):\n    def parse_errors(self, view, errors, lines, errorUnderlines, violationUnderlines, warningUnderlines, errorMessages, violationMessages, warningMessages):\n        for line in errors.splitlines():\n            match = re.match(r'[Ee]rr(or)?: (?P<error>.+?(Syntax error at \\'(?P<near>.+?)\\'; expected \\'.+\\')) at /.+?:(?P<line>\\d+)?', line)\n            if not match:\n                match = re.match(r'[Ee]rr(or)?: (?P<error>.+?(Could not match (?P<near>.+?))?) at /.+?:(?P<line>\\d+)?', line)\n                if not match:\n                    match = re.match(r'(ERROR|WARNING): (?P<error>.+?) on line (?P<line>\\d+)?', line)\n\n            if match:\n                error, line = match.group('error'), match.group('line')\n                lineno = int(line)\n                try:\n                    near = match.group('near')\n                except IndexError:\n                    near = ''\n\n                if near:\n                    error = '{0}, near \"{1}\"'.format(error, near)\n                    self.underline_regex(view, lineno, '(?P<underline>{0})'.format(re.escape(near)), lines, errorUnderlines)\n\n                self.add_message(lineno, lines, error, errorMessages)\n"
  },
  {
    "path": "sublimelinter/modules/python.py",
    "content": "# -*- coding: utf-8 -*-\n# python.py - Lint checking for Python - given filename and contents of the code:\n# It provides a list of line numbers to outline and offsets to highlight.\n#\n# This specific module is part of the SublimeLinter project.\n# It is a fork by André Roberge from the original SublimeLint project,\n# (c) 2011 Ryan Hileman and licensed under the MIT license.\n# URL: http://bochs.info/\n#\n# The original copyright notices for this file/project follows:\n#\n# (c) 2005-2008 Divmod, Inc.\n# See LICENSE file for details\n#\n# The LICENSE file is as follows:\n#\n# Copyright (c) 2005 Divmod, Inc., http://www.divmod.com/\n#\n# Permission is hereby granted, free of charge, to any person obtaining\n# a copy of this software and associated documentation files (the\n# \"Software\"), to deal in the Software without restriction, including\n# without limitation the rights to use, copy, modify, merge, publish,\n# distribute, sublicense, and/or sell copies of the Software, and to\n# permit persons to whom the Software is furnished to do so, subject to\n# the following conditions:\n#\n# The above copyright notice and this permission notice shall be\n# included in all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\n# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n#\n\n# TODO:\n# * fix regex for variable names inside strings (quotes)\n\nimport re\nimport _ast\n\nimport pep8\nimport pyflakes.checker as pyflakes\n\nfrom base_linter import BaseLinter\n\npyflakes.messages.Message.__str__ = lambda self: self.message % self.message_args\n\nCONFIG = {\n    'language': 'Python'\n}\n\n\nclass LOC(object):\n    def __init__(self, lineno):\n        self.lineno = lineno\n\n\nclass PythonLintError(pyflakes.messages.Message):\n\n    def __init__(self, filename, loc, level, message, message_args, offset=None, text=None):\n        if isinstance(loc, int):\n            loc = LOC(loc)\n        super(PythonLintError, self).__init__(filename, loc)\n        self.level = level\n        self.message = message\n        self.message_args = message_args\n        if offset is not None:\n            self.offset = offset\n        if text is not None:\n            self.text = text\n\n\nclass Pep8Error(PythonLintError):\n\n    def __init__(self, filename, loc, offset, code, text):\n        # PEP 8 Errors are downgraded to \"warnings\"\n        super(Pep8Error, self).__init__(filename, loc, 'W', '[W] PEP 8 (%s): %s', (code, text),\n                                        offset=offset, text=text)\n\n\nclass Pep8Warning(PythonLintError):\n\n    def __init__(self, filename, loc, offset, code, text):\n        # PEP 8 Warnings are downgraded to \"violations\"\n        super(Pep8Warning, self).__init__(filename, loc, 'V', '[V] PEP 8 (%s): %s', (code, text),\n                                          offset=offset, text=text)\n\n\nclass OffsetError(PythonLintError):\n\n    def __init__(self, filename, loc, text, offset):\n        super(OffsetError, self).__init__(filename, loc, 'E', '[E] %r', (text,), offset=offset + 1, text=text)\n\n\nclass PythonError(PythonLintError):\n\n    def __init__(self, filename, loc, text):\n        super(PythonError, self).__init__(filename, loc, 'E', '[E] %r', (text,), text=text)\n\n\nclass Linter(BaseLinter):\n    def pyflakes_check(self, code, filename, ignore=None):\n        try:\n            tree = compile(code, filename, \"exec\", _ast.PyCF_ONLY_AST)\n        except (SyntaxError, IndentationError), value:\n            msg = value.args[0]\n\n            (lineno, offset, text) = value.lineno, value.offset, value.text\n\n            # If there's an encoding problem with the file, the text is None.\n            if text is None:\n                # Avoid using msg, since for the only known case, it contains a\n                # bogus message that claims the encoding the file declared was\n                # unknown.\n                if msg.startswith('duplicate argument'):\n                    arg = msg.split('duplicate argument ', 1)[1].split(' ', 1)[0].strip('\\'\"')\n                    error = pyflakes.messages.DuplicateArgument(filename, value, arg)\n                else:\n                    error = PythonError(filename, value, msg)\n            else:\n                line = text.splitlines()[-1]\n\n                if offset is not None:\n                    offset = offset - (len(text) - len(line))\n\n                if offset is not None:\n                    error = OffsetError(filename, value, msg, offset)\n                else:\n                    error = PythonError(filename, value, msg)\n            return [error]\n        except ValueError, e:\n            return [PythonError(filename, 0, e.args[0])]\n        else:\n            # Okay, it's syntactically valid.  Now check it.\n            if ignore is not None:\n                old_magic_globals = pyflakes._MAGIC_GLOBALS\n                pyflakes._MAGIC_GLOBALS += ignore\n\n            w = pyflakes.Checker(tree, filename)\n\n            if ignore is not None:\n                pyflakes._MAGIC_GLOBALS = old_magic_globals\n\n            return w.messages\n\n    def pep8_check(self, code, filename, ignore=None):\n        messages = []\n        _lines = code.split('\\n')\n\n        if _lines:\n            class SublimeLinterReport(pep8.BaseReport):\n                def error(self, line_number, offset, text, check):\n                    \"\"\"Report an error, according to options.\"\"\"\n                    code = text[:4]\n                    message = text[5:]\n\n                    if self._ignore_code(code):\n                        return\n                    if code in self.counters:\n                        self.counters[code] += 1\n                    else:\n                        self.counters[code] = 1\n                        self.messages[code] = message\n\n                    # Don't care about expected errors or warnings\n                    if code in self.expected:\n                        return\n\n                    self.file_errors += 1\n                    self.total_errors += 1\n\n                    if code.startswith('E'):\n                        messages.append(Pep8Error(filename, line_number, offset, code, message))\n                    else:\n                        messages.append(Pep8Warning(filename, line_number, offset, code, message))\n\n                    return code\n\n            _ignore = ignore + pep8.DEFAULT_IGNORE.split(',')\n\n            options = pep8.StyleGuide(reporter=SublimeLinterReport, ignore=_ignore).options\n            options.max_line_length = pep8.MAX_LINE_LENGTH\n\n            good_lines = [l + '\\n' for l in _lines]\n            good_lines[-1] = good_lines[-1].rstrip('\\n')\n\n            if not good_lines[-1]:\n                good_lines = good_lines[:-1]\n\n            try:\n                pep8.Checker(filename, good_lines, options).check_all()\n            except Exception, e:\n                print \"An exception occured when running pep8 checker: %s\" % e\n\n        return messages\n\n    def built_in_check(self, view, code, filename):\n        errors = []\n\n        if view.settings().get(\"pep8\", True):\n            errors.extend(self.pep8_check(code, filename, ignore=view.settings().get('pep8_ignore', [])))\n\n        pyflakes_ignore = view.settings().get('pyflakes_ignore', None)\n        pyflakes_disabled = view.settings().get('pyflakes_disabled', False)\n\n        if not pyflakes_disabled:\n            errors.extend(self.pyflakes_check(code, filename, pyflakes_ignore))\n\n        return errors\n\n    def parse_errors(self, view, errors, lines, errorUnderlines, violationUnderlines, warningUnderlines, errorMessages, violationMessages, warningMessages):\n\n        def underline_word(lineno, word, underlines):\n            regex = r'((and|or|not|if|elif|while|in)\\s+|[+\\-*^%%<>=\\(\\{{])*\\s*(?P<underline>[\\w\\.]*{0}[\\w]*)'.format(re.escape(word))\n            self.underline_regex(view, lineno, regex, lines, underlines, word)\n\n        def underline_import(lineno, word, underlines):\n            linematch = '(from\\s+[\\w_\\.]+\\s+)?import\\s+(?P<match>[^#;]+)'\n            regex = '(^|\\s+|,\\s*|as\\s+)(?P<underline>[\\w]*{0}[\\w]*)'.format(re.escape(word))\n            self.underline_regex(view, lineno, regex, lines, underlines, word, linematch)\n\n        def underline_for_var(lineno, word, underlines):\n            regex = 'for\\s+(?P<underline>[\\w]*{0}[\\w*])'.format(re.escape(word))\n            self.underline_regex(view, lineno, regex, lines, underlines, word)\n\n        def underline_duplicate_argument(lineno, word, underlines):\n            regex = 'def [\\w_]+\\(.*?(?P<underline>[\\w]*{0}[\\w]*)'.format(re.escape(word))\n            self.underline_regex(view, lineno, regex, lines, underlines, word)\n\n        errors.sort(lambda a, b: cmp(a.lineno, b.lineno))\n        ignoreImportStar = view.settings().get('pyflakes_ignore_import_*', True)\n\n        for error in errors:\n            try:\n                error_level = error.level\n            except AttributeError:\n                error_level = 'W'\n            if error_level == 'E':\n                messages = errorMessages\n                underlines = errorUnderlines\n            elif error_level == 'V':\n                messages = violationMessages\n                underlines = violationUnderlines\n            elif error_level == 'W':\n                messages = warningMessages\n                underlines = warningUnderlines\n\n            if isinstance(error, pyflakes.messages.ImportStarUsed) and ignoreImportStar:\n                continue\n\n            self.add_message(error.lineno, lines, str(error), messages)\n\n            if isinstance(error, (Pep8Error, Pep8Warning, OffsetError)):\n                self.underline_range(view, error.lineno, error.offset, underlines)\n\n            elif isinstance(error, (pyflakes.messages.RedefinedWhileUnused,\n                                    pyflakes.messages.UndefinedName,\n                                    pyflakes.messages.UndefinedExport,\n                                    pyflakes.messages.UndefinedLocal,\n                                    pyflakes.messages.Redefined,\n                                    pyflakes.messages.UnusedVariable)):\n                underline_word(error.lineno, error.message, underlines)\n\n            elif isinstance(error, pyflakes.messages.ImportShadowedByLoopVar):\n                underline_for_var(error.lineno, error.message, underlines)\n\n            elif isinstance(error, pyflakes.messages.UnusedImport):\n                underline_import(error.lineno, error.message, underlines)\n\n            elif isinstance(error, pyflakes.messages.ImportStarUsed):\n                underline_import(error.lineno, '*', underlines)\n\n            elif isinstance(error, pyflakes.messages.DuplicateArgument):\n                underline_duplicate_argument(error.lineno, error.message, underlines)\n\n            elif isinstance(error, pyflakes.messages.LateFutureImport):\n                pass\n\n            else:\n                print 'Oops, we missed an error type!', type(error)\n"
  },
  {
    "path": "sublimelinter/modules/ruby-lint.py",
    "content": "import re\n\nfrom base_linter import BaseLinter, INPUT_METHOD_TEMP_FILE\n\nCONFIG = {\n    'language': 'ruby-lint',\n    'executable': 'ruby-lint',\n    'lint_args': '{filename}',\n    'input_method': INPUT_METHOD_TEMP_FILE\n}\n\n\nclass Linter(BaseLinter):\n\n    def parse_errors(self, view, errors, lines, errorUnderlines, violationUnderlines, warningUnderlines, errorMessages, violationMessages, warningMessages):\n        for line in errors.splitlines():\n            match = re.match(r'^.+: (?P<type>.+): line (?P<line>\\d+), column (?P<column>\\d+):\\s+(?P<error>.+)', line)\n\n            if match:\n                error_type, error, line, column = match.group('type'), match.group('error'), match.group('line'), match.group('column')\n                line = int(line)\n                column = int(column)\n                error = '[{0}] {1}'.format(error_type[0].upper(), error)\n\n                if error_type == 'warning':\n                    messages = warningMessages\n                    underlines = warningUnderlines\n                else:\n                    messages = errorMessages\n                    underlines = errorUnderlines\n\n                self.add_message(line, lines, error, messages)\n                self.underline_range(view, line, column, underlines)\n"
  },
  {
    "path": "sublimelinter/modules/ruby.py",
    "content": "import re\n\nfrom base_linter import BaseLinter\n\nCONFIG = {\n    'language': 'Ruby',\n    'executable': 'ruby',\n    'lint_args': '-wc'\n}\n\n\nclass Linter(BaseLinter):\n    def parse_errors(self, view, errors, lines, errorUnderlines, violationUnderlines, warningUnderlines, errorMessages, violationMessages, warningMessages):\n        for line in errors.splitlines():\n            match = re.match(r'^.+:(?P<line>\\d+):\\s+(?P<error>.+)', line)\n\n            if match:\n                error, line = match.group('error'), match.group('line')\n                self.add_message(int(line), lines, error, errorMessages)\n"
  },
  {
    "path": "sublimelinter/modules/squirrel.py",
    "content": "# -*- coding: utf-8 -*-\n# squirrel.py - sublimelint package for checking squirrel files\n\nimport re\n\nfrom base_linter import BaseLinter, INPUT_METHOD_TEMP_FILE\n\nCONFIG = {\n    'language': 'Squirrel',\n    'executable': 'sq',\n    'lint_args': ['-c', '-o', '{filename}', '{filename}'],\n    'input_method': INPUT_METHOD_TEMP_FILE\n}\n\n\nclass Linter(BaseLinter):\n\n    def parse_errors(self, view, errors, lines, errorUnderlines, violationUnderlines, warningUnderlines, errorMessages, violationMessages, warningMessages):\n        print errors\n        for line in errors.splitlines():\n            match = re.match(r'^.*\\sline\\s=\\s\\((?P<line>\\d+)\\)\\scolumn\\s=\\s\\(\\d+\\)\\s:\\s(?P<error>.+)', line)\n\n            if match:\n                error, line = match.group('error'), match.group('line')\n                self.add_message(int(line), lines, error, errorMessages)\n"
  },
  {
    "path": "sublimelinter/modules/sublime_pylint.py",
    "content": "from StringIO import StringIO\nimport tempfile\n\ntry:\n    from pylint import checkers\n    from pylint import lint\n    PYLINT_AVAILABLE = True\nexcept ImportError:\n    PYLINT_AVAILABLE = False\n\nfrom base_linter import BaseLinter\n\nCONFIG = {\n    'language': 'pylint'\n}\n\n\nclass Linter(BaseLinter):\n    def get_executable(self, view):\n        return (PYLINT_AVAILABLE, None, 'built in' if PYLINT_AVAILABLE else 'the pylint module could not be imported')\n\n    def built_in_check(self, view, code, filename):\n        linter = lint.PyLinter()\n        checkers.initialize(linter)\n\n        # Disable some errors.\n        linter.load_command_line_configuration([\n            '--module-rgx=.*',  # don't check the module name\n            '--reports=n',      # remove tables\n            '--persistent=n',   # don't save the old score (no sense for temp)\n        ])\n\n        temp = tempfile.NamedTemporaryFile(suffix='.py')\n        temp.write(code)\n        temp.flush()\n\n        output_buffer = StringIO()\n        linter.reporter.set_output(output_buffer)\n        linter.check(temp.name)\n        report = output_buffer.getvalue().replace(temp.name, 'line ')\n\n        output_buffer.close()\n        temp.close()\n\n        return report\n\n    def remove_unwanted(self, errors):\n        '''remove unwanted warnings'''\n        ## todo: investigate how this can be set by a user preference\n        #  as it appears that the user pylint configuration file is ignored.\n        lines = errors.split('\\n')\n        wanted = []\n        unwanted = [\"Found indentation with tabs instead of spaces\",\n                    \"************* Module\"]\n\n        for line in lines:\n            for not_include in unwanted:\n                if not_include in line:\n                    break\n            else:\n                wanted.append(line)\n\n        return '\\n'.join(wanted)\n\n    def parse_errors(self, view, errors, lines, errorUnderlines, violationUnderlines, warningUnderlines, errorMessages, violationMessages, warningMessages):\n        errors = self.remove_unwanted(errors)\n\n        for line in errors.splitlines():\n            info = line.split(\":\")\n\n            try:\n                lineno = info[1]\n            except IndexError:\n                print info\n\n            message = \":\".join(info[2:])\n            self.add_message(int(lineno), lines, message, errorMessages)\n"
  },
  {
    "path": "sublimelinter/modules/xml.py",
    "content": "import re\n\nfrom base_linter import BaseLinter\n\nCONFIG = {\n    'language': 'XML',\n    'executable': 'xmllint',\n    'lint_args': ['-noout', '-']\n}\n\n\nclass Linter(BaseLinter):\n    def parse_errors(self, view, errors, lines, errorUnderlines, violationUnderlines, warningUnderlines, errorMessages, violationMessages, warningMessages):\n\n        for line in errors.splitlines():\n            match = re.match(r'\\-\\:(?P<line>\\d+): (?P<error>.+)', line)\n\n            if match:\n                error, line = match.group('error'), match.group('line')\n                self.add_message(int(line), lines, error, errorMessages)\n"
  }
]