Full Code of Cleod9/as3js for AI

master ea426d1289a2 cached
26 files
209.3 KB
56.3k tokens
1 symbols
1 requests
Download .txt
Showing preview only (219K chars total). Download the full file or copy to clipboard to get everything.
Repository: Cleod9/as3js
Branch: master
Commit: ea426d1289a2
Files: 26
Total size: 209.3 KB

Directory structure:
gitextract_llgholf1/

├── .gitattributes
├── .gitignore
├── AS3JS.as3proj
├── AS3JS.lxml
├── LICENSE
├── Readme.md
├── bin/
│   └── as3jsc.js
├── build.js
├── index.js
├── lib/
│   └── as3.js
├── package.json
├── runtime.js
├── snippets/
│   ├── class-snippet.js
│   └── main-snippet.js
└── src/
    └── com/
        └── mcleodgaming/
            └── as3js/
                ├── Main.as
                ├── enums/
                │   ├── AS3Encapsulation.as
                │   ├── AS3MemberType.as
                │   ├── AS3ParseState.as
                │   └── AS3Pattern.as
                ├── parser/
                │   ├── AS3Class.as
                │   ├── AS3Parser.as
                │   └── AS3Token.as
                └── types/
                    ├── AS3Argument.as
                    ├── AS3Function.as
                    ├── AS3Member.as
                    └── AS3Variable.as

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitattributes
================================================
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto

# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.js text
*.as text
*.html text
*.less text
*.json text
*.text text
*.bat text
*.sh text

# Declare files that will always have CRLF line endings on checkout.
#*.sln text eol=crlf

# Denote all files that are truly binary and should not be modified.
#*.png binary
#*.jpg binary

================================================
FILE: .gitignore
================================================
node_modules/
runtime-compiled.js


================================================
FILE: AS3JS.as3proj
================================================
<?xml version="1.0" encoding="utf-8"?>
<project version="2">
  <!-- Output SWF options -->
  <output>
    <movie outputType="CustomBuild" />
    <movie input="" />
    <movie path="bin\NewProject.swf" />
    <movie fps="30" />
    <movie width="800" />
    <movie height="600" />
    <movie version="16" />
    <movie minorVersion="0" />
    <movie platform="Flash Player" />
    <movie background="#FFFFFF" />
  </output>
  <!-- Other classes to be compiled into your SWF -->
  <classpaths>
    <class path="src" />
  </classpaths>
  <!-- Build options -->
  <build>
    <option accessible="False" />
    <option advancedTelemetry="False" />
    <option allowSourcePathOverlap="False" />
    <option benchmark="False" />
    <option es="False" />
    <option inline="False" />
    <option locale="" />
    <option loadConfig="" />
    <option optimize="True" />
    <option omitTraces="True" />
    <option showActionScriptWarnings="True" />
    <option showBindingWarnings="True" />
    <option showInvalidCSS="True" />
    <option showDeprecationWarnings="True" />
    <option showUnusedTypeSelectorWarnings="True" />
    <option strict="True" />
    <option useNetwork="True" />
    <option useResourceBundleMetadata="True" />
    <option warnings="True" />
    <option verboseStackTraces="False" />
    <option linkReport="" />
    <option loadExterns="" />
    <option staticLinkRSL="True" />
    <option additional="" />
    <option compilerConstants="" />
    <option minorVersion="" />
  </build>
  <!-- SWC Include Libraries -->
  <includeLibraries>
    <!-- example: <element path="..." /> -->
  </includeLibraries>
  <!-- SWC Libraries -->
  <libraryPaths>
    <!-- example: <element path="..." /> -->
  </libraryPaths>
  <!-- External Libraries -->
  <externalLibraryPaths>
    <!-- example: <element path="..." /> -->
  </externalLibraryPaths>
  <!-- Runtime Shared Libraries -->
  <rslPaths>
    <!-- example: <element path="..." /> -->
  </rslPaths>
  <!-- Intrinsic Libraries -->
  <intrinsics>
    <!-- example: <element path="..." /> -->
  </intrinsics>
  <!-- Assets to embed into the output SWF -->
  <library>
    <!-- example: <asset path="..." id="..." update="..." glyphs="..." mode="..." place="..." sharepoint="..." /> -->
  </library>
  <!-- Class files to compile (other referenced classes will automatically be included) -->
  <compileTargets>
    <compile path="src\com\mcleodgaming\as3js\Main.as" />
  </compileTargets>
  <!-- Paths to exclude from the Project Explorer tree -->
  <hiddenPaths>
    <hidden path="obj" />
  </hiddenPaths>
  <!-- Executed before build -->
  <preBuildCommand>node build.js</preBuildCommand>
  <!-- Executed after build -->
  <postBuildCommand alwaysRun="False" />
  <!-- Other project options -->
  <options>
    <option showHiddenPaths="False" />
    <option testMovie="Unknown" />
    <option testMovieCommand="" />
  </options>
  <!-- Plugin storage -->
  <storage>
    <entry key="at_enabled"><![CDATA[0]]></entry>
    <entry key="at_password"><![CDATA[]]></entry>
  </storage>
</project>

================================================
FILE: AS3JS.lxml
================================================
<?xml version="1.0" encoding="utf-8"?>
<SWCProject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <FlexBinPath />
  <FlashBinPath />
  <FlexIncludeASI>false</FlexIncludeASI>
  <MakeCS3>false</MakeCS3>
  <MakeMXI>false</MakeMXI>
  <IntegrateAsDoc>true</IntegrateAsDoc>
  <LaunchAEM>false</LaunchAEM>
  <MXPIncludeASI>false</MXPIncludeASI>
  <Flex_IgnoreClasses />
  <CS3_IgnoreClasses />
  <CS3_PreviewType>None</CS3_PreviewType>
</SWCProject>

================================================
FILE: LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2015 Greg McLeod <cleod9{at}gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.


================================================
FILE: Readme.md
================================================
# AS3JS (deprecated) #

----------

### NOTICE: Due to lack of interest this project is no longer maintained. ###

I appreciate everyone who starred the project and participated in the discussions. Maybe some day we'll see true strictly typed JavaScript in some other form :)

----------

**NEW:** **Try AS3JS [live in your browser!](https://jsfiddle.net/cleod9/r1kn2cxf/12/embedded/result)** 

AS3JS is a tool written for Node.js that converts ActionScript 3.0 to vanilla JavaScript (originally based on [ImportJS](https://github.com/Cleod9/importjs)). This allows you to write your code using the standard AS3 package structure, and have it automatically converted into a standalone JavaScript file. There are many IDE's out there that can easily parse ActionScript files, so why would you pass up this chance at smart JS code-completion in a program such as [FlashDevelop](http://www.flashdevelop.org/wikidocs/index.php?title=Features:Completion) or [FDT](http://fdt.powerflasher.com/)? **AS3JS even compiles its own source code from AS3 to JS!** :)

So this tool was created with the following goals in mind: 

- Write your code in ActionScript
- Output to **coherent, debugabble** JavaScript!

The best part about AS3JS is that even if you aren't familiar with AS3 you can still use this tool with a very small learning curve. The only real difference between AS3JS and normal JS code is what I'd like to call **"outer syntax"**. The majority of your code stays the same, you just need to change what "surrounds" your code. This should hopefully encourage building a much more organized code base in a large application.


## Features ##

- Converts ActionScript 3.0 code into readable JavaScript output (Structure based on [ImportJS](https://github.com/Cleod9/importjs))
- Recursively parses directories for ActionScript files and automatically resolves import dependencies
- Concatenation into a single .js file
- Support for Vector type syntax (transpiles to a standard Array)
- Support for the '*' wildcard symbol for imports
- Support for AS3's default argument values and the "...rest" argument
- Support for the "super" keyword up to the parent level
- Moderate support for getter/setter methods
- Mix and match with traditional JS code via the global namespace at your leisure
- Ultra fast compilation!

### Experimental features ###
- Allows `require "module_name"` at the package level (do not include semicolon, variable `module_name` will be assigned)

## Setup Instructions ##

**Installation Requirements:**

- [Node.js](http://nodejs.org/)


So the first thing you need in order to use this application is Node.js:

[http://nodejs.org/](http://nodejs.org/)

Once installed, then install AS3JS as a global module via your command line:

```
$ npm install as3js -g
```

If you just want to install as3js into a local project, you can omit the `-g` to run via `./node_modules/.bin/as3js`:

```
$ npm install as3js
```

## Usage ##

### CLI ###

AS3JS can be run as a CLI via the `as3js` command, which has the following parameters:

`-o`, `--output`: Path where the output file will be written (e.g. path/to/output.js)

`-src`, `--sourcepath`: Comma-delimited list of paths to pull source .as files from. It is expected that this path be the root of your project's package directory. So for example, if you defined a package such as `com.myproject`, you would want this value to be the folder that contains the `com` directory. Note that AS3JS processes folders recursively, so you only need to put the path to your top-level folders.

`-h`, `--help`: Outputs help information.

`-v`,`--version`: Outputs version information.

`-s`,`--silent`: Flag to completely silence AS3JS output.

`--verbose`: Flag to enable verbose output. Use to help debug transpiler errors.

`-d`, `--dry`: Perfoms a dry-run of the compilation. This will perform all of the usual compilation steps but skip writing the final output file.

`-e`, `--entry`: This is the entry package class for your application. Uses the format `[mode]:path.to.package.Class`. You replace `[mode]` with either `"instance"` to have AS3JS instantiate the class once your compiled script loads, or `"static"` to have AS3JS return the class function as-is.

`--safe-require` - Puts a try-catch around require statements. Useful for code that may run in both the browser and Node.js

`--ignore-flash` - Ignores imports of flash.* packages (helps silence errors when porting Flash code)

Here is an example command:

```
$ as3js -src ./myas3 -o ./output.js -e new:com.example.MyClass
```

The above example recursively browses through the directory `myas3` finding all `.as` files, converts them to JS, and finally combines the results into a file called `output.js` in the working directory. This script contains your entire application, and will initialize `MyClass` as your entry point.  Simple as that!
### Node Script ###

AS3JS can also be initialized manually within a Node.js script like so:

```js
// Import the compiler
var AS3JS = require('as3js');

// Instantiate the compiler
var as3js = new AS3JS();
var result = as3js.compile({
  srcPaths: ['./src'], // --sourcepath
  silent: false, // --silent
  verbose: false, // --verbose
  entry: "com.my.App", // Entry point class path
  entryMode: "instance", // "instance" or "static"
  safeRequire: false, // --safe-require
  ignoreFlash: false // --ignore-flash
  packages: [] // Provide an array of raw text strings to be parsed as "files"
});

// Gets the compiled source text and do what you want with it
var sourceText = result.compiledSource;

// Example: Prepending the loader source code to the program
var as3jslib = fs.readFileSync('node_modules/as3js/lib/as3.js');
fs.writeFileSync('app.js', as3jslib + '\n' + sourceText, "UTF-8", {flags: 'w+'});
```



## Examples ##

- **[Live browser demo](https://jsfiddle.net/cleod9/r1kn2cxf/12/embedded/result)** - Test out AS3JS right in your browser!

- **[Elevator Engine](https://github.com/cleod9/elevatorjs)** - I wrote this elevator simulator a long time ago in JavaScript and converted it to AS3. What's unique about this one is that the code can also compile to SWF simply by swapping out a single file.

## Limitations ##

Of course since AS3JS is still in alpha it comes with its limitations. See below:

### Event Listeners ###

AS3JS does not enforce class function binding when using them as callbacks. This is commonly an issue when dealing with event listeners. This simply means you will have to manage binding any event listeners on your own. A simple workaround for this is as follows:

```actionscript
//Write a global helper somewhere that anyone can access
var eventHelper = function (context, fn) {
	//Returns a function with the proper binding
	return function () {
		return fn.apply(context, Array.prototype.slice.call(arguments));
	};
};
```
```actionscript
//Usage in AS3
package {
	public class Main {
		public var myFuncBinded:Function;
		public function Main():void {
			//Allows you to use myFuncBinded for guaranteed scope
			myFuncBinded = eventHelper(this, myFunc);
			window.addEventListener("click", myFuncBinded);
		}
		public function myFunc(e:* = null):void {
			//When window is clicked
			console.log("clicked");
		}
	}
}
```
### No True Privates ###

While you can use any of the encapsulation keywords you'd like, there is currently no "true" encapsulation support in AS3JS. Private/protected class properties and methods remain publicly accessible on any instantiated objects. I gave a lot of thought to this and went over many potential solutions. I came to the conclusion that while encapsulation is convenient, in the open world of JavaScript all of this data is easily accessible through basic browser debugging tools. As such, I have no plans to add true encapsulation to AS3JS. The good news is that you can still use the keywords and AS3JS will simply strip them out.

### No Chaining super() ###

AS3JS does not currently support chaining `super` (i.e. `super.super.super.fn()`). If you need such a feature, you can achieve this by using JavaScript in your code:

```actionscript
GreatGrandfather.prototype.fn.call(this, arg1, arg2... etc);
```

### No type validation ###

AS3JS will not validate your types during compile time or runtime. I may add some compile time type checking in the future, but there are no plans for runtime type checking due to unnecessary overhead.

### Typed variable declarations cannot be all on one line ###

I hope to work on this soon, but currently you can't write statements like this:

```actionscript
var a:Type, b:Type, c:Type = 4;
```
If you remove the types it will work fine, but I have not yet implemented anything to strip the types from this type of statement.

### Class-level member variable assignments must be on one line ###

Currently AS3JS doesn't support breaking out something like this into separate lines:

```actionscript
public static var foo:Object = { a: 1, b: 2, c: 3, d: 4, e: 5 };
```
Hopefully you aren't writing such large assignments on class level properties, but for now please write these types of assignments as one-liners.

### Getter/Setter limitations ###

While the getter/setters work pretty well, there are a couple of things you should avoid:

- Assigning a value to a setter that spans multiple lines;
- Accessing a getter from within a getter: (e.g. `myGetter['key'].someOtherGetter`)

AS3JS isn't able to recognize those situations, so it will likely export invalid JS.

### No support for package-level functions ###

This isn't something I've seen used all that often anyway, but if you want to read up on package-level functions see [here](http://blogs.adobe.com/digitalmedia/2011/01/as3-package-level-functions-and-java-static-imports/)

### No casting types ###

I have not implemented the `as` operator, nor can you case with the `Caster(castee)` syntax. The only workaround for now is to re-assign values to a variable that has the proper Type:

```actionscript
var other:SomeOtherType = new SomeOtherType();
var foo:TypeIWant = other;
```

### No `is` support ###

Currently there is no support for type checking via the `is` operator (e.g. `val is Type`) Just stick with `instanceof` for now.

### No `Embed` support ###

Resource embedding is specific to the Flash platform, so I have no plans to implement it at this time.

### Restricted regex support ###

The parser is currently unable to recognize the start and end of a regular expression literal (e.g. `/pattern/`). As such, characters such as `"`, `'`, `{`, `}`, and other patterns may confuse the parser. A simple workaround for this is to use the `RegExp` constructor to define regular expressions that contain these characters (e.g. `new RegExp("pattern")`)


## \*Disclaimer\* ##

**AS3JS cannot currently convert *all* AS3 to proper JS.** While I have put a ton of effort into allowing it to convert 99% of AS3 syntax into JavaScript, the languages are still fundamentally different. There are several things that I have yet to handle, such as casting via the `as` operator, or forcefully binding event callbacks to class instances. This tool is not perfect, however it is quite able to handle a full-fledged personal project. You'll find that  sometimes after compiling without errors there may still be some minor syntax issues in the output, however nearly all of these issues can be avoided very easily with a few code tweaks in your AS3 and are easy to catch (See "Limitations" listed above).

Also I would like to note that **this is not an all-in-one solution** like [FlashJS](http://flashjs.com/), [FlexJS](http://flex.apache.org/download-flexjs.html), [OpenFL](http://www.openfl.org/), or [Randori](http://randoriframework.com/). This is more like what [Jangaroo](http://www.jangaroo.net/home/) was meant to do, but a trillion times simpler. Although AS3JS can be used to create code that is somewhat cross-compatible with Flash, it is still designed with the average JavaScript developer in mind. The philosophy of AS3JS is to greatly simplify the organization of your JavaScript code using AS3 as syntax, not to re-create Flash. You have the freedom to implement Flash AS3 features if you want, but they will not come built into AS3JS.

Lastly, I fully acknowledge the ActionScript name as the property of [Adobe](http://www.adobe.com/). I do not claim ownership of the language nor do I have any affiliation with Adobe, but I do encourage you to check out the [documentation](http://www.adobe.com/devnet/actionscript/learning.html) if you are unfamiliar with ActionScript 3.0. Just remember that AS3JS is made for JavaScript, so many features of Flash AS3 will not be implemented unless you create them yourself.

## Building Source ##

The source code for AS3JS is written in ActionScript 3 under the `src/` folder, and is also set up as a FlashDevelop project. You can compile the source code one of two ways:


- Clicking the Build button in the toolbar of FlashDevelop

OR

- Executing `node build.js` via the command-line

Either of these steps will output a file called `runtime-compiled.js`. Replace `runtime.js` with the contents of `runtime-compiled.js` to update the runtime with your changes.

### Finalizing A Build ###

Since AS3JS's source is written to be compiled by AS3JS itself, if your changes affect the output of compiled files it's important to run the build again and replace `runtime.js` a second AND third time. This ensures that the runtime is using your code as opposed to an outdated runtime. If something is wrong with the build, it will likely fail the third time you attempt to build. It also can't hurt to build a fourth time to ensure the final build is stable.


## Upgrade Notes ##

**Upgrading from v0.1.**: [ImportJS](https://github.com/Cleod9/importjs) and [OOPS.js](https://github.com/Cleod9/oopsjs) are no longer dependencies of this project, so be sure to follow the new setup instructions carefully)

**Upgrading from v0.2.**: AS3JS's responsibilities have been split into two functions: The *compiler*, and the *loader*. The compiler is what converts your AS3 into vanilla JS, but with a few extra features that depend on a separate loader library included in this repo. In browser environments, this is just a matter of using the `./lib/as3.js` as a global script on the page to load your program. For Node.js environments, you'll need to attach AS3JS to the `global` object (details later on below)


## Version History ##

**0.3.3** (Final build)
- Added $cinit() and $init() logic to mimic Flash
- Inferring imports from top-scope member assignments

**0.3.2**
- Handle dictionary class
- Const keyword Removal
- Implicit Static Assignments

**0.3.1**
- Updated Readme
- Improved error messaging when class paths are missing

**0.3.0**

- Documented the Node.js interface for loading the compiler manually
- Split AS3JS roles into "compiler" and "program" (while still maintaining mostly vanilla code)
- Added safeRequire option to allow browser to load code with Node require statements
- Added ignoreFlash option to ignore **flash.*** packages
- Fixed several issues with transpiling classes in the top-level package
- Experimental package-level `require` feature
- New `packages` option that can be used when compiling directly in Node.js (allows injecting raw text packages into the compiler)
- Shipped new live editor with 0.3.* support: https://jsfiddle.net/cleod9/r1kn2cxf/12/embedded/result

**0.2.***

-Created new Vanilla output format that no longer requires external libraries
-Removed ImportJS and OOPS.js as dependencies

**0.1.***

-Initial alpha release

**0.0.1**

-First commit (before conversion of the source code itself to AS3)



----------

Copyrighted © 2017 by Greg McLeod

GitHub: [https://github.com/cleod9](https://github.com/cleod9)

================================================
FILE: bin/as3jsc.js
================================================
#!/usr/bin/env node

/**
* This is the global AS3JS compiler for running 'as3js' as a CLI
**/

var pjson = require('../package.json');
var fs = require('fs');
var path = require('path');
global.AS3JS = require(path.resolve(__dirname, '..', 'lib/as3.js'));
var AS3JS = require(path.resolve(__dirname, '..', 'runtime.js'));

var VERSION = pjson.version;

//AS3JS options
var srcPaths = [];
var output = null;
var silent = false;
var verbose = false;
var entry = '';
var dry = false;
var safeRequire = false;
var ignoreFlash = false;

//Command line args
var arg = null;
var option = null;
var command = null;

//Misc options

//Parse arguemnts
for(var i = 0; i < process.argv.length; i++) {
	arg = process.argv[i];
	if(command) {
		//Commands will go here if implemented
		command = null;
	} else if(option) {
		//Options are set here
		if(option == 'o') {
			output = arg; //File output
		} else if(option == 'src') {
			srcPaths = srcPaths.concat(arg.split(",")); //Source path(s) to parse
		} else if(option == 'e') {
			entry = arg;
		}
		option = null;
	} else {
		if(arg == '--verbose') {
			verbose = true;
		} else if(arg == '-d' || arg == '--dry') {
			dry = true;
		} else if(arg == '-s' || arg == '--silent') {
			silent = true;
		} else if(arg == '--safe-require') {
			safeRequire = true;
		} else if(arg == '-o' || arg == '--output') {
			option = 'o'; //File output
		} else if(arg == '-src' || arg == '--sourcepath') {
			option = 'src'; //Source path(s)
		} else if(arg == '-e' || arg == '--entry') {
			option = 'e'; //Entry point
		} else if(arg == '--ignore-flash') {
			ignoreFlash = true;
		} else if(arg == '-h' || arg == '--help') {
			//Help text
			console.log("Options:");
			console.log("\t[-o|--output]\t\tOutput file");
			console.log("\t[-src|-sourcepath]\tSource Path(s) (comma-separated)");
			console.log("\t[-d|--dry]\tDry-run mode");
			console.log("\t[-e|--entry]\t\tEntry point (ex. \"[instance|static]:com.example.MyClass\")");
			console.log("\t[-h|--help]\t\tView Help");
			console.log("\t[-v|--version]\t\tView Version information");
			console.log("\t[--verbose]\t\tVerbose console output");
			console.log("\t[--safe-require]\t\tTry-catch require() statements");
			console.log("\t[--ignore-flash]\t\tIgnore flash.* imports");
			
			return;
		} else if(arg == '-v' || arg == '--version') {
			//Version info
			console.log("AS3JS for Node.js");
			console.log("Created by Greg McLeod (c) 2017");
			console.log("Version: " + VERSION);
			return;
		}
	}
}

if(srcPaths.length <= 0) {
	console.log("Error, must supply source path (-src)");
} else if(!output) {
	console.log("Error, must supply output path (-o)");
} else {
	var as3js = new AS3JS();
	var sourceText = as3js.compile({
		srcPaths: srcPaths,
		silent: silent,
		verbose: verbose,
		entry: entry.split(':')[1],
		entryMode: entry.split(':')[0],
		safeRequire: safeRequire,
		ignoreFlash: ignoreFlash
	}).compiledSource;
	
	//Remove old output file if it exists
	if (output && !dry)
	{
		if (fs.existsSync(output))
		{
			fs.unlinkSync(output);
		}
		fs.writeFileSync(output || 'output.js', sourceText, "UTF-8", {flags: 'w+'});
	}
}


================================================
FILE: build.js
================================================
var fs = require('fs');
var beautify = require('js-beautify').js_beautify;
// Pull in loader library first
global.AS3JS = require('./lib/as3.js');
// Now Pull in the actual AS3JS program
var AS3JS = require('./runtime.js');

// Load the program
var as3js = new AS3JS();

// Execute the program 
var sourceText = as3js.compile({
	srcPaths: ['./src'],
	silent: false,
	verbose: false,
	safeRequire: true,
	entry: 'com.mcleodgaming.as3js.Main',
	entryMode: 'static'
}).compiledSource;

// Output the resulting source code
if (fs.existsSync('runtime-compiled.js'))
{
	fs.unlinkSync('runtime-compiled.js');
}
fs.writeFileSync('runtime-compiled.js', beautify(sourceText, { indent_size: 2, max_preserve_newlines: 2 }), "UTF-8", {flags: 'w+'});

================================================
FILE: index.js
================================================
global.AS3JS = require('./lib/as3.js');

module.exports = require('./runtime.js');

================================================
FILE: lib/as3.js
================================================
/*******************************
  AS3JS Version 0.3.3
  
    AS3 to JS converter for use with ImportJS and OOPS.js.
  
  The MIT License (MIT)

  Copyright (c) 2017 Greg McLeod <cleod9{at}gmail.com>

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:

  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE.
*******************************/
(function ( ) {
  var AS3JS = {
    Utils: {
      // Helper for default args
      getDefaultValue: function getDefaultValue(value, fallback) {
        return (typeof value != 'undefined') ? value : fallback;
      },
      // Helper for Vector/Array constructors
	  createArray: function (size, val) {
        var arr = [];
        for (var i = 0; i < size; i++)  {
          arr.push(val); 
        }
        return arr;
      }
    },
    load: function ( params ) {
      // Loads program specified by params
      params = params || {};
	  params.entryMode = params.entryMode || 'instance';
	
      // Shim just in case
      if (typeof Object.create !== 'function') {
        Object.create = function (o) {
          function F() {}
          F.prototype = o;
          return new F();
        }
      };

      // Some temps / helper
      var i, j, tmpPkg;
      var getPackageInfo = function ( name ) {
        // Splits package path into separate package and class name
        var pkg = name.split('.');
        var className = pkg[pkg.length-1];
        pkg.splice(pkg.length-1, 1);
        var packageName = pkg.join('.');

        return { 
          packageName: packageName,
          className: className
        };
      };

      // This hash map contains each package, each package contains its classes
      var packages = {};

      // Converts supplied package hash to packageName.className.{ source: moduleFn }
      for (i in params.program) {
        tmpPkg = getPackageInfo(i);
        packages[tmpPkg.packageName] = packages[tmpPkg.packageName] || {};
        packages[tmpPkg.packageName][tmpPkg.className] = { compiled: false, source: params.program[i] };
      }

      // This helper will execute the module source specified by "name" and return its exports object
      var imports = function ( packageName, className ) {
        // Only run source() if it hasn't been compiled yet
        if (!packages[packageName][className].compiled) {
          packages[packageName][className].compiled = true;
          packages[packageName][className].module = { exports: null, inject: null, import: imports };
          //This next line actually compiles the module
          packages[packageName][className].source(packages[packageName][className].module, packages[packageName][className].module.exports);
        }
        // Returns the compiled module
        return packages[packageName][className].module.exports;
      };

      // Compiles all packages
      for (i in packages) {
        for (j in packages[i]) {
          imports(i, j);
        }
      }
	
      // Run inject() and $cinit() functions as the final step (this trivializes circular dependencies)
      for (i in packages) {
        // Execute the injection functions
        for (j in packages[i]) {
          if (typeof packages[i][j].module.inject === 'function') {
            packages[i][j].module.inject();
          }
        }
      }
      for (i in packages) {
        // Execute the $cinit functions
        for (j in packages[i]) {
          if (typeof packages[i][j].module.exports.$cinit === 'function') {
            packages[i][j].module.exports.$cinit();
          }
        }
      }

      // Initializes application
      var entryPkgInfo = getPackageInfo(params.entry);
      var entryPoint = imports(entryPkgInfo.packageName, entryPkgInfo.className);
      if (params.entryMode === "instance") {
        return new entryPoint();
      } else if (params.entryMode === "static") {
        return entryPoint;
      }
    }
  };
  
  if (typeof module !== 'undefined') {
    //CommonJS
    module.exports = AS3JS;
  } else {
    //Browser Global
    window.AS3JS = AS3JS;
  }
})();

================================================
FILE: package.json
================================================
{
	"name": "as3js",
	"version": "0.3.3",
	"author": "Greg McLeod <cleod9@gmail.com>",
	"description": "AS3 to JS converter.",
	"bin": {
		"as3js": "./bin/as3jsc.js"
	},
	"devDependencies": {
		"js-beautify": "1.5.10"
	},
	"main": "./index.js",
	"repository": {
		"type": "git",
		"url": "https://github.com/cleod9/as3js"
	},
	"keywords": [
		"as3",
		"js",
		"converter",
		"import",
		"oop"
	],
	"license": "MIT"
}


================================================
FILE: runtime.js
================================================
(function() {
  var Program = {};
  Program["com.mcleodgaming.as3js.enums.AS3Encapsulation"] = function(module, exports) {
    var AS3Encapsulation = function AS3Encapsulation() {};

    AS3Encapsulation.PUBLIC = null;
    AS3Encapsulation.PRIVATE = null;
    AS3Encapsulation.PROTECTED = null;

    AS3Encapsulation.$cinit = function() {
      AS3Encapsulation.PUBLIC = "public";
      AS3Encapsulation.PRIVATE = "private";
      AS3Encapsulation.PROTECTED = "protected";

    };

    AS3Encapsulation.prototype.$init = function() {}

    module.exports = AS3Encapsulation;
  };
  Program["com.mcleodgaming.as3js.enums.AS3MemberType"] = function(module, exports) {
    var AS3MemberType = function AS3MemberType() {};

    AS3MemberType.VAR = null;
    AS3MemberType.CONST = null;
    AS3MemberType.FUNCTION = null;

    AS3MemberType.$cinit = function() {
      AS3MemberType.VAR = "var";
      AS3MemberType.CONST = "const";
      AS3MemberType.FUNCTION = "function";

    };

    AS3MemberType.prototype.$init = function() {}

    module.exports = AS3MemberType;
  };
  Program["com.mcleodgaming.as3js.enums.AS3ParseState"] = function(module, exports) {
    var AS3ParseState = function AS3ParseState() {};

    AS3ParseState.START = null;
    AS3ParseState.PACKAGE_NAME = null;
    AS3ParseState.PACKAGE = null;
    AS3ParseState.CLASS_NAME = null;
    AS3ParseState.CLASS = null;
    AS3ParseState.CLASS_EXTENDS = null;
    AS3ParseState.CLASS_IMPLEMENTS = null;
    AS3ParseState.COMMENT_INLINE = null;
    AS3ParseState.COMMENT_MULTILINE = null;
    AS3ParseState.STRING_SINGLE_QUOTE = null;
    AS3ParseState.STRING_DOUBLE_QUOTE = null;
    AS3ParseState.STRING_REGEX = null;
    AS3ParseState.MEMBER_VARIABLE = null;
    AS3ParseState.MEMBER_FUNCTION = null;
    AS3ParseState.LOCAL_VARIABLE = null;
    AS3ParseState.LOCAL_FUNCTION = null;
    AS3ParseState.IMPORT_PACKAGE = null;
    AS3ParseState.REQUIRE_MODULE = null;

    AS3ParseState.$cinit = function() {
      AS3ParseState.START = "start";
      AS3ParseState.PACKAGE_NAME = "packageName";
      AS3ParseState.PACKAGE = "package";
      AS3ParseState.CLASS_NAME = "className";
      AS3ParseState.CLASS = "class";
      AS3ParseState.CLASS_EXTENDS = "classExtends";
      AS3ParseState.CLASS_IMPLEMENTS = "classImplements";
      AS3ParseState.COMMENT_INLINE = "commentInline";
      AS3ParseState.COMMENT_MULTILINE = "commentMultiline";
      AS3ParseState.STRING_SINGLE_QUOTE = "stringSingleQuote";
      AS3ParseState.STRING_DOUBLE_QUOTE = "stringDoubleQuote";
      AS3ParseState.STRING_REGEX = "stringRegex";
      AS3ParseState.MEMBER_VARIABLE = "memberVariable";
      AS3ParseState.MEMBER_FUNCTION = "memberFunction";
      AS3ParseState.LOCAL_VARIABLE = "localVariable";
      AS3ParseState.LOCAL_FUNCTION = "localFunction";
      AS3ParseState.IMPORT_PACKAGE = "importPackage";
      AS3ParseState.REQUIRE_MODULE = "requireModule";

    };

    AS3ParseState.prototype.$init = function() {}

    module.exports = AS3ParseState;
  };
  Program["com.mcleodgaming.as3js.enums.AS3Pattern"] = function(module, exports) {
    var AS3Pattern = function AS3Pattern() {};

    AS3Pattern.IDENTIFIER = null;
    AS3Pattern.OBJECT = null;
    AS3Pattern.IMPORT = null;
    AS3Pattern.REQUIRE = null;
    AS3Pattern.CURLY_BRACE = null;
    AS3Pattern.VARIABLE = null;
    AS3Pattern.VARIABLE_TYPE = null;
    AS3Pattern.VARIABLE_DECLARATION = null;
    AS3Pattern.ASSIGN_START = null;
    AS3Pattern.ASSIGN_UPTO = null;
    AS3Pattern.VECTOR = null;
    AS3Pattern.ARRAY = null;
    AS3Pattern.DICTIONARY = null;
    AS3Pattern.REST_ARG = null;

    AS3Pattern.$cinit = function() {
      AS3Pattern.IDENTIFIER = [/\w/g, /\w/g];
      AS3Pattern.OBJECT = [/[\w\.]/g, /[\w(\w(\.\w)+)]/g];
      AS3Pattern.IMPORT = [/[0-9a-zA-Z_$.*]/g, /[a-zA-Z_$][0-9a-zA-Z_$]([.][a-zA-Z_$][0-9a-zA-Z_$])*\*?/g];
      AS3Pattern.REQUIRE = [/./g, /["'](.*?)['"]/g];
      AS3Pattern.CURLY_BRACE = [/[\{|\}]/g, /[\{|\}]/g];
      AS3Pattern.VARIABLE = [/[0-9a-zA-Z_$]/g, /[a-zA-Z_$][0-9a-zA-Z_$]*/g];
      AS3Pattern.VARIABLE_TYPE = [/[a-zA-Z_$<>.*][0-9a-zA-Z_$<>.]*/g, /[a-zA-Z_$<>.*][0-9a-zA-Z_$<>.]*/g];
      AS3Pattern.VARIABLE_DECLARATION = [/[0-9a-zA-Z_$:<>.*]/g, /[a-zA-Z_$][0-9a-zA-Z_$]*\s*:\s*([a-zA-Z_$<>\.\*][0-9a-zA-Z_$<>\.]*)/g];
      AS3Pattern.ASSIGN_START = [/[=\r\n]/g, /[=\r\n]/g];
      AS3Pattern.ASSIGN_UPTO = [new RegExp("[^;\\r\\n]", "g"), /(.*?)/g];
      AS3Pattern.VECTOR = [/new[\s\t]+Vector\.<(.*?)>\((.*?)\)/g, /new[\s\t]+Vector\.<(.*?)>\((.*?)\)/];
      AS3Pattern.ARRAY = [/new[\s\t]+Array\((.*?)\)/g, /new[\s\t]+Array\((.*?)\)/];
      AS3Pattern.DICTIONARY = [/new[\s\t]+Dictionary\((.*?)\)/g];
      AS3Pattern.REST_ARG = [/\.\.\.[a-zA-Z_$][0-9a-zA-Z_$]*/g, /\.\.\.[a-zA-Z_$][0-9a-zA-Z_$]*/g];

    };

    AS3Pattern.prototype.$init = function() {}

    module.exports = AS3Pattern;
  };
  Program["com.mcleodgaming.as3js.Main"] = function(module, exports) {
    var path = (function() {
      try {
        return require("path");
      } catch (e) {
        return undefined;
      }
    })();
    var fs = (function() {
      try {
        return require("fs");
      } catch (e) {
        return undefined;
      }
    })();

    var AS3Parser;
    module.inject = function() {
      AS3Parser = module.import('com.mcleodgaming.as3js.parser', 'AS3Parser');
    };

    var Main = function() {
      this.$init();

    };

    Main.DEBUG_MODE = false;
    Main.SILENT = false;
    Main.debug = function() {
      if (Main.SILENT) {
        return;
      }
      if (Main.DEBUG_MODE) {
        console.log.apply(console, arguments);
      }
    };
    Main.log = function() {
      if (Main.SILENT) {
        return;
      }
      console.log.apply(console, arguments);
    };
    Main.warn = function() {
      if (Main.SILENT) {
        return;
      }
      console.warn.apply(console, arguments);
    };

    Main.$cinit = function() {
      Main.DEBUG_MODE = false;
      Main.SILENT = false;

    };

    Main.prototype.$init = function() {};
    Main.prototype.compile = function(options) {
      options = AS3JS.Utils.getDefaultValue(options, null);
      var packages = {}; //Will contain the final map of package names to source text
      var i;
      var j;
      var k;
      var m;
      var tmp;
      options = options || {};
      var srcPaths = options.srcPaths || {};
      var rawPackages = options.rawPackages || [];
      var parserOptions = {
        safeRequire: options.safeRequire,
        ignoreFlash: options.ignoreFlash
      };

      //Temp classes for holding raw class info
      var rawClass;
      var rawParser;

      var pkgLists = {};
      for (i in srcPaths) {
        pkgLists[srcPaths[i]] = this.buildPackageList(srcPaths[i]);
      }

      Main.DEBUG_MODE = options.verbose || Main.DEBUG_MODE;
      Main.SILENT = options.silent || Main.SILENT;

      var classes = {};
      var buffer = "";

      //First, parse through the file-based classes and get the basic information
      for (i in pkgLists) {
        for (j in pkgLists[i]) {
          Main.log('Analyzing class path: ' + pkgLists[i][j].classPath);
          classes[pkgLists[i][j].classPath] = pkgLists[i][j].parse(parserOptions);
          Main.debug(classes[pkgLists[i][j].classPath]);
        }
      }

      // Now parse through any raw string classes
      for (i = 0; i < rawPackages.length; i++) {
        Main.log('Analyzing class: ' + i);
        rawParser = new AS3Parser(rawPackages[i]);
        rawClass = rawParser.parse(parserOptions);
        classes[rawParser.classPath] = rawClass;
      }

      //Resolve all possible package name wildcards
      for (i in classes) {
        //For every class
        for (j in classes[i].importWildcards) {
          Main.debug('Resolving ' + classes[i].className + '\'s ' + classes[i].importWildcards[j] + ' ...')
            //For every wild card in the class
          for (k in srcPaths) {
            //For each possible source path (should hopefully just be 1 most of the time -_-)
            tmp = srcPaths[k] + path.sep + classes[i].importWildcards[j].replace(/\./g, path.sep).replace(path.sep + '*', '');
            tmp = tmp.replace(/\\/g, '/');
            tmp = tmp.replace(/[\/]/g, path.sep);
            if (fs.existsSync(tmp)) {
              Main.debug('Searching path ' + tmp + '...')
                //Path exists, read the files in the directory
              var files = fs.readdirSync(tmp);
              for (m in files) {
                //See if this is an ActionScript file
                if (fs.statSync(tmp + path.sep + files[m]).isFile() && files[m].lastIndexOf('.as') == files[m].length - 3) {
                  //See if the class needs the file
                  if (classes[i].needsImport(classes[i].importWildcards[j].replace(/\*/g, files[m].substr(0, files[m].length - 3)))) {
                    Main.debug('Auto imported ' + files[m].substr(0, files[m].length - 3));
                    classes[i].addImport(classes[i].importWildcards[j].replace(/\*/g, files[m].substr(0, files[m].length - 3))); //Pass in package name with wild card replaced
                  }
                }
              }
            } else {
              Main.warn('Warning, could not find directory: ' + tmp);
            }
          }
          // Must do again for classes in case there we
          for (k in classes) {
            if (classes[i].needsImport(AS3Parser.fixClassPath(classes[k].packageName + '.' + classes[k].className))) {
              Main.debug('Auto imported ' + AS3Parser.fixClassPath(classes[k].packageName + '.' + classes[k].className));
              classes[i].addImport(AS3Parser.fixClassPath(classes[k].packageName + '.' + classes[k].className)); //Pass in package name with wild card replaced
            }
          }
        }
      }

      //Add extra imports before registring them (these will not be imported in the output code, but rather will provide insight for AS3JS to determine variable types)
      for (i in classes) {
        for (j in classes) {
          classes[i].addExtraImport(AS3Parser.fixClassPath(classes[j].packageName + '.' + classes[j].className));
        }
      }

      //Resolve import map
      for (i in classes) {
        classes[i].registerImports(classes);
      }

      //Resolve parent imports
      for (i in classes) {
        classes[i].findParents(classes);
      }

      //Walk through the class members that had assignments in the class scope
      for (i in classes) {
        classes[i].checkMembersWithAssignments();
      }

      //Process the function text to comply with JS
      for (i in classes) {
        Main.log('Parsing package: ' + AS3Parser.fixClassPath(classes[i].packageName + "." + classes[i].className));
        classes[i].process(classes);
      }
      // Load stringified versions of snippets/main-snippet.js and snippets/class-snippet.js
      var mainTemplate = "(function(){var Program={};{{packages}}if(typeof module !== 'undefined'){module.exports=AS3JS.load({program:Program,entry:\"{{entryPoint}}\",entryMode:\"{{entryMode}}\"});}else if(typeof window!=='undefined'&&typeof AS3JS!=='undefined'){window['{{entryPoint}}']=AS3JS.load({program:Program,entry:\"{{entryPoint}}\",entryMode:\"{{entryMode}}\"});}})();";
      var classTemplate = "Program[\"{{module}}\"]=function(module, exports){{{source}}};";
      var packageObjects = [];
      var classObjects = null;
      var currentClass = "";

      if (options.entry) {
        // Entry point should be in the format "mode:path.to.package.Class"
        var currentPackage = options.entry;
        var mode = options.entryMode || 'instance';
        // Update template with entry points
        mainTemplate = mainTemplate.replace(/\{\{entryPoint\}\}/g, AS3Parser.fixClassPath(classes[currentPackage].packageName + '.' + classes[currentPackage].className));
        mainTemplate = mainTemplate.replace(/\{\{entryMode\}\}/g, mode);
      } else {
        mainTemplate = mainTemplate.replace(/\{\{entryPoint\}\}/g, "");
        mainTemplate = mainTemplate.replace(/\{\{entryMode\}\}/g, "");
      }

      //Retrieve converted class code
      var groupByPackage = {};
      for (i in classes) {
        groupByPackage[classes[i].packageName] = groupByPackage[classes[i].packageName] || [];
        groupByPackage[classes[i].packageName].push(classes[i]);
      }
      for (i in groupByPackage) {
        classObjects = [];
        for (j in groupByPackage[i]) {
          packages[AS3Parser.fixClassPath(i + "." + groupByPackage[i][j].className)] = groupByPackage[i][j].toString();
          currentClass = classTemplate;
          currentClass = currentClass.replace(/\{\{module\}\}/g, AS3Parser.fixClassPath(groupByPackage[i][j].packageName + "." + groupByPackage[i][j].className));
          currentClass = currentClass.replace(/\{\{source\}\}/g, AS3Parser.increaseIndent(packages[AS3Parser.fixClassPath(i + "." + groupByPackage[i][j].className)], "  "));
          classObjects.push(currentClass);
        }
        packageObjects.push(AS3Parser.increaseIndent(classObjects.join(""), "  "));
      }

      mainTemplate = mainTemplate.replace(/\{\{packages\}\}/g, packageObjects.join(""));

      mainTemplate = mainTemplate.replace(/\t/g, "  ");

      buffer += mainTemplate;

      Main.log("Done.");

      return {
        compiledSource: buffer,
        packageSources: packages
      };
    };
    Main.prototype.readDirectory = function(location, pkgBuffer, obj) {
      var files = fs.readdirSync(location);
      for (var i in files) {
        var pkg = pkgBuffer;
        if (fs.statSync(location + path.sep + files[i]).isDirectory()) {
          var splitPath = location.split(path.sep);
          if (pkg != '') {
            pkg += '.';
          }
          this.readDirectory(location + path.sep + files[i], pkg + files[i], obj)
        } else if (fs.statSync(location + path.sep + files[i]).isFile() && files[i].lastIndexOf('.as') == files[i].length - 3) {
          if (pkg != '') {
            pkg += '.';
          }
          pkg += files[i].substr(0, files[i].length - 3);
          var f = fs.readFileSync(location + path.sep + files[i]);
          obj[pkg] = new AS3Parser(f.toString(), pkg);
          Main.debug("Loaded file: ", location + path.sep + files[i] + " (package: " + pkg + ")");
        }
      }
    };
    Main.prototype.buildPackageList = function(location) {
      var obj = {};
      var topLevel = location;
      location = location.replace(/\\/g, '/');
      location = location.replace(/[\/]/g, path.sep);
      if (fs.existsSync(location) && fs.statSync(location).isDirectory()) {
        var splitPath = location.split(path.sep);
        this.readDirectory(location, '', obj);
        return obj;
      } else {
        throw new Error("Error could not find directory: " + location);
      }
    }

    module.exports = Main;
  };
  Program["com.mcleodgaming.as3js.parser.AS3Class"] = function(module, exports) {
    var Main, AS3Parser, AS3MemberType, AS3Pattern, AS3Function, AS3Variable;
    module.inject = function() {
      Main = module.import('com.mcleodgaming.as3js', 'Main');
      AS3Parser = module.import('com.mcleodgaming.as3js.parser', 'AS3Parser');
      AS3MemberType = module.import('com.mcleodgaming.as3js.enums', 'AS3MemberType');
      AS3Pattern = module.import('com.mcleodgaming.as3js.enums', 'AS3Pattern');
      AS3Function = module.import('com.mcleodgaming.as3js.types', 'AS3Function');
      AS3Variable = module.import('com.mcleodgaming.as3js.types', 'AS3Variable');
    };

    var AS3Class = function(options) {
      this.$init();
      options = AS3JS.Utils.getDefaultValue(options, null);
      options = options || {};
      this.safeRequire = false;

      if (typeof options.safeRequire !== 'undefined') {
        this.safeRequire = options.safeRequire;
      }
      if (typeof options.ignoreFlash !== 'undefined') {
        this.ignoreFlash = options.ignoreFlash;
      }

      this.packageName = null;
      this.className = null;
      this.imports = [];
      this.requires = [];
      this.importWildcards = [];
      this.importExtras = [];
      this.interfaces = [];
      this.parent = null;
      this.parentDefinition = null;
      this.members = [];
      this.staticMembers = [];
      this.getters = [];
      this.setters = [];
      this.staticGetters = [];
      this.staticSetters = [];
      this.membersWithAssignments = [];
      this.isInterface = false;
      this.fieldMap = {};
      this.staticFieldMap = {};
      this.classMap = {};
      this.classMapFiltered = {};
      this.packageMap = {};

      var $init = new AS3Function();
      $init.name = "$init";
      $init.value = "{}";
      $init.type === AS3MemberType.FUNCTION;
      $init.isStatic = false;
      this.members.push($init);
      this.registerField($init.name, $init);
    };

    AS3Class.reservedWords = null;
    AS3Class.nativeTypes = null;

    AS3Class.$cinit = function() {
      AS3Class.reservedWords = ["as", "class", "delete", "false", "if", "instanceof", "native", "private", "super", "to", "use", "with", "break", "const", "do", "finally", "implements", "new", "protected", "switch", "true", "var", "case", "continue", "else", "for", "import", "internal", "null", "public", "this", "try", "void", "catch", "default", "extends", "function", "in", "is", "package", "return", "throw", "typeof", "while", "each", "get", "set", "namespace", "include", "dynamic", "final", "natiev", "override", "static", "abstract", "char", "export", "long", "throws", "virtual", "boolean", "debugger", "float", "prototype", "to", "volatile", "byte", "double", "goto", "short", "transient", "cast", "enum", "intrinsic", "synchronized", "type"];
      AS3Class.nativeTypes = ["Boolean", "Number", "int", "uint", "String"];

    };

    AS3Class.prototype.$init = function() {
      this.imports = null;
      this.requires = null;
      this.importWildcards = null;
      this.importExtras = null;
      this.interfaces = null;
      this.parentDefinition = null;
      this.members = null;
      this.staticMembers = null;
      this.getters = null;
      this.setters = null;
      this.staticGetters = null;
      this.staticSetters = null;
      this.membersWithAssignments = null;
      this.fieldMap = null;
      this.staticFieldMap = null;
      this.classMap = null;
      this.classMapFiltered = null;
      this.packageMap = null;
    };
    AS3Class.prototype.packageName = null;
    AS3Class.prototype.className = null;
    AS3Class.prototype.imports = null;
    AS3Class.prototype.requires = null;
    AS3Class.prototype.importWildcards = null;
    AS3Class.prototype.importExtras = null;
    AS3Class.prototype.interfaces = null;
    AS3Class.prototype.parent = null;
    AS3Class.prototype.parentDefinition = null;
    AS3Class.prototype.members = null;
    AS3Class.prototype.staticMembers = null;
    AS3Class.prototype.getters = null;
    AS3Class.prototype.setters = null;
    AS3Class.prototype.staticGetters = null;
    AS3Class.prototype.staticSetters = null;
    AS3Class.prototype.isInterface = false;
    AS3Class.prototype.membersWithAssignments = null;
    AS3Class.prototype.fieldMap = null;
    AS3Class.prototype.staticFieldMap = null;
    AS3Class.prototype.classMap = null;
    AS3Class.prototype.classMapFiltered = null;
    AS3Class.prototype.packageMap = null;
    AS3Class.prototype.safeRequire = false;
    AS3Class.prototype.ignoreFlash = false;
    AS3Class.prototype.registerImports = function(clsList) {
      var i;
      for (i in this.imports) {
        if (clsList[this.imports[i]]) {
          var lastIndex = this.imports[i].lastIndexOf(".");
          var shorthand = (lastIndex < 0) ? this.imports[i] : this.imports[i].substr(lastIndex + 1);
          this.classMap[shorthand] = clsList[this.imports[i]];
        }
      }
      for (i in this.importExtras) {
        if (clsList[this.importExtras[i]]) {
          var lastIndex = this.importExtras[i].lastIndexOf(".");
          var shorthand = (lastIndex < 0) ? this.importExtras[i] : this.importExtras[i].substr(lastIndex + 1);
          this.classMap[shorthand] = clsList[this.importExtras[i]];
        }
      }
      this.packageMap = clsList;
    };
    AS3Class.prototype.registerField = function(name, value) {
      if (value && value.isStatic) {
        this.staticFieldMap[name] = this.staticFieldMap[name] || value;
      } else {
        this.fieldMap[name] = this.fieldMap[name] || value;
      }
    };
    AS3Class.prototype.retrieveField = function(name, isStatic) {
      if (isStatic) {
        if (this.staticFieldMap[name]) {
          return this.staticFieldMap[name];
        } else if (this.parentDefinition) {
          return this.parentDefinition.retrieveField(name, isStatic);
        } else {
          return null;
        }
      } else {
        if (this.fieldMap[name]) {
          return this.fieldMap[name];
        } else if (this.parentDefinition) {
          return this.parentDefinition.retrieveField(name, isStatic);
        } else {
          return null;
        }
      }
    };
    AS3Class.prototype.needsImport = function(pkg) {
      var i;
      var j;
      var lastIndex = pkg.lastIndexOf(".");
      var shorthand = (lastIndex < 0) ? pkg : pkg.substr(lastIndex + 1);
      var matches;

      if (this.imports.indexOf(pkg) >= 0) {
        return false; //Class was already imported
      }

      if (shorthand == this.className && pkg == this.packageName) {
        return true; //Don't need self
      }

      if (shorthand == this.parent) {
        return true; //Parent class is in another package
      }

      //Now we must parse through all members one by one, looking at functions and variable types to determine the necessary imports

      for (i in this.members) {
        //See if the function definition or variable assigment have a need for this package
        if (this.members[i] instanceof AS3Function) {
          matches = this.members[i].value.match(AS3Pattern.VARIABLE_DECLARATION[1]);
          for (j in matches) {
            if (matches[j].split(":")[1] == shorthand)
              return true;
          }
          for (j in this.members[i].argList) {
            if (typeof this.members[i].argList[j].type == 'string' && this.members[i].argList[j].type == shorthand)
              return true;
          }
        }
        if (typeof this.members[i].value == 'string' && this.members[i].value.match(new RegExp("([^a-zA-Z_$.])" + shorthand + "([^0-9a-zA-Z_$])", "g"))) {
          return true;
        } else if (typeof this.members[i].type == 'string' && this.members[i].type == shorthand) {
          return true;
        }
      }
      for (i in this.staticMembers) {
        //See if the function definition or variable assigment have a need for this package
        if (this.staticMembers[i] instanceof AS3Function) {
          matches = this.staticMembers[i].value.match(AS3Pattern.VARIABLE_DECLARATION[1]);
          for (j in matches) {
            if (matches[j].split(":")[1] == shorthand) {
              return true;
            }
          }
          for (j in this.staticMembers[i].argList) {
            if (typeof this.staticMembers[i].argList[j].type == 'string' && this.staticMembers[i].argList[j].type == shorthand) {
              return true;
            }
          }
        }
        if (typeof this.staticMembers[i].value == 'string' && this.staticMembers[i].value.match(new RegExp("([^a-zA-Z_$.])" + shorthand + "([^0-9a-zA-Z_$])", "g"))) {
          return true;
        } else if (typeof this.staticMembers[i].type == 'string' && this.staticMembers[i].type == shorthand) {
          return true;
        }
      }
      for (i in this.getters) {
        //See if the function definition or variable assigment have a need for this package
        matches = this.getters[i].value.match(AS3Pattern.VARIABLE_DECLARATION[1]);
        for (j in matches) {
          if (matches[j].split(":")[1] == shorthand) {
            return true;
          }
        }
        for (j in this.getters[i].argList) {
          if (typeof this.getters[i].argList[j].type == 'string' && this.getters[i].argList[j].type == shorthand) {
            return true;
          }
        }
        if (typeof this.getters[i].value == 'string' && this.getters[i].value.match(new RegExp("([^a-zA-Z_$.])" + shorthand + "([^0-9a-zA-Z_$])", "g"))) {
          return true;
        } else if (typeof this.getters[i].type == 'string' && this.getters[i].type == shorthand) {
          return true;
        }
      }
      for (i in this.setters) {
        matches = this.setters[i].value.match(AS3Pattern.VARIABLE_DECLARATION[1]);
        for (j in matches) {
          if (matches[j].split(":")[1] == shorthand) {
            return true;
          }
        }
        //See if the function definition or variable assigment have a need for this package
        for (j in this.setters[i].argList) {
          if (typeof this.setters[i].argList[j].type == 'string' && this.setters[i].argList[j].type == shorthand) {
            return true;
          }
        }
        if (typeof this.setters[i].value == 'string' && this.setters[i].value.match(new RegExp("([^a-zA-Z_$.])" + shorthand + "([^0-9a-zA-Z_$])", "g"))) {
          return true;
        } else if (typeof this.setters[i].type == 'string' && this.setters[i].type == shorthand) {
          return true;
        }
      }
      for (i in this.staticGetters) {
        matches = this.staticGetters[i].value.match(AS3Pattern.VARIABLE_DECLARATION[1]);
        for (j in matches) {
          if (matches[j].split(":")[1] == shorthand) {
            return true;
          }
        }
        //See if the function definition or variable assigment have a need for this package
        for (j in this.staticGetters[i].argList) {
          if (typeof this.staticGetters[i].argList[j].type == 'string' && this.staticGetters[i].argList[j].type == shorthand) {
            return true;
          }
        }
        if (typeof this.staticGetters[i].value == 'string' && this.staticGetters[i].value.match(new RegExp("([^a-zA-Z_$.])" + shorthand + "([^0-9a-zA-Z_$])", "g"))) {
          return true;
        } else if (typeof this.staticGetters[i].type == 'string' && this.staticGetters[i].type == shorthand) {
          return true;
        }
      }
      for (i in this.staticSetters) {
        matches = this.staticSetters[i].value.match(AS3Pattern.VARIABLE_DECLARATION[1]);
        for (j in matches) {
          if (matches[j].split(":")[1] == shorthand) {
            return true;
          }
        }
        for (j in this.staticSetters[i].argList) {
          if (typeof this.staticSetters[i].argList[j].type == 'string' && this.staticSetters[i].argList[j].type == shorthand) {
            return true;
          }
        }
        //See if the function definition or variable assigment have a need for this package
        if (typeof this.staticSetters[i].value == 'string' && this.staticSetters[i].value.match(new RegExp("([^a-zA-Z_$.])" + shorthand + "([^0-9a-zA-Z_$])", "g"))) {
          return true;
        } else if (typeof this.staticSetters[i].type == 'string' && this.staticSetters[i].type == shorthand) {
          return true;
        }
      }

      var classMember;
      // Same logic as checkMembersWithAssignments()
      // For each member that has an assignment at the top-level scope
      for (i = 0; i < this.membersWithAssignments.length; i++) {
        classMember = this.membersWithAssignments[i];
        // Make a dumb attempt to identify use of the class as assignments here
        if (classMember.value && classMember.value.indexOf(shorthand) >= 0 && !(this.parentDefinition && this.parentDefinition.packageName + "." + this.parentDefinition.className === pkg)) {
          return true;
        }
      }

      return false;
    };
    AS3Class.prototype.addImport = function(pkg) {
      if (this.imports.indexOf(pkg) < 0) {
        this.imports.push(pkg);
      }
    };
    AS3Class.prototype.addExtraImport = function(pkg) {
      if (this.importExtras.indexOf(pkg) < 0) {
        this.importExtras.push(pkg);
      }
    };
    AS3Class.prototype.findParents = function(classes) {
      if (!this.parent) {
        return;
      }
      for (var i in classes) {
        //Only gather vars from the parent
        if (classes[i] != this && this.parent == classes[i].className) {
          this.parentDefinition = classes[i]; //Found our parent
          return;
        }
      }
    };
    AS3Class.prototype.checkMembersWithAssignments = function() {
      var i;
      var j;
      var classMember;
      // If the type of this param is a Class
      for (i = 0; i < this.membersWithAssignments.length; i++) {
        classMember = this.membersWithAssignments[i];
        // Make a dumb attempt to identify use of the class as assignments here
        for (j in this.imports) {
          if (this.packageMap[this.imports[j]] && classMember.value.indexOf(this.packageMap[this.imports[j]].className) >= 0 && this.parentDefinition !== this.packageMap[this.imports[j]]) {
            // If this is a token that matches a class from an import statement, store it in the filtered classMap
            this.classMapFiltered[this.packageMap[this.imports[j]].className] = this.packageMap[this.imports[j]];
          }
        }
      }
    };
    AS3Class.prototype.stringifyFunc = function(fn) {
      var buffer = "";
      if (fn instanceof AS3Function) {
        //Functions need to be handled differently
        //Prepend sub-type if it exists
        if (fn.subType) {
          buffer += fn.subType + '_';
        }
        //Print out the rest of the name and start the function definition
        buffer += fn.name
        buffer += " = function(";
        //Concat all of the arguments together
        tmpArr = [];
        for (j = 0; j < fn.argList.length; j++) {
          if (!fn.argList[j].isRestParam) {
            tmpArr.push(fn.argList[j].name);
          }
        }
        buffer += tmpArr.join(", ") + ") ";
        //Function definition is finally added
        buffer += fn.value + ";\n";
      } else if (fn instanceof AS3Variable) {
        //Variables can be added immediately
        buffer += fn.name;
        buffer += " = " + fn.value + ";\n";
      }
      return buffer;
    };
    AS3Class.prototype.process = function(classes) {
      var self = this;
      var i;
      var index;
      var currParent = this;
      var allMembers = [];
      var allFuncs = [];
      var allStaticMembers = [];
      var allStaticFuncs = [];

      while (currParent) {
        //Parse members of this parent
        for (i in currParent.setters) {
          allMembers.push(currParent.setters[i]);
        }
        for (i in currParent.staticSetters) {
          allStaticMembers.push(currParent.staticSetters[i]);
        }
        for (i in currParent.getters) {
          allMembers.push(currParent.getters[i]);
        }
        for (i in currParent.staticGetters) {
          allStaticMembers.push(currParent.staticGetters[i]);
        }
        for (i in currParent.members) {
          allMembers.push(currParent.members[i]);
        }
        for (i in currParent.staticMembers) {
          allStaticMembers.push(currParent.staticMembers[i]);
        }

        //Go to the next parent
        currParent = currParent.parentDefinition;
      }

      //Add copies of the setters and getters to the "all" arrays (for convenience)
      for (i in this.setters) {
        if (this.setters[i] instanceof AS3Function) {
          allFuncs.push(this.setters[i]);
        }
      }
      for (i in this.staticSetters) {
        if (this.staticSetters[i] instanceof AS3Function) {
          allStaticFuncs.push(this.staticSetters[i]);
        }
      }
      for (i in this.getters) {
        if (this.getters[i] instanceof AS3Function) {
          allFuncs.push(this.getters[i]);
        }
      }
      for (i in this.staticGetters) {
        if (this.staticGetters[i] instanceof AS3Function) {
          allStaticFuncs.push(this.staticGetters[i]);
        }
      }
      for (i in this.members) {
        if (this.members[i] instanceof AS3Function) {
          allFuncs.push(this.members[i]);
        }
        if (this.members[i] instanceof AS3Variable) {
          // Fix any obvious assignments that rely on implicit static class name (only works for simple statements)
          if (this.members[i].value && this.retrieveField(this.members[i].value.replace(/^([a-zA-Z_$][0-9a-zA-Z_$]*)(.*?)$/g, "$1"), true)) {
            this.members[i].value = this.className + '.' + this.members[i].value;
          }
        }
      }
      for (i in this.staticMembers) {
        if (this.staticMembers[i] instanceof AS3Function) {
          allStaticFuncs.push(this.staticMembers[i]);
        }
        if (this.staticMembers[i] instanceof AS3Variable) {
          // Fix any obvious assignments that rely on implicit static class name (only works for simple statements)
          if (this.staticMembers[i].value && this.retrieveField(this.staticMembers[i].value.replace(/^([a-zA-Z_$][0-9a-zA-Z_$]*)(.*?)$/g, "$1"), true)) {
            this.staticMembers[i].value = this.className + '.' + this.staticMembers[i].value;
          }
        }
      }

      // Insert $init function for instantiations
      for (i in allFuncs) {
        Main.debug("Now parsing function: " + this.className + ":" + allFuncs[i].name);
        allFuncs[i].value = AS3Parser.parseFunc(this, allFuncs[i].value, allFuncs[i].buildLocalVariableStack(), allFuncs[i].isStatic)[0];
        allFuncs[i].value = AS3Parser.checkArguments(allFuncs[i]);
        if (allFuncs[i].name === "$init") {
          //Inject instantiations here
          allFuncs[i].value = AS3Parser.injectInstantiations(this, allFuncs[i]);
        }
        if (allFuncs[i].name === this.className) {
          //Inject $init() into constructor
          allFuncs[i].value = AS3Parser.injectInit(this, allFuncs[i]);
        }
        allFuncs[i].value = AS3Parser.cleanup(allFuncs[i].value);
        //Fix supers
        allFuncs[i].value = allFuncs[i].value.replace(/super\.(.*?)\(/g, this.parent + '.prototype.$1.call(this, ').replace(/\.call\(this,\s*\)/g, ".call(this)");
        allFuncs[i].value = allFuncs[i].value.replace(/super\(/g, this.parent + '.call(this, ').replace(/\.call\(this,\s*\)/g, ".call(this)");
        allFuncs[i].value = allFuncs[i].value.replace(new RegExp("this[.]" + this.parent, "g"), this.parent); //Fix extra 'this' on the parent
      }

      for (i in allStaticFuncs) {
        Main.debug("Now parsing static function: " + this.className + ":" + allStaticFuncs[i].name);
        allStaticFuncs[i].value = AS3Parser.parseFunc(this, allStaticFuncs[i].value, allStaticFuncs[i].buildLocalVariableStack(), allStaticFuncs[i].isStatic)[0];
        allStaticFuncs[i].value = AS3Parser.checkArguments(allStaticFuncs[i]);
        allStaticFuncs[i].value = AS3Parser.cleanup(allStaticFuncs[i].value);
      }
    };
    AS3Class.prototype.toString = function() {
      //Outputs the class inside a JS function
      var i;
      var j;
      var buffer = "";

      if (this.requires.length > 0) {
        if (this.safeRequire) {
          for (i in this.requires) {
            buffer += 'var ' + this.requires[i].substring(1, this.requires[i].length - 1) + ' = (function () { try { return require(' + this.requires[i] + '); } catch(e) { return undefined; }})();\n';
          }
        } else {
          for (i in this.requires) {
            buffer += 'var ' + this.requires[i].substring(1, this.requires[i].length - 1) + ' = require(' + this.requires[i] + ');\n';
          }
        }
        buffer += "\n";
      }

      var tmpArr = null;

      //Parent class must be imported if it exists
      if (this.parentDefinition) {
        buffer += "var " + this.parentDefinition.className + " = module.import('" + this.parentDefinition.packageName + "', '" + this.parentDefinition.className + "');\n";
      }

      //Create refs for all the other classes
      if (this.imports.length > 0) {
        tmpArr = [];
        for (i in this.imports) {
          if (!(this.ignoreFlash && this.imports[i].indexOf('flash.') >= 0) && this.parent != this.imports[i].substr(this.imports[i].lastIndexOf('.') + 1) && this.packageName + '.' + this.className != this.imports[i]) //Ignore flash imports
          {
            // Must be in the filtered map, otherwise no point in writing
            if (!this.packageMap[this.imports[i]]) {
              Main.warn("Warning, missing class path: " + this.imports[i] + " (found in " + this.packageName + '.' + this.className + ")");
            } else if (this.classMapFiltered[this.packageMap[this.imports[i]].className]) {
              tmpArr.push(this.imports[i].substr(this.imports[i].lastIndexOf('.') + 1)); //<-This will return characters after the final '.', or the entire String if no '.'
            }
          }
        }
        //Join up separated by commas
        if (tmpArr.length > 0) {
          buffer += 'var ';
          buffer += tmpArr.join(", ") + ";\n";
        }
      }
      //Check for injection function code
      var injectedText = "";
      for (i in this.imports) {
        if (!(this.ignoreFlash && this.imports[i].indexOf('flash.') >= 0) && this.packageName + '.' + this.className != this.imports[i] && !(this.parentDefinition && this.parentDefinition.packageName + '.' + this.parentDefinition.className == this.imports[i])) //Ignore flash imports and parent for injections
        {
          // Must be in the filtered map, otherwise no point in writing
          if (!this.packageMap[this.imports[i]]) {
            Main.warn("Warning, missing class path: " + this.imports[i] + " (found in " + this.packageName + '.' + this.className + ")");
          } else if (this.classMapFiltered[this.packageMap[this.imports[i]].className]) {
            injectedText += "\t" + this.imports[i].substr(this.imports[i].lastIndexOf('.') + 1) + " = module.import('" + this.packageMap[this.imports[i]].packageName + "', '" + this.packageMap[this.imports[i]].className + "');\n";
          }
        }
      }

      if (injectedText.length > 0) {
        buffer += "module.inject = function () {\n";
        buffer += injectedText;
        buffer += "};\n";
      }

      buffer += '\n';

      buffer += (this.fieldMap[this.className]) ? "var " + this.stringifyFunc(this.fieldMap[this.className]) : "var " + this.className + " = function " + this.className + "() {};";

      buffer += '\n';
      buffer += '\n';

      if (this.parent) {
        //Extend parent if necessary
        buffer += this.className + ".prototype = Object.create(" + this.parent + ".prototype);";
      }

      buffer += '\n\n';

      // Deal with static member assigments
      if (this.staticMembers.length > 0) {
        //Place defaults first
        for (i in this.staticMembers) {
          if (this.staticMembers[i] instanceof AS3Function) {
            buffer += this.className + "." + this.stringifyFunc(this.staticMembers[i]);
          } else if (this.staticMembers[i].type === "Number" || this.staticMembers[i].type === "int" || this.staticMembers[i].type === "uint") {
            if (isNaN(parseInt(this.staticMembers[i].value))) {
              buffer += this.className + "." + this.staticMembers[i].name + ' = 0;\n';
            } else {
              buffer += this.className + "." + this.stringifyFunc(this.staticMembers[i]);
            }
          } else if (this.staticMembers[i].type === "Boolean") {
            buffer += this.className + "." + this.staticMembers[i].name + ' = false;\n';
          } else {
            buffer += this.className + "." + this.staticMembers[i].name + ' = null;\n';
          }
        }
        for (i in this.staticGetters) {
          buffer += this.className + "." + this.stringifyFunc(this.staticGetters[i]);
        }
        for (i in this.staticSetters) {
          buffer += this.className + "." + this.stringifyFunc(this.staticSetters[i]);
        }

        buffer += '\n';

        buffer += this.className + ".$cinit = function () {\n";

        // Now do the assignments for the rest
        for (i in this.staticMembers) {
          if (!(this.staticMembers[i] instanceof AS3Function)) {
            buffer += "\t" + AS3Parser.cleanup(this.className + '.' + this.staticMembers[i].name + ' = ' + this.staticMembers[i].value + ";\n");
          }
        }

        buffer += '\n';
        buffer += "};\n";
      }
      buffer += "\n";

      for (i in this.getters) {
        buffer += this.className + ".prototype." + this.stringifyFunc(this.getters[i]);
      }
      for (i in this.setters) {
        buffer += this.className + ".prototype." + this.stringifyFunc(this.setters[i]);
      }
      for (i in this.members) {
        if (this.members[i].name === this.className) {
          continue;
        }
        if (this.members[i] instanceof AS3Function || (AS3Class.nativeTypes.indexOf(this.members[i].type) >= 0 && this.members[i].value)) {
          buffer += this.className + ".prototype." + this.stringifyFunc(this.members[i]); //Print functions immediately
        } else if (this.members[i].type === "Number" || this.members[i].type === "int" || this.members[i].type === "uint") {
          if (isNaN(parseInt(this.members[i].value))) {
            buffer += this.className + ".prototype." + this.members[i].name + ' = 0;\n';
          } else {
            buffer += this.className + ".prototype." + this.stringifyFunc(this.members[i]);
          }
        } else if (this.members[i].type === "Boolean") {
          buffer += this.className + ".prototype." + this.members[i].name + ' = false;\n';
        } else {
          buffer += this.className + ".prototype." + this.members[i].name + ' = null;\n';
        }
      }

      buffer = buffer.substr(0, buffer.length - 2) + "\n"; //Strips the final comma out of the string

      buffer += "\n\n";
      buffer += "module.exports = " + this.className + ";\n";

      //Remaining fixes
      buffer = buffer.replace(/(this\.)+/g, "this.");

      return buffer;
    }

    module.exports = AS3Class;
  };
  Program["com.mcleodgaming.as3js.parser.AS3Parser"] = function(module, exports) {
    var path = (function() {
      try {
        return require("path");
      } catch (e) {
        return undefined;
      }
    })();
    var fs = (function() {
      try {
        return require("fs");
      } catch (e) {
        return undefined;
      }
    })();

    var Main, AS3Class, AS3Token, AS3Encapsulation, AS3MemberType, AS3ParseState, AS3Pattern, AS3Argument, AS3Function, AS3Member, AS3Variable;
    module.inject = function() {
      Main = module.import('com.mcleodgaming.as3js', 'Main');
      AS3Class = module.import('com.mcleodgaming.as3js.parser', 'AS3Class');
      AS3Token = module.import('com.mcleodgaming.as3js.parser', 'AS3Token');
      AS3Encapsulation = module.import('com.mcleodgaming.as3js.enums', 'AS3Encapsulation');
      AS3MemberType = module.import('com.mcleodgaming.as3js.enums', 'AS3MemberType');
      AS3ParseState = module.import('com.mcleodgaming.as3js.enums', 'AS3ParseState');
      AS3Pattern = module.import('com.mcleodgaming.as3js.enums', 'AS3Pattern');
      AS3Argument = module.import('com.mcleodgaming.as3js.types', 'AS3Argument');
      AS3Function = module.import('com.mcleodgaming.as3js.types', 'AS3Function');
      AS3Member = module.import('com.mcleodgaming.as3js.types', 'AS3Member');
      AS3Variable = module.import('com.mcleodgaming.as3js.types', 'AS3Variable');
    };

    var AS3Parser = function(src, classPath) {
      this.$init();
      classPath = AS3JS.Utils.getDefaultValue(classPath, null);
      //index = 0;
      this.stack = [];
      this.src = src;
      this.classPath = classPath;
      this.parserOptions = {};
      this.parserOptions.safeRequire = false;
      this.parserOptions.ignoreFlash = false;
    };

    AS3Parser.PREVIOUS_BLOCK = null;
    AS3Parser.increaseIndent = function(str, indent) {
      return (indent + str).replace(/\n/g, "\n" + indent);
    };
    AS3Parser.parseArguments = function(str) {
      var args = [];
      var tmpToken;
      var tmpArr = AS3Parser.extractBlock(str, 0, '(', ')');
      var tmpExtractArr = null;
      var index = tmpArr[1] - 1; //Ending index of parsed block
      var tmpStr = tmpArr[0].trim(); //Parsed block
      tmpStr = tmpStr.substr(1, tmpStr.length - 2); //Remove outer parentheses
      tmpArr = null; //Trash this
      tmpArr = tmpStr.split(','); //Split args by commas
      //Don't bother if there are no arguments
      if (tmpArr.length > 0 && tmpArr[0] != '') {
        //Truncate spaces and assign values to arguments as needed
        for (var i = 0; i < tmpArr.length; i++) {
          tmpStr = tmpArr[i].trim();
          args.push(new AS3Argument());
          if (tmpStr.indexOf('...') === 0) {
            //This is a ...rest argument, stop here
            args[args.length - 1].name = tmpStr.substr(3);
            args[args.length - 1].isRestParam = true;
            Main.debug('----->Parsed a ...rest param: ' + args[args.length - 1].name);
            break;
          } else {
            //Grab the function name
            tmpToken = AS3Parser.nextWord(tmpStr, 0, AS3Pattern.VARIABLE[0], AS3Pattern.VARIABLE[1]); //Parse out the function name
            args[args.length - 1].name = tmpToken.token; //Set the argument name
            Main.debug('----->Sub-Function argument found: ' + tmpToken.token);
            //If a colon was next, we'll assume it was typed and grab it
            if (tmpToken.index < tmpStr.length && tmpStr.charAt(tmpToken.index) == ':') {
              tmpToken = AS3Parser.nextWord(tmpStr, tmpToken.index, AS3Pattern.VARIABLE_TYPE[0], AS3Pattern.VARIABLE_TYPE[1]); //Parse out the argument type
              args[args.length - 1].type = tmpToken.token; //Set the argument type
              Main.debug('----->Sub-Function argument typed to: ' + tmpToken.token);
            }
            tmpToken = AS3Parser.nextWord(tmpStr, tmpToken.index, AS3Pattern.ASSIGN_START[0], AS3Pattern.ASSIGN_START[1]);
            if (tmpToken.token == "=") {
              //Use all characters after self symbol to set value
              tmpExtractArr = AS3Parser.extractUpTo(tmpStr, tmpToken.index, /[;\r\n]/g);
              //Store value
              args[args.length - 1].value = tmpExtractArr[0].trim();
              //Store value
              Main.debug('----->Sub-Function argument defaulted to: ' + tmpExtractArr[0].trim());
            }
          }
        }
      }
      return args;
    };
    AS3Parser.checkForCommentOpen = function(str) {
      return (str == "//") ? AS3ParseState.COMMENT_INLINE : (str == "/*") ? AS3ParseState.COMMENT_MULTILINE : null;
    };
    AS3Parser.checkForCommentClose = function(state, str) {
      return (state == AS3ParseState.COMMENT_INLINE && (str.charAt(0) == '\n' || str.charAt(0) == '\r' || str.charAt(0) == '')) ? true : (state == AS3ParseState.COMMENT_MULTILINE && str == "*/") ? true : false;
    };
    AS3Parser.checkForStringOpen = function(str) {
      return (str == '"') ? AS3ParseState.STRING_DOUBLE_QUOTE : (str == "'") ? AS3ParseState.STRING_SINGLE_QUOTE : null;
    };
    AS3Parser.checkForStringClose = function(state, str) {
      return (state == AS3ParseState.STRING_DOUBLE_QUOTE && str == '"') ? true : (state == AS3ParseState.STRING_SINGLE_QUOTE && str == "'") ? true : false;
    };
    AS3Parser.nextWord = function(src, index, characters, pattern) {
      characters = characters || AS3Pattern.IDENTIFIER[0];
      pattern = pattern || AS3Pattern.IDENTIFIER[1];
      var tokenBuffer = null;
      var extraBuffer = ''; //Contains characters that were missed
      var escapeToggle = false;
      var innerState = null;
      for (; index < src.length; index++) {
        var c = src.charAt(index);
        if (c.match(characters)) {
          tokenBuffer = (tokenBuffer) ? tokenBuffer + c : c; //Create new token buffer if needed, otherwise append
        } else if (!innerState && AS3Parser.checkForCommentOpen(src.substr(index, 2)) && !tokenBuffer) {
          tokenBuffer = null;
          Main.debug("Entering comment...");
          innerState = AS3Parser.checkForCommentOpen(src.substr(index, 2));
          extraBuffer += src.substr(index, 2);
          index += 2; //Skip next index
          //Loop until we break out of comment
          for (; index < src.length; index++) {
            if (AS3Parser.checkForCommentClose(innerState, src.substr(index, 2))) {
              if (innerState == AS3ParseState.COMMENT_MULTILINE) {
                extraBuffer += src.substr(index, 2);
                index++; //Skip next token
              } else {
                extraBuffer += src.charAt(index);
              }
              innerState = null; //Return to previous state
              Main.debug("Exiting comment...");
              break;
            } else {
              extraBuffer += src.charAt(index);
            }
          }
        } else if (!innerState && AS3Parser.checkForStringOpen(src.charAt(index)) && !tokenBuffer) {
          tokenBuffer = null;
          Main.debug("Entering string...");
          innerState = AS3Parser.checkForStringOpen(src.charAt(index));
          extraBuffer += src.substr(index, 1);
          index++; //Skip to next index
          //Loop until we break out of string
          for (; index < src.length; index++) {
            extraBuffer += src.charAt(index);
            if (!escapeToggle && src.charAt(index) == '\\') {
              escapeToggle = true;
              continue;
            }
            escapeToggle = false;
            if (AS3Parser.checkForStringClose(innerState, src.charAt(index))) {
              innerState = null; //Return to previous state
              Main.debug("Exiting string...");
              break;
            }
          }
        } else if (tokenBuffer && tokenBuffer.match(pattern)) {
          return new AS3Token(tokenBuffer, index, extraBuffer); //[Token, Index]
        } else {
          if (tokenBuffer) {
            extraBuffer += tokenBuffer + c;
          } else {
            extraBuffer += c;
          }
          tokenBuffer = null;
        }
      }
      return new AS3Token(tokenBuffer || null, index, extraBuffer); //[Token, Index]
    };
    AS3Parser.extractBlock = function(text, start, opening, closing) {
      start = AS3JS.Utils.getDefaultValue(start, 0);
      opening = AS3JS.Utils.getDefaultValue(opening, "{");
      closing = AS3JS.Utils.getDefaultValue(closing, "}");
      var buffer = "";
      var i = start;
      var count = 0;
      var started = false;
      var insideString = null;
      var insideComment = null;
      var escapingChar = false;
      while (!(count == 0 && started) && i < text.length) {
        if (insideComment) {
          //Inside of a comment, wait until we get out
          if (insideComment == '//' && (text.charAt(i) == '\n' || text.charAt(i) == '\r')) {
            insideComment = null; //End inline comment
            Main.debug("Exited comment");
          } else if (insideComment == '/*' && text.charAt(i) == '*' && i + 1 < text.length && text.charAt(i + 1) == '/') {
            insideComment = null; //End multiline comment
            Main.debug("Exited comment");
          }
        } else if (insideString) {
          //Inside of a string, wait until we get out
          if (!escapingChar && text.charAt(i) == "\\") {
            escapingChar = true; //Start escape sequence
          } else if (!escapingChar && text.charAt(i) == insideString) {
            insideString = null; //Found closing quote
          } else {
            escapingChar = false; //Forget escape sequence
          }
        } else if (text.charAt(i) == opening) {
          started = true;
          count++; //Found opening
        } else if (text.charAt(i) == closing) {
          count--; //Found closing
        } else if ((text.charAt(i) == '\"' || text.charAt(i) == '\'')) {
          insideString = text.charAt(i); //Now inside of a string
        } else if (text.charAt(i) == '/' && i + 1 < text.length && text.charAt(i + 1) == '/') {
          Main.debug("Entering comment... " + "(//)");
          insideComment = '//';
        } else if (text.charAt(i) == '/' && i + 1 < text.length && text.charAt(i + 1) == '*') {
          Main.debug("Entering comment..." + "(/*)");
          insideComment = '/*';
        }
        if (started) {
          buffer += text.charAt(i);
        }
        i++;
      }
      if (!started) {
        throw new Error("Error, no starting '" + opening + "' found for method body while parsing " + AS3Parser.PREVIOUS_BLOCK);
      } else if (count > 0) {
        throw new Error("Error, no closing '" + closing + "' found for method body while parsing " + AS3Parser.PREVIOUS_BLOCK);
      } else if (count < 0) {
        throw new Error("Error, malformed enclosing '" + opening + closing + " body while parsing " + AS3Parser.PREVIOUS_BLOCK);
      }
      return [buffer, i];
    };
    AS3Parser.extractUpTo = function(text, start, target) {
      var buffer = "";
      var i = start;
      var insideString = null;
      var insideComment = null;
      var escapingChar = false;
      var pattern = new RegExp(target);
      while (i < text.length) {
        if (insideComment) {
          //Inside of a comment, wait until we get out
          if (insideComment == '//' && (text.charAt(i) == '\n' || text.charAt(i) == '\r')) {
            insideComment = null; //End inline comment
            Main.debug("Exited comment");
          } else if (insideComment == '/*' && text.charAt(i) == '*' && i + 1 < text.length && text.charAt(i + 1) == '/') {
            insideComment = null; //End multiline comment
            Main.debug("Exited comment");
          }
        } else if (insideString) {
          //Inside of a string, wait until we get out
          if (!escapingChar && text.charAt(i) == "\\") {
            escapingChar = true; //Start escape sequence
          } else if (!escapingChar && text.charAt(i) == insideString) {
            insideString = null; //Found closing quote
          } else {
            escapingChar = false; //Forget escape sequence
          }
        } else if ((text.charAt(i) == '\"' || text.charAt(i) == '\'')) {
          insideString = text.charAt(i); //Now inside of a string
        } else if (text.charAt(i) == '/' && i + 1 < text.length && text.charAt(i + 1) == '/') {
          Main.debug("Entering comment... " + "(//)");
          insideComment = '//';
        } else if (text.charAt(i) == '/' && i + 1 < text.length && text.charAt(i + 1) == '*') {
          Main.debug("Entering comment..." + "(/*)");
          insideComment = '/*';
        } else if (text.charAt(i).match(pattern)) {
          break; //Done
        }
        buffer += text.charAt(i);
        i++;
      }
      return [buffer, i];
    };
    AS3Parser.fixClassPath = function(clsPath) {
      // Class paths at the root level might accidentally be prepended with a "."
      return clsPath.replace(/^\./g, "");
    };
    AS3Parser.checkArguments = function(fn) {
      if (fn.argList.length <= 0) {
        return fn.value;
      }
      var start = fn.value.indexOf('{');
      var args = "";
      for (var i = 0; i < fn.argList.length; i++) {
        //We will inject arguments into the top of the method definition
        if (fn.argList[i].isRestParam) {
          args += "\n\t\t\tvar " + fn.argList[i].name + " = Array.prototype.slice.call(arguments).splice(" + i + ");";
        } else if (fn.argList[i].value) {
          args += "\n\t\t\t" + fn.argList[i].name + " = AS3JS.Utils.getDefaultValue(" + fn.argList[i].name + ", " + fn.argList[i].value + ");";
        }
      }
      return fn.value.substr(0, start + 1) + args + fn.value.substr(start + 1);
    };
    AS3Parser.injectInstantiations = function(cls, fn) {
      var start = fn.value.indexOf('{');
      var text = "";
      for (var i = 0; i < cls.members.length; i++) {
        //We will inject instantiated vars into the top of the method definition
        if (cls.members[i] instanceof AS3Variable && AS3Class.nativeTypes.indexOf(cls.members[i].type) < 0) {
          text += "\n\t\t\tthis." + cls.members[i].name + " = " + cls.members[i].value + ";";
        }
      }
      return fn.value.substr(0, start + 1) + text + fn.value.substr(start + 1);
    };
    AS3Parser.injectInit = function(cls, fn) {
      var start = fn.value.indexOf('{');
      var text = "\n\t\t\tthis.$init();";

      return fn.value.substr(0, start + 1) + text + fn.value.substr(start + 1);
    };
    AS3Parser.checkStack = function(stack, name) {
      if (!name) {
        return null;
      }
      for (var i = stack.length - 1; i >= 0; i--) {
        if (stack[i].name == name) {
          return stack[i];
        }
      }
      return null;
    };
    AS3Parser.lookAhead = function(str, index) {
      //Look ahead in the function for assignments
      var originalIndex = index;
      var startIndex = -1;
      var endIndex = -1;
      var semicolonIndex = -1;
      var token = "";
      var extracted = "";
      //Not a setter if there is a dot operator immediately after
      if (str.charAt(index) == '.') {
        return {
          token: null,
          extracted: '',
          startIndex: startIndex,
          endIndex: endIndex
        };
      }
      for (; index < str.length; index++) {
        if (str.charAt(index).match(/[+-\/=*]/g)) {
          //Append to the assignment instruction
          token += str.charAt(index);
          startIndex = index;
        } else if (startIndex < 0 && str.charAt(index).match(/[\t\s]/g)) //Skip these characters
        {
          continue;
        } else {
          break; //Exits when token has already been started and no more regexes pass
        }
      }

      //Only allow these patterns
      if (!(token == "=" || token == "++" || token == "--" || token == "+=" || token == "-=" || token == "*=" || token == "/=")) {
        token = null;
      }

      if (token) {
        //Pick whatever is closer, new line or semicolon
        endIndex = str.indexOf('\n', startIndex);
        if (endIndex < 0) {
          endIndex = str.length - 1;
        }
        //Windows fix
        if (str.charAt(endIndex - 1) == '\r') {
          endIndex--;
        }
        //We want to place closing parens before semicolon if it exists
        semicolonIndex = str.indexOf(";", startIndex);
        if (semicolonIndex < endIndex) {
          endIndex = semicolonIndex;
        }
        extracted = str.substring(startIndex + token.length, endIndex);
      }

      return {
        token: token,
        extracted: extracted,
        startIndex: startIndex,
        endIndex: endIndex
      };
    };
    AS3Parser.parseFunc = function(cls, fnText, stack, statFlag) {
      statFlag = AS3JS.Utils.getDefaultValue(statFlag, false);
      var i;
      var j;
      var index = 0;
      var result = '';
      var tmpStr = '';
      var tmpArgs;
      var tmpMember;
      var tmpClass;
      var tmpField;
      var prevToken;
      var currToken;
      var tmpParse;
      var tmpStatic = false;
      var tmpPeek;
      var objBuffer = ''; //Tracks the current object that is being "pathed" (e.g. "object.field1" or "object.field1[index + 1]", etc)
      var justCreatedVar = false; //Keeps track if we just started a var statement (to help test if we're setting a type))
      for (index = 0; index < fnText.length; index++) {
        objBuffer = '';
        prevToken = currToken;
        currToken = AS3Parser.nextWord(fnText, index, AS3Pattern.VARIABLE[0], AS3Pattern.VARIABLE[1]);
        result += currToken.extra; //<-Puts all other non-identifier characters into the buffer first
        tmpMember = AS3Parser.checkStack(stack, currToken.token); //<-Check the stack for a member with this identifier already
        index = currToken.index;
        if (currToken.token) {
          if (currToken.token == 'function') {
            var t1 = AS3Parser.nextWord(fnText, index, AS3Pattern.VARIABLE[0], AS3Pattern.VARIABLE[1]);
            var t2 = fnText.indexOf('(', index);
            //If the parenthesis si less than the last index of the next parsed variable name
            result += (t2 < t1.index) ? 'function' : 'function ' + t1.token;
            tmpParse = AS3Parser.extractBlock(fnText, index, '(', ')'); //Parse out argument block
            index = tmpParse[1]; //Update index
            tmpArgs = AS3Parser.parseArguments(tmpParse[0]); //Extract arg types
            //Join the args together without types
            result += '(' + (function(args) {
              var arr = [];
              for (var i = 0; i < args.length; i++) {
                if (args[i] === '...rest') {
                  break;
                }
                arr.push(args[i].name);
              }
              var str = arr.join(', ');
              return str;
            })(tmpArgs) + ')';
            tmpParse = AS3Parser.extractBlock(fnText, index, '{', '}'); //Extract function block
            index = tmpParse[1] - 1; //Update index
            tmpParse = AS3Parser.parseFunc(cls, tmpParse[0], stack.concat(tmpArgs), statFlag); //Recurse into function
            result += ' ' + tmpParse[0];
          } else {
            if (currToken.token == 'this') {
              //No need to perform any extra checks on the subsequent token
              tmpStatic = false;
              tmpClass = cls;
              objBuffer += currToken.token;
              result += currToken.token;
            } else {
              if (cls.classMap[currToken.token] && cls.parentDefinition !== cls.classMap[currToken.token] && !(justCreatedVar && currToken.extra.match(/:\s*/g))) {
                // If this is a token that matches a class from a potential import statement, store it in the filtered classMap
                cls.classMapFiltered[currToken.token] = cls.classMap[currToken.token];
              }
              tmpStatic = (cls.className == currToken.token || cls.retrieveField(currToken.token, true) !== null);

              //Find field in class, then make sure we didn't already have a local member defined with this name, and skip next block if static since the definition is the class itself
              //Note: tmpMember needs to be checked, if something is in there it means we have a variable with the same name in local scope
              if (cls.retrieveField(currToken.token, tmpStatic) && cls.className != currToken.token && !tmpMember && !(prevToken && prevToken.token === "var")) {
                tmpMember = cls.retrieveField(currToken.token, tmpStatic); //<-Reconciles the type of the current variable
                if (tmpMember && (tmpMember.subType == 'get' || tmpMember.subType == 'set')) {
                  tmpPeek = AS3Parser.lookAhead(fnText, index);
                  if (tmpPeek.token) {
                    //Handle differently if we are assigning a setter

                    //Prepend the correct term
                    if (tmpStatic) {
                      objBuffer += (cls.retrieveField(currToken.token, tmpStatic)) ? cls.className + '.' : currToken.token + '.';
                      result += (cls.retrieveField(currToken.token, tmpStatic)) ? cls.className + '.' : currToken.token + '.';
                    } else {
                      objBuffer += 'this.';
                      result += 'this.';
                    }
                    objBuffer += 'get_' + currToken.token + '()';
                    result += 'set_' + currToken.token + '(';
                    index = tmpPeek.endIndex;
                    if (tmpPeek.token == '++') {
                      result += objBuffer + ' + 1';
                    } else if (tmpPeek.token == '--') {
                      result += objBuffer + ' - 1';
                    } else {
                      tmpParse = AS3Parser.parseFunc(cls, tmpPeek.extracted, stack); //Recurse into the assignment to parse vars
                      if (tmpPeek.token == '=') {
                        result += tmpParse[0].trim();
                      } else {
                        result += objBuffer + ' ' + tmpPeek.token.charAt(0) + ' (' + tmpParse[0] + ')';
                      }
                    }
                    result += ')';
                  } else {
                    //Getters are easy
                    if (tmpStatic) {
                      objBuffer += (cls.retrieveField(currToken.token, true)) ? cls.className + '.get_' + currToken.token + '()' : 'this.get_' + currToken.token + '()';
                      result += (cls.retrieveField(currToken.token, true)) ? cls.className + '.get_' + currToken.token + '()' : 'this.get_' + currToken.token + '()';
                    } else {
                      objBuffer += 'this.get_' + currToken.token + '()';
                      result += 'this.get_' + currToken.token + '()';
                    }
                  }
                } else {
                  if (tmpStatic) {
                    objBuffer += (cls.className == currToken.token) ? currToken.token : cls.className + '.' + currToken.token;
                    result += (cls.className == currToken.token) ? currToken.token : cls.className + '.' + currToken.token;
                  } else {
                    objBuffer += (cls.retrieveField(currToken.token, false) && !statFlag && !(prevToken && prevToken.token === 'new' && cls.retrieveField(currToken.token, false).type !== "Class")) ? 'this.' + currToken.token : currToken.token;
                    result += (cls.retrieveField(currToken.token, false) && !statFlag && !(prevToken && prevToken.token === 'new' && cls.retrieveField(currToken.token, false).type !== "Class")) ? 'this.' + currToken.token : currToken.token;
                  }
                }
              } else {
                //Likely a local variable, argument, or static reference
                if (tmpStatic) {
                  objBuffer += currToken.token;
                  result += currToken.token;
                } else {
                  objBuffer += (cls.retrieveField(currToken.token, false) && !tmpMember && !(prevToken && prevToken.token === "var")) ? 'this.' + currToken.token : currToken.token;
                  result += (cls.retrieveField(currToken.token, false) && !tmpMember && !(prevToken && prevToken.token === "var")) ? 'this.' + currToken.token : currToken.token;
                }
              }
              if (tmpStatic) {
                //Just use the class itself, we will reference fields from it. If parser injected the static prefix manually, we'll try to determome the type of var instead
                tmpClass = (cls.className == currToken.token) ? cls : (tmpMember) ? cls.classMap[tmpMember.type] || null : null;
              } else {
                //Use the member's type to determine the class it's mapped to
                tmpClass = (tmpMember && tmpMember.type && tmpMember.type != '*') ? cls.classMap[tmpMember.type] : null;
                //If no mapping was found, this may be a static reference
                if (!tmpClass && cls.classMap[currToken.token]) {
                  tmpClass = cls.classMap[currToken.token];
                  tmpStatic = true;
                }
              }
              //If tmpClass is null, it's possible we were trying to retrieve a Vector type. Let's fix this:
              if (!tmpClass && tmpMember && tmpMember.type && tmpMember.type.replace(/Vector\.<(.*?)>/g, "$1") != tmpMember.type) {
                //Extract Vector type if necessary by testing regex
                tmpClass = cls.classMap[tmpMember.type.replace(/Vector\.<(.*?)>/g, "$1")] || null;
              }
            }
            //Note: At this point, tmpMember is no longer used, it was only needed to remember the type of the first token. objBuffer will be building out the token

            //If this had a variable declaration before it, we will add it to the local var stack and move on to the next token
            if (prevToken && prevToken.token === "var") {
              justCreatedVar = true;
              if (cls.retrieveField(currToken.token, tmpStatic)) {
                //Appends current character index to the result, add dummy var to stack, and move on
                result += fnText.charAt(index);
                var localVar = new AS3Member();
                localVar.name = currToken.token;
                stack.push(localVar); //<-Ensures we don't add "this." or anything in front of this variable anymore
                continue;
              }
            } else {
              justCreatedVar = false;
            }

            //We have parsed the current token, and the index sits at the next level down in the object
            for (; index < fnText.length; index++) {
              //Loop until we stop parsing a variable declaration
              if (fnText.charAt(index) == '.') {
                var parsingVector = (prevToken && prevToken.token === 'new' && currToken.token === 'Vector');
                prevToken = currToken;
                if (parsingVector) {
                  //We need to allow asterix
                  currToken = AS3Parser.nextWord(fnText, index, AS3Pattern.VARIABLE_TYPE[0], AS3Pattern.VARIABLE_TYPE[1]);
                } else {
                  currToken = AS3Parser.nextWord(fnText, index, AS3Pattern.VARIABLE[0], AS3Pattern.VARIABLE[1]);
                }
                result += currToken.extra; //<-Puts all other non-identifier characters into the buffer first
                index = currToken.index;
                if (tmpClass) {
                  //This means we are coming from a typed variable
                  tmpField = tmpClass.retrieveField(currToken.token, tmpStatic);
                  if (tmpField) {
                    //console.log("parsing: " + tmpField.name + ":" + tmpField.type)
                    //We found a field that matched this value within the class
                    if (tmpField instanceof AS3Function) {
                      if (tmpField.subType == 'get' || tmpField.subType == 'set') {
                        tmpPeek = AS3Parser.lookAhead(fnText, index);
                        if (tmpPeek.token) {
                          //Handle differently if we are assigning a setter
                          objBuffer += '.get_' + currToken.token + '()';
                          result += 'set_' + currToken.token + '(';
                          index = tmpPeek.endIndex;
                          if (tmpPeek.token == '++') {
                            result += objBuffer + ' + 1';
                          } else if (tmpPeek.token == '--') {
                            result += objBuffer + ' - 1';
                          } else {
                            tmpParse = AS3Parser.parseFunc(cls, tmpPeek.extracted, stack); //Recurse into the assignment to parse vars
                            if (tmpPeek.token == '=') {
                              result += tmpParse[0].trim();
                            } else {
                              result += objBuffer + ' ' + tmpPeek.token.charAt(0) + ' (' + tmpParse[0] + ')';
                            }
                          }
                          result += ')';
                        } else {
                          objBuffer += '.get_' + currToken.token + '()';
                          result += 'get_' + currToken.token + "()";
                        }
                        //console.log("set get flag: " + currToken.token);
                      } else {
                        objBuffer += '.' + currToken.token;
                        result += currToken.token;
                      }
                    } else {
                      objBuffer += '.' + currToken.token;
                      result += currToken.token;
                    }
                  } else {
                    objBuffer += '.' + currToken.token;
                    result += currToken.token;
                    //console.log("appened typed: " + currToken.token);
                  }
                  //Update the type if this is not a static prop
                  if (tmpClass && tmpField && tmpField.type && tmpField.type != '*') {
                    //Extract Vector type if necessary by testing regex
                    tmpClass = (tmpField.type.replace(/Vector\.<(.*?)>/g, "$1") != tmpField.type) ? tmpClass.classMap[tmpField.type.replace(/Vector\.<(.*?)>/g, "$1")] || null : tmpClass.classMap[tmpField.type] || null;
                  } else {
                    tmpClass = null;
                  }
                } else {
                  //console.log("appened untyped: " + currToken.token);
                  objBuffer += '.' + currToken.token;
                  result += currToken.token;
                }
              } else if (fnText.charAt(index) == '[') {
                //We now have to recursively parse the inside of this open bracket
                tmpParse = AS3Parser.extractBlock(fnText, index, '[', ']');
                index = tmpParse[1];
                tmpParse = AS3Parser.parseFunc(cls, tmpParse[0], stack); //Recurse into the portion that was extracted
                //console.log("recursed into: " + tmpParse[0]);
                objBuffer += tmpParse[0]; //Append this text to the object buffer string so we can remember the variable we have accessed
                result += tmpParse[0];
              }
              tmpStatic = false; //Static can no longer be possible after the second field
              if (!fnText.charAt(index).match(/[.\[]/g)) {
                objBuffer = ''; //Clear out the current object buffer
                index--;
                break;
              }
              index--;
            }
          }
        } else {
          index = currToken.index - 1;
        }
      }
      return [result, index];
    };
    AS3Parser.cleanup = function(text) {
      var i;
      var type;
      var params;
      var val;
      var matches = text.match(AS3Pattern.VECTOR[0]);
      //For each Vector.<>() found in the text
      for (i in matches) {
        //Strip the type and provided params
        type = matches[i].replace(AS3Pattern.VECTOR[0], '$1').trim();
        params = matches[i].replace(AS3Pattern.VECTOR[0], '$2').split(',');
        //Set the default based on var type
        if (type == 'int' || type == 'uint' || type == 'Number') {
          val = "0";
        } else if (type == 'Boolean') {
          val = "false";
        } else {
          val = "null";
        }
        //Replace accordingly
        if (params.length > 0 && params[0].trim() != '') {
          text = text.replace(AS3Pattern.VECTOR[1], "AS3JS.Utils.createArray(" + params[0] + ", " + val + ")");
        } else {
          text = text.replace(AS3Pattern.VECTOR[1], "[]");
        }
      }
      matches = text.match(AS3Pattern.ARRAY[0]);
      //For each Array() found in the text
      for (i in matches) {
        //Strip the provided params
        params = matches[i].replace(AS3Pattern.ARRAY[0], '$1').trim();
        //Replace accordingly
        if (params.length > 0 && params[0].trim() != '') {
          text = text.replace(AS3Pattern.ARRAY[1], "AS3JS.Utils.createArray(" + params[0] + ", null)");
        } else {
          text = text.replace(AS3Pattern.ARRAY[1], "[]");
        }
      }

      matches = text.match(AS3Pattern.DICTIONARY[0]);
      //For each instantiated Dictionary found in the text
      for (i in matches) {
        // Replace with empty object
        text = text.replace(AS3Pattern.DICTIONARY[0], "{}");
      }

      //Now cleanup variable types
      text = text.replace(/([^0-9a-zA-Z_$.])(?:var|const)(\s*[a-zA-Z_$*][0-9a-zA-Z_$.<>]*)\s*:\s*([a-zA-Z_$*][0-9a-zA-Z_$.<>]*)/g, "$1var$2");

      return text;
    };

    AS3Parser.$cinit = function() {
      AS3Parser.PREVIOUS_BLOCK = null;

    };

    AS3Parser.prototype.$init = function() {
      this.stack = null;
      this.parserOptions = null;
    };
    AS3Parser.prototype.stack = null;
    AS3Parser.prototype.src = null;
    AS3Parser.prototype.classPath = null;
    AS3Parser.prototype.parserOptions = null;
    AS3Parser.prototype.getState = function() {
      return (this.stack.length > 0) ? this.stack[this.stack.length - 1] : null;
    };
    AS3Parser.prototype.parseHelper = function(cls, src) {
      var i;
      var j;
      var c;
      var currToken = null;
      var tmpToken = null;
      var tmpStr = null;
      var tmpArr = null;
      var currMember = null;
      var index;
      for (index = 0; index < src.length; index++) {
        c = src.charAt(index);
        if (this.getState() == AS3ParseState.START) {
          //String together letters only until we reach a non-letter
          currToken = AS3Parser.nextWord(src, index, AS3Pattern.IDENTIFIER[0], AS3Pattern.IDENTIFIER[1]);
          index = currToken.index - 1; //Update to the new position
          if (currToken.token == 'package') {
            this.stack.push(AS3ParseState.PACKAGE_NAME);
          }
        } else if (this.getState() == AS3ParseState.PACKAGE_NAME) {
          currToken = AS3Parser.nextWord(src, index, AS3Pattern.OBJECT[0], AS3Pattern.OBJECT[1]); //Package name
          tmpToken = AS3Parser.nextWord(src, index, AS3Pattern.CURLY_BRACE[0], AS3Pattern.CURLY_BRACE[1]); //Upcoming curly brace

          index = currToken.index - 1;
          if (!currToken.token || !tmpToken.token) {
            throw new Error("Error parsing package name.");
          } else {
            if (tmpToken.index < currToken.index) {
              cls.packageName = ''; //Curly brace came before next token
              index = tmpToken.index;
            } else {
              cls.packageName = currToken.token; //Just grab the package name
            }
            Main.debug('Found package: ' + cls.packageName);
            cls.importWildcards.push(AS3Parser.fixClassPath(cls.packageName + '.*')); //Add wild card for its own folder
            this.stack.push(AS3ParseState.PACKAGE);
            Main.debug('Attempting to parse package...');
          }
        } else if (this.getState() == AS3ParseState.PACKAGE) {
          currToken = AS3Parser.nextWord(src, index, AS3Pattern.IDENTIFIER[0], AS3Pattern.IDENTIFIER[1]);
          index = currToken.index - 1;
          if (currToken.token == 'class' || currToken.token == 'interface') {
            if (currToken.token == 'interface')
              cls.isInterface = true;
            this.stack.push(AS3ParseState.CLASS_NAME);
            Main.debug('Found class keyword...');
          } else if (currToken.token == 'import') {
            this.stack.push(AS3ParseState.IMPORT_PACKAGE);
            Main.debug('Found import keyword...');
          } else if (currToken.token == 'require') {
            this.stack.push(AS3ParseState.REQUIRE_MODULE);
            Main.debug('Found require keyword...');
          }
        } else if (this.getState() == AS3ParseState.CLASS_NAME) {
          currToken = AS3Parser.nextWord(src, index, AS3Pattern.IDENTIFIER[0], AS3Pattern.IDENTIFIER[1]);
          tmpToken = AS3Parser.nextWord(src, index, AS3Pattern.CURLY_BRACE[0], AS3Pattern.CURLY_BRACE[1]);
          index = currToken.index;
          if (!currToken.token || !tmpToken.token) {
            throw new Error("Error parsing class name.");
          } else if (tmpToken.index < currToken.index) {
            throw new Error("Error, no class name found before curly brace.");
          } else {
            //Set the class name
            cls.className = currToken.token;

            // Update fully qualified class path if needed
            this.classPath = this.classPath || AS3Parser.fixClassPath(cls.packageName + '.' + cls.className); //Remove extra "." for top level packages

            cls.classMap[cls.className] = cls; //Register self into the import map (used for static detection)
            //Now we will check for parent class and any interfaces
            currToken = AS3Parser.nextWord(src, index, AS3Pattern.IDENTIFIER[0], AS3Pattern.IDENTIFIER[1]);
            if (currToken.token == 'extends' && currToken.index < tmpToken.index) {
              index = currToken.index;
              currToken = AS3Parser.nextWord(src, index, AS3Pattern.IDENTIFIER[0], AS3Pattern.IDENTIFIER[1]);
              index = currToken.index;
              //The token following 'extends' must be the parent class
              cls.parent = currToken.token;
              //Prep the next token
              currToken = AS3Parser.nextWord(src, index, AS3Pattern.IDENTIFIER[0], AS3Pattern.IDENTIFIER[1]);
              Main.debug("Found parent: " + cls.parent);
            }
            if (currToken.token == 'implements' && currToken.index < tmpToken.index) {
              index = currToken.index;
              currToken = AS3Parser.nextWord(src, index, AS3Pattern.IDENTIFIER[0], AS3Pattern.IDENTIFIER[1]);
              index = currToken.index;
              //The token following 'implements' must be an interface
              cls.interfaces.push(currToken.token);
              Main.debug("Found interface: " + currToken.token);
              currToken = AS3Parser.nextWord(src, index, AS3Pattern.IDENTIFIER[0], AS3Pattern.IDENTIFIER[1]);
              //While we are at a token before the next curly brace
              while (currToken.index < tmpToken.index && currToken.index < src.length) {
                //Consider self token another interface being implemented
                index = currToken.index;
                Main.debug("Found interface: " + currToken.token);
                cls.interfaces.push(currToken.token);
                currToken = AS3Parser.nextWord(src, index, AS3Pattern.IDENTIFIER[0], AS3Pattern.IDENTIFIER[1]);
                index = currToken.index;
              }
            }
            Main.debug('Parsed class name: ' + cls.className);
            //Now parsing inside of the class
            this.stack.push(AS3ParseState.CLASS);
            Main.debug('Attempting to parse class...');

            //Extract out the next method block
            AS3Parser.PREVIOUS_BLOCK = cls.className + ":Class";
            tmpStr = AS3Parser.extractBlock(src, index)[0];
            index += tmpStr.length - 1;

            //Recursively call parseHelper again under this new state (Once returned, package will be exited)
            this.parseHelper(cls, tmpStr);
          }
        } else if (this.getState() == AS3ParseState.CLASS) {
          currMember = currMember || new AS3Member(); //Declare a new member to work with if it doesn't exist yet
          currToken = AS3Parser.nextWord(src, index, AS3Pattern.IDENTIFIER[0], AS3Pattern.IDENTIFIER[1]);
          index = currToken.index - 1;
          if (currToken.token == AS3Encapsulation.PUBLIC || currToken.token == AS3Encapsulation.PRIVATE || currToken.token == AS3Encapsulation.PROTECTED) {
            currMember.encapsulation = currToken.token;
            Main.debug('->Member encapsulation set to ' + currMember.encapsulation);
          } else if (currToken.token == 'static') {
            currMember.isStatic = true;
            Main.debug('-->Static flag set');
          } else if (currToken.token == AS3MemberType.VAR || currToken.token == AS3MemberType.CONST) {
            Main.debug('--->Member type "variable" set.');
            currMember = currMember.createVariable(); //Transform the member into a variable
            this.stack.push(AS3ParseState.MEMBER_VARIABLE);
          } else if (currToken.token == AS3MemberType.FUNCTION) {
            currToken = AS3Parser.nextWord(src, index + 1, AS3Pattern.IDENTIFIER[0], AS3Pattern.IDENTIFIER[1]);
            //Check for getter/setter
            if ((currToken.token == 'get' || currToken.token == 'set') && src[index + 1 + currToken.token.length + 1] != '(') {
              Main.debug('--->Member sub-type "' + currToken.token + '" set.');
              currMember.subType = currToken.token;
              index = currToken.index - 1;
            }
            currMember = currMember.createFunction(); //Transform the member into a function
            this.stack.push(AS3ParseState.MEMBER_FUNCTION);
            Main.debug('---->Member type "function" set.');
          }
        } else if (this.getState() == AS3ParseState.MEMBER_VARIABLE) {
          currToken = AS3Parser.nextWord(src, index, AS3Pattern.IDENTIFIER[0], AS3Pattern.IDENTIFIER[1]);
          currMember.name = currToken.token; //Set the member name
          Main.debug('---->Variable name declared: ' + currToken.token);
          index = currToken.index;
          if (src.charAt(index) == ":") {
            currToken = AS3Parser.nextWord(src, index, AS3Pattern.VARIABLE_TYPE[0], AS3Pattern.VARIABLE_TYPE[1]);
            index = currToken.index;
            currMember.type = currToken.token; //Set the value type name
            Main.debug('---->Variable type for ' + currMember.name + ' declared as: ' + currToken.token);
          }
          currToken = AS3Parser.nextWord(src, index, AS3Pattern.ASSIGN_START[0], AS3Pattern.ASSIGN_START[1]);
          if (currToken.token == "=") {
            //Use all characters after self symbol to set value
            index = currToken.index;
            tmpArr = AS3Parser.extractUpTo(src, index, /[;\r\n]/g);
            //Store value
            currMember.value = tmpArr[0].trim();
            index = tmpArr[1];

            cls.membersWithAssignments.push(currMember);
          }

          //Store and delete current member and exit
          if (currMember.isStatic) {
            cls.staticMembers.push(currMember);
          } else {
            cls.members.push(currMember);
          }
          cls.registerField(currMember.name, currMember);
          currMember = null;
          this.stack.pop();
        } else if (this.getState() == AS3ParseState.MEMBER_FUNCTION) {
          //Parse the arguments
          currToken = AS3Parser.nextWord(src, index, AS3Pattern.IDENTIFIER[0], AS3Pattern.IDENTIFIER[1]);
          index = currToken.index;
          currMember.name = currToken.token; //Set the member name
          Main.debug('****>Function name declared: ' + currToken.token);

          AS3Parser.PREVIOUS_BLOCK = currMember.name + ":Function";
          tmpArr = AS3Parser.extractBlock(src, index, '(', ')');
          index = tmpArr[1] - 1; //Ending index of parsed block
          tmpStr = tmpArr[0].trim(); //Parsed block
          tmpStr = tmpStr.substr(1, tmpStr.length - 2); //Remove outer parentheses
          tmpArr = null; //Trash this
          tmpArr = tmpStr.split(','); //Split args by commas
          //Don't bother if there are no arguments
          if (tmpArr.length > 0 && tmpArr[0] != '') {
            //Truncate spaces and assign values to arguments as needed
            for (i = 0; i < tmpArr.length; i++) {
              tmpStr = tmpArr[i];
              //Grab the function name
              tmpToken = AS3Parser.nextWord(tmpStr, 0, AS3Pattern.VARIABLE[0], AS3Pattern.VARIABLE[1]); //Parse out the function name
              currMember.argList.push(new AS3Argument());
              if (tmpStr.indexOf('...') === 0) {
                //This is a ...rest argument, stop here
                currMember.argList[currMember.argList.length - 1].name = tmpStr.substr(3);
                currMember.argList[currMember.argList.length - 1].isRestParam = true;
                Main.debug('----->Parsed a ...rest param: ' + currMember.argList[currMember.argList.length - 1].name);
                break;
              } else {
                currMember.argList[currMember.argList.length - 1].name = tmpToken.token; //Set the argument name
                Main.debug('----->Function argument found: ' + tmpToken.token);
                //If a colon was next, we'll assume it was typed and grab it
                if (tmpToken.index < tmpStr.length && tmpStr.charAt(tmpToken.index) == ':') {
                  tmpToken = AS3Parser.nextWord(tmpStr, tmpToken.index, AS3Pattern.VARIABLE_TYPE[0], AS3Pattern.VARIABLE_TYPE[1]); //Parse out the argument type
                  currMember.argList[currMember.argList.length - 1].type = tmpToken.token; //Set the argument type
                  Main.debug('----->Function argument typed to: ' + tmpToken.token);
                }
                tmpToken = AS3Parser.nextWord(tmpStr, tmpToken.index, AS3Pattern.ASSIGN_START[0], AS3Pattern.ASSIGN_START[1]);
                if (tmpToken.token == "=") {
                  //Use all characters after self symbol to set value
                  tmpToken = AS3Parser.nextWord(tmpStr, tmpToken.index, AS3Pattern.ASSIGN_UPTO[0], AS3Pattern.ASSIGN_UPTO[1]);
                  if (!tmpToken) {
                    throw new Error("Error during variable assignment in arg" + currMember.argList[currMember.argList.length - 1].name);
                  }
                  //Store value
                  currMember.argList[currMember.argList.length - 1].value = tmpToken.token.trim();
                  Main.debug('----->Function argument defaulted to: ' + tmpToken.token.trim());
                }
              }
            }
          }
          Main.debug('------>Completed paring args: ', currMember.argList);
          //Type the function if needed
          if (src.charAt(index + 1) == ":") {
            tmpToken = AS3Parser.nextWord(src, index + 1, AS3Pattern.VARIABLE_TYPE[0], AS3Pattern.VARIABLE_TYPE[1]); //Parse out the function type if needed
            index = tmpToken.index;
            currMember.type = tmpToken.token;
            Main.debug('------>Typed the function to: ', currMember.type);
          }

          if (cls.isInterface) {
            //Store and delete current member and exit
            currMember.value = '{}';
            if (currMember.subType == 'get') {
              (currMember.isStatic) ? cls.staticGetters.push(currMember): cls.getters.push(currMember);
            } else if (currMember.subType == 'set') {
              (currMember.isStatic) ? cls.staticSetters.push(currMember): cls.setters.push(currMember);
            } else if (currMember.isStatic) {
              cls.staticMembers.push(currMember);
            } else {
              cls.members.push(currMember);
            }
            cls.registerField(currMember.name, currMember);
            //Done parsing function
            currMember = null;
            this.stack.pop();
          } else {
            //Save the function body
            AS3Parser.PREVIOUS_BLOCK = currMember.name + ":Function";
            tmpArr = AS3Parser.extractBlock(src, index);
            index = tmpArr[1];
            currMember.value = tmpArr[0].trim();

            //Store and delete current member and exit
            if (currMember.subType == 'get') {
              (currMember.isStatic) ? cls.staticGetters.push(currMember): cls.getters.push(currMember);
            } else if (currMember.subType == 'set') {
              (currMember.isStatic) ? cls.staticSetters.push(currMember): cls.setters.push(currMember);
            } else if (currMember.isStatic) {
              cls.staticMembers.push(currMember);
            } else {
              cls.members.push(currMember);
            }
            cls.registerField(currMember.name, currMember);

            currMember = null;
            this.stack.pop();
          }
        } else if (this.getState() == AS3ParseState.LOCAL_VARIABLE) {

        } else if (this.getState() == AS3ParseState.LOCAL_FUNCTION) {

        } else if (this.getState() == AS3ParseState.IMPORT_PACKAGE) {
          //The current token is a class import
          currToken = AS3Parser.nextWord(src, index, AS3Pattern.IMPORT[0], AS3Pattern.IMPORT[1]);
          index = currToken.index - 1;
          if (!currToken.token) {
            throw new Error("Error parsing import.");
          } else {
            Main.debug("Parsed import name: " + currToken.token);
            if (currToken.token.indexOf("*") >= 0) {
              cls.importWildcards.push(currToken.token); //To be resolved later
            } else {
              cls.imports.push(currToken.token); //No need to resolve
            }
            this.stack.push(AS3ParseState.PACKAGE);
          }
        } else if (this.getState() == AS3ParseState.REQUIRE_MODULE) {
          //The current token is a module requirement
          currToken = AS3Parser.nextWord(src, index, AS3Pattern.REQUIRE[0], AS3Pattern.REQUIRE[1]);
          index = currToken.index - 1;
          if (!currToken.token)
            throw new Error("Error parsing require.");
          else {
            Main.debug("Parsed require name: " + currToken.token);
            cls.requires.push(currToken.token.trim());
            this.stack.push(AS3ParseState.PACKAGE);
          }
        }
      }
    };
    AS3Parser.prototype.parse = function(options) {
      options = AS3JS.Utils.getDefaultValue(options, null);
      options = options || {};
      if (typeof options.safeRequire !== 'undefined') {
        this.parserOptions.safeRequire = options.safeRequire;
      }
      if (typeof options.ignoreFlash !== 'undefined') {
        this.parserOptions.ignoreFlash = options.ignoreFlash;
      }

      var classDefinition = new AS3Class(this.parserOptions);
      this.stack.splice(0, this.stack.length);
      this.stack.push(AS3ParseState.START);

      this.parseHelper(classDefinition, this.src);

      if (!classDefinition.className) {
        throw new Error("Error, no class provided for package: " + this.classPath);
      }
      return classDefinition;
    }

    module.exports = AS3Parser;
  };
  Program["com.mcleodgaming.as3js.parser.AS3Token"] = function(module, exports) {
    var AS3Token = function(token, index, extra) {
      this.$init();
      this.token = token;
      this.index = index;
      this.extra = extra;
    };

    AS3Token.prototype.$init = function() {};
    AS3Token.prototype.token = null;
    AS3Token.prototype.index = 0;
    AS3Token.prototype.extra = null

    module.exports = AS3Token;
  };
  Program["com.mcleodgaming.as3js.types.AS3Argument"] = function(module, exports) {
    var AS3Variable = module.import('com.mcleodgaming.as3js.types', 'AS3Variable');

    var AS3Argument = function() {
      this.$init();

    };

    AS3Argument.prototype = Object.create(AS3Variable.prototype);

    AS3Argument.prototype.$init = function() {};
    AS3Argument.prototype.isRestParam = false

    module.exports = AS3Argument;
  };
  Program["com.mcleodgaming.as3js.types.AS3Function"] = function(module, exports) {
    var AS3Member = module.import('com.mcleodgaming.as3js.types', 'AS3Member');
    var AS3Variable;
    module.inject = function() {
      AS3Variable = module.import('com.mcleodgaming.as3js.types', 'AS3Variable');
    };

    var AS3Function = function() {
      this.$init();
      this.argList = [];
    };

    AS3Function.prototype = Object.create(AS3Member.prototype);

    AS3Function.prototype.$init = function() {
      this.argList = null;
    };
    AS3Function.prototype.argList = null;
    AS3Function.prototype.hasArgument = function() {
      for (var i = 0; i < this.argList.length; i++)
        if (this.argList[i].name == this.name)
          return true;
      return false;
    };
    AS3Function.prototype.buildLocalVariableStack = function() {
      var i;
      var text = this.value || '';
      var matches = text.match(/(var|,)(.*?)([a-zA-Z_$][0-9a-zA-Z_$]*):([a-zA-Z_$][0-9a-zA-Z_$]*)/g);
      var locals = [];
      if (this.argList) {
        for (i in this.argList) {
          locals.push(this.argList[i]);
        }
      }
      for (i in matches) {
        var tmpVar = new AS3Variable();
        tmpVar.name = matches[i].replace(/(var|,)(.*?)([a-zA-Z_$][0-9a-zA-Z_$]*):([a-zA-Z_$][0-9a-zA-Z_$]*)/g, "$3");
        tmpVar.type = matches[i].replace(/(var|,)(.*?)([a-zA-Z_$][0-9a-zA-Z_$]*):([a-zA-Z_$][0-9a-zA-Z_$]*)/g, "$4");
        locals.push(tmpVar);
      }

      return locals;
    }

    module.exports = AS3Function;
  };
  Program["com.mcleodgaming.as3js.types.AS3Member"] = function(module, exports) {
    var AS3Function, AS3Variable;
    module.inject = function() {
      AS3Function = module.import('com.mcleodgaming.as3js.types', 'AS3Function');
      AS3Variable = module.import('com.mcleodgaming.as3js.types', 'AS3Variable');
    };

    var AS3Member = function() {
      this.$init();
      this.name = null;
      this.type = '*';
      this.subType = null,
        this.value = null;
      this.encapsulation = "public";
      this.isStatic = false;
    };

    AS3Member.prototype.$init = function() {};
    AS3Member.prototype.name = null;
    AS3Member.prototype.type = null;
    AS3Member.prototype.subType = null;
    AS3Member.prototype.value = null;
    AS3Member.prototype.encapsulation = null;
    AS3Member.prototype.isStatic = false;
    AS3Member.prototype.createVariable = function() {
      var obj = new AS3Variable();
      obj.name = this.name;
      obj.type = this.type;
      obj.subType = this.subType,
        obj.value = this.value;
      obj.encapsulation = this.encapsulation;
      obj.isStatic = this.isStatic;
      return obj;
    };
    AS3Member.prototype.createFunction = function() {
      var obj = new AS3Function();
      obj.name = this.name;
      obj.type = this.type;
      obj.subType = this.subType,
        obj.value = this.value;
      obj.encapsulation = this.encapsulation;
      obj.isStatic = this.isStatic;
      return obj;
    }

    module.exports = AS3Member;
  };
  Program["com.mcleodgaming.as3js.types.AS3Variable"] = function(module, exports) {
    var AS3Member = module.import('com.mcleodgaming.as3js.types', 'AS3Member');

    var AS3Variable = function() {
      this.$init();

    };

    AS3Variable.prototype = Object.create(AS3Member.prototype);

    AS3Variable.prototype.$init = function() {}

    module.exports = AS3Variable;
  };
  if (typeof module !== 'undefined') {
    module.exports = AS3JS.load({
      program: Program,
      entry: "com.mcleodgaming.as3js.Main",
      entryMode: "static"
    });
  } else if (typeof window !== 'undefined' && typeof AS3JS !== 'undefined') {
    window['com.mcleodgaming.as3js.Main'] = AS3JS.load({
      program: Program,
      entry: "com.mcleodgaming.as3js.Main",
      entryMode: "static"
    });
  }
})();

================================================
FILE: snippets/class-snippet.js
================================================
Program["{{module}}"] = function ( module, exports ) {
{{source}}
};


================================================
FILE: snippets/main-snippet.js
================================================
(function ( ) {
  var Program = {};
{{packages}}

  if (typeof module !== 'undefined') {
    module.exports = AS3JS.load({ program: Program, entry: "{{entryPoint}}", entryMode: "{{entryMode}}" });
  } else if (typeof window !== 'undefined' && typeof AS3JS !== 'undefined') {
    window['{{entryPoint}}'] = AS3JS.load({ program: Program, entry: "{{entryPoint}}", entryMode: "{{entryMode}}" });
  }
})();

================================================
FILE: src/com/mcleodgaming/as3js/Main.as
================================================
package com.mcleodgaming.as3js
{
	import com.mcleodgaming.as3js.parser.AS3Class;
	import com.mcleodgaming.as3js.parser.AS3Parser;
	require "path"
	require "fs"
	
	public class Main 
	{
		public static var DEBUG_MODE:Boolean = false;
		public static var SILENT:Boolean = false;
		public static function debug():void
		{
			if (Main.SILENT)
			{
				return;
			}
			if (Main.DEBUG_MODE)
			{
				console.log.apply(console, arguments);
			}
		}
		public static function log():void
		{
			if (Main.SILENT)
			{
				return;
			}
			console.log.apply(console, arguments);
		}
		public static function warn():void
		{
			if (Main.SILENT)
			{
				return;
			}
			console.warn.apply(console, arguments);
		}
		
		public function Main() 
		{
			
		}
		
		public function compile(options:Object = null):Object
		{
			var packages:Object = { }; //Will contain the final map of package names to source text
			var i:*;
			var j:*;
			var k:*;
			var m:*;
			var tmp:String;
			options = options || {};
			var srcPaths:Object = options.srcPaths || {};
			var rawPackages:Array = options.rawPackages || [];
			var parserOptions:Object = { safeRequire: options.safeRequire, ignoreFlash: options.ignoreFlash};
			
			//Temp classes for holding raw class info
			var rawClass:AS3Class;
			var rawParser:AS3Parser;
			
			var pkgLists:Object = {};
			for (i in srcPaths)
			{
				pkgLists[srcPaths[i]] = buildPackageList(srcPaths[i]);
			}

			Main.DEBUG_MODE = options.verbose || Main.DEBUG_MODE;
			Main.SILENT = options.silent || Main.SILENT;

			var classes:Object = {};
			var buffer:String = "";
			
			//First, parse through the file-based classes and get the basic information
			for (i in pkgLists)
			{
				for (j in pkgLists[i])
				{
					Main.log('Analyzing class path: ' + pkgLists[i][j].classPath);
					classes[pkgLists[i][j].classPath] = pkgLists[i][j].parse(parserOptions);
					Main.debug(classes[pkgLists[i][j].classPath]);
				}
			}
			
			// Now parse through any raw string classes
			for (i = 0; i < rawPackages.length; i++)
			{
				Main.log('Analyzing class: ' + i);
				rawParser = new AS3Parser(rawPackages[i]);
				rawClass = rawParser.parse(parserOptions);
				classes[rawParser.classPath] = rawClass;
			}

			//Resolve all possible package name wildcards
			for (i in classes)
			{
				//For every class
				for (j in classes[i].importWildcards)
				{
					Main.debug('Resolving ' + classes[i].className + '\'s ' + classes[i].importWildcards[j] + ' ...')
					//For every wild card in the class
					for (k in srcPaths)
					{
						//For each possible source path (should hopefully just be 1 most of the time -_-)
						tmp = srcPaths[k] + path.sep + classes[i].importWildcards[j].replace(/\./g, path.sep).replace(path.sep+'*', '');
						tmp = tmp.replace(/\\/g, '/'); 
						tmp = tmp.replace(/[\/]/g, path.sep); 
						if(fs.existsSync(tmp)) {
							Main.debug('Searching path ' + tmp + '...')
							//Path exists, read the files in the directory
							var files = fs.readdirSync(tmp);
							for(m in files) {
								//See if this is an ActionScript file
								if(fs.statSync(tmp + path.sep + files[m]).isFile() && files[m].lastIndexOf('.as') == files[m].length - 3) {
									//See if the class needs the file
									if(classes[i].needsImport(classes[i].importWildcards[j].replace(/\*/g, files[m].substr(0, files[m].length - 3)))) {
										Main.debug('Auto imported ' + files[m].substr(0, files[m].length - 3));
										classes[i].addImport(classes[i].importWildcards[j].replace(/\*/g, files[m].substr(0, files[m].length - 3))); //Pass in package name with wild card replaced
									}
								}
							}
						} else {
							Main.warn('Warning, could not find directory: ' + tmp);
						}
					}
					// Must do again for classes in case there we
					for (k in classes)
					{
						if(classes[i].needsImport(AS3Parser.fixClassPath(classes[k].packageName + '.' + classes[k].className))) {
							Main.debug('Auto imported ' + AS3Parser.fixClassPath(classes[k].packageName + '.' + classes[k].className));
							classes[i].addImport(AS3Parser.fixClassPath(classes[k].packageName + '.' + classes[k].className)); //Pass in package name with wild card replaced
						}
					}
				}
			}
			
			//Add extra imports before registring them (these will not be imported in the output code, but rather will provide insight for AS3JS to determine variable types)
			for (i in classes)
			{
				for (j in classes)
				{
					classes[i].addExtraImport(AS3Parser.fixClassPath(classes[j].packageName + '.' + classes[j].className));
				}
			}
			
			//Resolve import map
			for (i in classes)
			{
				classes[i].registerImports(classes);
			}

			//Resolve parent imports
			for (i in classes)
			{
				classes[i].findParents(classes);
			}
			
			//Walk through the class members that had assignments in the class scope
			for (i in classes)
			{
				classes[i].checkMembersWithAssignments();
			}
				
			//Process the function text to comply with JS
			for (i in classes)
			{
				Main.log('Parsing package: ' + AS3Parser.fixClassPath(classes[i].packageName + "." + classes[i].className));
				classes[i].process(classes);
			}
			// Load stringified versions of snippets/main-snippet.js and snippets/class-snippet.js
			var mainTemplate:String = "(function(){var Program={};{{packages}}if(typeof module !== 'undefined'){module.exports=AS3JS.load({program:Program,entry:\"{{entryPoint}}\",entryMode:\"{{entryMode}}\"});}else if(typeof window!=='undefined'&&typeof AS3JS!=='undefined'){window['{{entryPoint}}']=AS3JS.load({program:Program,entry:\"{{entryPoint}}\",entryMode:\"{{entryMode}}\"});}})();";
			var classTemplate:String = "Program[\"{{module}}\"]=function(module, exports){{{source}}};";
			var packageObjects:Array = [];
			var classObjects:Array = null;
			var currentClass:String = "";
			
			if (options.entry)
			{
				// Entry point should be in the format "mode:path.to.package.Class"
				var currentPackage:String = options.entry;
				var mode:String = options.entryMode || 'instance';
				// Update template with entry points
				mainTemplate = mainTemplate.replace(/\{\{entryPoint\}\}/g, AS3Parser.fixClassPath(classes[currentPackage].packageName + '.' + classes[currentPackage].className));
				mainTemplate = mainTemplate.replace(/\{\{entryMode\}\}/g, mode);
			} else
			{
				mainTemplate = mainTemplate.replace(/\{\{entryPoint\}\}/g, "");
				mainTemplate = mainTemplate.replace(/\{\{entryMode\}\}/g, "");
			}
			
			//Retrieve converted class code
			var groupByPackage:Object = { };
			for (i in classes)
			{
				groupByPackage[classes[i].packageName] = groupByPackage[classes[i].packageName] || [];
				groupByPackage[classes[i].packageName].push(classes[i]);
			}
			for (i in groupByPackage)
			{
				classObjects = [];
				for (j in groupByPackage[i])
				{
					packages[AS3Parser.fixClassPath(i+"."+groupByPackage[i][j].className)] = groupByPackage[i][j].toString();
					currentClass = classTemplate;
					currentClass = currentClass.replace(/\{\{module\}\}/g, AS3Parser.fixClassPath(groupByPackage[i][j].packageName + "." + groupByPackage[i][j].className));
					currentClass = currentClass.replace(/\{\{source\}\}/g, AS3Parser.increaseIndent(packages[AS3Parser.fixClassPath(i+"."+groupByPackage[i][j].className)], "  "));
					classObjects.push(currentClass);
				}
				packageObjects.push(AS3Parser.increaseIndent(classObjects.join(""), "  "));
			}
			
			mainTemplate = mainTemplate.replace(/\{\{packages\}\}/g, packageObjects.join(""));
			
			mainTemplate = mainTemplate.replace(/\t/g, "  ");
			
			buffer += mainTemplate;
			
			Main.log("Done.");
			
			return { compiledSource: buffer, packageSources: packages };
		}
		private function readDirectory(location:String, pkgBuffer:String, obj:Object):void
		{
			var files:Array = fs.readdirSync(location);
			for (var i in files)
			{
				var pkg:String = pkgBuffer;
				if (fs.statSync(location + path.sep + files[i]).isDirectory())
				{
					var splitPath:Array = location.split(path.sep);
					if (pkg != '')
					{
						pkg += '.';
					}
					this.readDirectory(location + path.sep + files[i], pkg + files[i], obj)
				} else if (fs.statSync(location + path.sep + files[i]).isFile() && files[i].lastIndexOf('.as') == files[i].length - 3)
				{
					if (pkg != '')
					{
						pkg += '.';
					}
					pkg += files[i].substr(0, files[i].length - 3);
					var f = fs.readFileSync(location + path.sep + files[i]);
					obj[pkg] = new AS3Parser(f.toString(), pkg);
					Main.debug("Loaded file: ", location + path.sep + files[i] + " (package: " + pkg + ")");
				}
			}
		}
		public function buildPackageList(location:String):void
		{
			var obj:Object = {};
			var topLevel:String = location;
			location = location.replace(/\\/g, '/'); 
			location = location.replace(/[\/]/g, path.sep); 
			if (fs.existsSync(location) && fs.statSync(location).isDirectory())
			{
				var splitPath = location.split(path.sep);
				readDirectory(location, '', obj);
				return obj;
			} else
			{
				throw new Error("Error could not find directory: " + location);
			}
		}
	}

}

================================================
FILE: src/com/mcleodgaming/as3js/enums/AS3Encapsulation.as
================================================
package com.mcleodgaming.as3js.enums
{
	public class AS3Encapsulation 
	{
		public static const PUBLIC:String = "public";
		public static const PRIVATE:String = "private";
		public static const PROTECTED:String = "protected";
	}
}

================================================
FILE: src/com/mcleodgaming/as3js/enums/AS3MemberType.as
================================================
package com.mcleodgaming.as3js.enums
{
	public class AS3MemberType 
	{
		public static const VAR:String = "var";
		public static const CONST:String = "const";
		public static const FUNCTION:String = "function";
	}
}

================================================
FILE: src/com/mcleodgaming/as3js/enums/AS3ParseState.as
================================================
package com.mcleodgaming.as3js.enums
{
	public class AS3ParseState 
	{
		public static const START:String = "start";
		public static const PACKAGE_NAME:String = "packageName";
		public static const PACKAGE:String = "package";
		public static const CLASS_NAME:String = "className";
		public static const CLASS:String = "class";
		public static const CLASS_EXTENDS:String = "classExtends";
		public static const CLASS_IMPLEMENTS:String = "classImplements";
		public static const COMMENT_INLINE:String = "commentInline";
		public static const COMMENT_MULTILINE:String = "commentMultiline";
		public static const STRING_SINGLE_QUOTE:String = "stringSingleQuote";
		public static const STRING_DOUBLE_QUOTE:String = "stringDoubleQuote";
		public static const STRING_REGEX:String = "stringRegex";
		public static const MEMBER_VARIABLE:String = "memberVariable";
		public static const MEMBER_FUNCTION:String = "memberFunction";
		public static const LOCAL_VARIABLE:String = "localVariable";
		public static const LOCAL_FUNCTION:String = "localFunction";
		public static const IMPORT_PACKAGE:String = "importPackage";
		public static const REQUIRE_MODULE:String = "requireModule";
	}
}

================================================
FILE: src/com/mcleodgaming/as3js/enums/AS3Pattern.as
================================================
package com.mcleodgaming.as3js.enums
{
	public class AS3Pattern 
	{
		public static const IDENTIFIER:Array = [ /\w/g, /\w/g ];
		public static const OBJECT:Array = [ /[\w\.]/g, /[\w(\w(\.\w)+)]/g ];
		public static const IMPORT:Array = [ /[0-9a-zA-Z_$.*]/g, /[a-zA-Z_$][0-9a-zA-Z_$]([.][a-zA-Z_$][0-9a-zA-Z_$])*\*?/g ];
		public static const REQUIRE:Array = [ /./g, /["'](.*?)['"]/g ];
		public static const CURLY_BRACE:Array = [ /[\{|\}]/g, /[\{|\}]/g ];
		public static const VARIABLE:Array = [ /[0-9a-zA-Z_$]/g, /[a-zA-Z_$][0-9a-zA-Z_$]*/g ];
		public static const VARIABLE_TYPE:Array = [ /[a-zA-Z_$<>.*][0-9a-zA-Z_$<>.]*/g, /[a-zA-Z_$<>.*][0-9a-zA-Z_$<>.]*/g ];
		public static const VARIABLE_DECLARATION:Array = [ /[0-9a-zA-Z_$:<>.*]/g, /[a-zA-Z_$][0-9a-zA-Z_$]*\s*:\s*([a-zA-Z_$<>\.\*][0-9a-zA-Z_$<>\.]*)/g ];
		public static const ASSIGN_START:Array = [ /[=\r\n]/g, /[=\r\n]/g ];
		public static const ASSIGN_UPTO:Array = [ new RegExp("[^;\\r\\n]", "g"), /(.*?)/g ];
		public static const VECTOR:Array = [ /new[\s\t]+Vector\.<(.*?)>\((.*?)\)/g, /new[\s\t]+Vector\.<(.*?)>\((.*?)\)/ ];
		public static const ARRAY:Array = [ /new[\s\t]+Array\((.*?)\)/g, /new[\s\t]+Array\((.*?)\)/ ];
		public static const DICTIONARY:Array = [ /new[\s\t]+Dictionary\((.*?)\)/g ];
		public static const REST_ARG:Array = [ /\.\.\.[a-zA-Z_$][0-9a-zA-Z_$]*/g, /\.\.\.[a-zA-Z_$][0-9a-zA-Z_$]*/g];
	}
}

================================================
FILE: src/com/mcleodgaming/as3js/parser/AS3Class.as
================================================
package com.mcleodgaming.as3js.parser
{
	import com.mcleodgaming.as3js.Main;
	import com.mcleodgaming.as3js.enums.*;
	import com.mcleodgaming.as3js.types.*;
	
	public class AS3Class 
	{
		public static var reservedWords:Array = ["as", "class", "delete", "false", "if", "instanceof", "native", "private", "super", "to", "use", "with", "break", "const", "do", "finally", "implements", "new", "protected", "switch", "true", "var", "case", "continue", "else", "for", "import", "internal", "null", "public", "this", "try", "void", "catch", "default", "extends", "function", "in", "is", "package", "return", "throw", "typeof", "while", "each", "get", "set", "namespace", "include", "dynamic", "final", "natiev", "override", "static", "abstract", "char", "export", "long", "throws", "virtual", "boolean", "debugger", "float", "prototype", "to", "volatile", "byte", "double", "goto", "short", "transient", "cast", "enum", "intrinsic", "synchronized", "type"];
		
		public static var nativeTypes:Array = ["Boolean", "Number", "int", "uint", "String" ];
		
		public var packageName:String;
		public var className:String;
		public var imports:Vector.<String>;
		public var requires:Vector.<String>;
		public var importWildcards:Vector.<String>;
		public var importExtras:Vector.<String>;
		public var interfaces:Vector.<String>;
		public var parent:String;
		public var parentDefinition:AS3Class;
		public var members:Vector.<AS3Member>;
		public var staticMembers:Vector.<AS3Member>;
		public var getters:Vector.<AS3Member>;
		public var setters:Vector.<AS3Member>;
		public var staticGetters:Vector.<AS3Member>;
		public var staticSetters:Vector.<AS3Member>;
		public var isInterface:Boolean;
		public var membersWithAssignments:Vector.<AS3Member>; //List of class members that have assignments in the class-level scope
		public var fieldMap:Object; //Maps instance field names to instance members
		public var staticFieldMap:Object; //Maps static field names to static members
		public var classMap:Object; //Maps class shorthand name to class
		public var classMapFiltered:Object; //Same as classMap but only references classes that are actually used (i.e. used in another way besides just a "type")
		public var packageMap:Object; //Maps full package path to class
		
		// Options
		public var safeRequire:Boolean; //Try catch around parsed require statements
		public var ignoreFlash:Boolean; //Ignore FL imports
			
		public function AS3Class(options:Object = null) 
		{
			options = options || { };
			safeRequire = false;
			
			if (typeof options.safeRequire !== 'undefined')
			{
				safeRequire = options.safeRequire;
			}
			if (typeof options.ignoreFlash !== 'undefined')
			{
				ignoreFlash = options.ignoreFlash;
			}
			
			packageName = null;
			className = null;
			imports = new Vector.<String>();
			requires = new Vector.<String>();
			importWildcards = new Vector.<String>();
			importExtras = new Vector.<String>();
			interfaces = new Vector.<String>();
			parent = null;
			parentDefinition = null;
			members = new Vector.<AS3Member>();
			staticMembers = new Vector.<AS3Member>();
			getters = new Vector.<AS3Member>();
			setters = new Vector.<AS3Member>();
			staticGetters = new Vector.<AS3Member>();
			staticSetters = new Vector.<AS3Member>();
			membersWithAssignments = new Vector.<AS3Member>();
			isInterface = false;
			fieldMap = {};
			staticFieldMap = {};
			classMap = { };
			classMapFiltered = { };
			packageMap = { };
			
			var $init:AS3Function = new AS3Function();
			$init.name = "$init";
			$init.value = "{}";
			$init.type === AS3MemberType.FUNCTION;
			$init.isStatic = false;
			members.push($init);
			registerField($init.name, $init);
		}
		public function registerImports(clsList:Object):void
		{
			var i;
			for (i in imports)
			{
				if (clsList[imports[i]])
				{
					var lastIndex:int = imports[i].lastIndexOf(".");
					var shorthand:String = (lastIndex < 0) ? imports[i] : imports[i].substr(lastIndex + 1);
					classMap[shorthand] = clsList[imports[i]];
				}
			}
			for (i in importExtras)
			{
				if (clsList[importExtras[i]])
				{
					var lastIndex:int = importExtras[i].lastIndexOf(".");
					var shorthand:String = (lastIndex < 0) ? importExtras[i] : importExtras[i].substr(lastIndex + 1);
					classMap[shorthand] = clsList[importExtras[i]];
				}
			}
			packageMap = clsList;
		}
		public function registerField(name:String, value:AS3Member):void
		{
			if (value && value.isStatic)
			{
				staticFieldMap[name] = staticFieldMap[name] || value;
			} else
			{
				fieldMap[name] = fieldMap[name] || value;
			}
		}
		public function retrieveField(name:String, isStatic:Boolean):AS3Member
		{
			if (isStatic)
			{
				if (staticFieldMap[name])
				{
					return staticFieldMap[name];
				} else if (parentDefinition)
				{
					return parentDefinition.retrieveField(name, isStatic);
				} else
				{
					return null;
				}
			} else
			{
				if (fieldMap[name])
				{
					return fieldMap[name];
				} else if (parentDefinition)
				{
					return parentDefinition.retrieveField(name, isStatic);
				} else
				{
					return null;
				}
			}
		}
		public function needsImport(pkg:String):Boolean
		{
			var i:*;
			var j:*;
			var lastIndex:int = pkg.lastIndexOf(".");
			var shorthand:String = (lastIndex < 0) ? pkg : pkg.substr(lastIndex + 1);
			var matches:Vector.<AS3Member>;

			if (imports.indexOf(pkg) >= 0)
			{
				return false; //Class was already imported
			}

			if (shorthand == className && pkg == packageName)
			{
				return true; //Don't need self
			}
				
			if (shorthand == parent)
			{
				return true; //Parent class is in another package
			}
			
			//Now we must parse through all members one by one, looking at functions and variable types to determine the necessary imports
				
			for (i in members)
			{
				//See if the function definition or variable assigment have a need for this package
				if (members[i] instanceof AS3Function)
				{
					matches = members[i].value.match(AS3Pattern.VARIABLE_DECLARATION[1]);
					for (j in matches)
					{
						if(matches[j].split(":")[1] == shorthand)
							return true;
					}
					for (j in members[i].argList)
					{
						if(typeof members[i].argList[j].type == 'string' && members[i].argList[j].type == shorthand)
							return true;
					}
				}
				if (typeof members[i].value == 'string' && members[i].value.match(new RegExp("([^a-zA-Z_$.])" + shorthand + "([^0-9a-zA-Z_$])", "g")))
				{
					return true;
				} else if (typeof members[i].type == 'string' && members[i].type == shorthand)
				{
					return true;
				}
			}
			for (i in staticMembers)
			{
				//See if the function definition or variable assigment have a need for this package
				if (staticMembers[i] instanceof AS3Function)
				{
					matches = staticMembers[i].value.match(AS3Pattern.VARIABLE_DECLARATION[1]);
					for (j in matches)
					{
						if (matches[j].split(":")[1] == shorthand)
						{
							return true;
						}
					}
					for (j in staticMembers[i].argList) 
					{
						if (typeof staticMembers[i].argList[j].type == 'string' && staticMembers[i].argList[j].type == shorthand)
						{
							return true;
						}
					}
				}
				if (typeof staticMembers[i].value == 'string' && staticMembers[i].value.match(new RegExp("([^a-zA-Z_$.])" + shorthand + "([^0-9a-zA-Z_$])", "g")))
				{
					return true;
				} else if (typeof staticMembers[i].type == 'string' && staticMembers[i].type == shorthand)
				{
					return true;
				}
			}
			for (i in getters)
			{
				//See if the function definition or variable assigment have a need for this package
				matches = getters[i].value.match(AS3Pattern.VARIABLE_DECLARATION[1]);
				for (j in matches)
				{
					if (matches[j].split(":")[1] == shorthand)
					{
						return true;
					}
				}
				for (j in getters[i].argList)
				{
					if (typeof getters[i].argList[j].type == 'string' && getters[i].argList[j].type == shorthand)
					{
						return true;
					}
				}
				if (typeof getters[i].value == 'string' && getters[i].value.match(new RegExp("([^a-zA-Z_$.])" + shorthand + "([^0-9a-zA-Z_$])", "g")))
				{
					return true;
				} else if (typeof getters[i].type == 'string' && getters[i].type == shorthand)
				{
					return true;
				}
			}
			for (i in setters)
			{
				matches = setters[i].value.match(AS3Pattern.VARIABLE_DECLARATION[1]);
				for (j in matches)
				{
					if (matches[j].split(":")[1] == shorthand)
					{
						return true;
					}
				}
				//See if the function definition or variable assigment have a need for this package
				for (j in setters[i].argList) 
				{
					if (typeof setters[i].argList[j].type == 'string' && setters[i].argList[j].type == shorthand)
					{
						return true;
					}
				}
				if (typeof setters[i].value == 'string' && setters[i].value.match(new RegExp("([^a-zA-Z_$.])" + shorthand + "([^0-9a-zA-Z_$])", "g")))
				{
					return true;
				} else if (typeof setters[i].type == 'string' && setters[i].type == shorthand)
				{
					return true;
				}
			}
			for (i in staticGetters)
			{
				matches = staticGetters[i].value.match(AS3Pattern.VARIABLE_DECLARATION[1]);
				for (j in matches)
				{
					if (matches[j].split(":")[1] == shorthand)
					{
						return true;
					}
				}
				//See if the function definition or variable assigment have a need for this package
				for (j in staticGetters[i].argList)
				{
					if (typeof staticGetters[i].argList[j].type == 'string' && staticGetters[i].argList[j].type == shorthand)
					{
						return true;
					}
				}
				if (typeof staticGetters[i].value == 'string' && staticGetters[i].value.match(new RegExp("([^a-zA-Z_$.])" + shorthand + "([^0-9a-zA-Z_$])", "g")))
				{
					return true;
				} else if (typeof staticGetters[i].type == 'string' && staticGetters[i].type == shorthand)
				{
					return true;
				}
			}
			for (i in staticSetters)
			{
				matches = staticSetters[i].value.match(AS3Pattern.VARIABLE_DECLARATION[1]);
				for (j in matches)
				{
					if (matches[j].split(":")[1] == shorthand)
					{
						return true;
					}
				}
				for (j in staticSetters[i].argList)
				{
					if (typeof staticSetters[i].argList[j].type == 'string' && staticSetters[i].argList[j].type == shorthand)
					{
						return true;
					}
				}
				//See if the function definition or variable assigment have a need for this package
				if (typeof staticSetters[i].value == 'string' && staticSetters[i].value.match(new RegExp("([^a-zA-Z_$.])" + shorthand + "([^0-9a-zA-Z_$])", "g")))
				{
					return true;
				} else if (typeof staticSetters[i].type == 'string' && staticSetters[i].type == shorthand)
				{
					return true;
				}
			}
			
			var classMember:AS3Member;
			// Same logic as checkMembersWithAssignments()
			// For each member that has an assignment at the top-level scope
			for (i = 0; i < membersWithAssignments.length; i++)
			{
				classMember = membersWithAssignments[i];
				// Make a dumb attempt to identify use of the class as assignments here
				if (classMember.value && classMember.value.indexOf(shorthand) >= 0 && !(parentDefinition && parentDefinition.packageName + "." + parentDefinition.className === pkg))
				{
					return true;
				}
			}
			
			return false;
		}
		public function addImport(pkg:String):void
		{
			if (imports.indexOf(pkg) < 0)
			{
				imports.push(pkg);
			}
		}
		public function addExtraImport(pkg:String):void
		{
			if (importExtras.indexOf(pkg) < 0)
			{
				importExtras.push(pkg);
			}
		}
		public function findParents(classes:Vector.<AS3Class>):void
		{
			if (!parent)
			{
				return;
			}
			for (var i in classes)
			{
				//Only gather vars from the parent
				if (classes[i] != this && parent == classes[i].className)
				{
					parentDefinition = classes[i]; //Found our parent
					return;
				}
			}
		}
		public function checkMembersWithAssignments():void
		{
			var i:int;
			var j:*;
			var classMember:AS3Member;
			// If the type of this param is a Class
			for (i = 0; i < membersWithAssignments.length; i++)
			{
				classMember = membersWithAssignments[i];
				// Make a dumb attempt to identify use of the class as assignments here
				for (j in imports)
				{
					if (packageMap[imports[j]] && classMember.value.indexOf(packageMap[imports[j]].className) >= 0 && parentDefinition !== packageMap[imports[j]])
					{
						// If this is a token that matches a class from an import statement, store it in the filtered classMap
						classMapFiltered[packageMap[imports[j]].className] = packageMap[imports[j]];
					}
				}
			}
		}
		public function stringifyFunc(fn:AS3Member):String
		{
			var buffer:String = "";
			if (fn instanceof AS3Function)
			{
				//Functions need to be handled differently
				//Prepend sub-type if it exists
				if (fn.subType)
				{
					buffer += fn.subType + '_';
				}
				//Print out the rest of the name and start the function definition
				buffer += fn.name
				buffer += " = function(";
				//Concat all of the arguments together
				tmpArr = [];
				for (j = 0; j < fn.argList.length; j++)
				{
					if (!fn.argList[j].isRestParam)
					{
						tmpArr.push(fn.argList[j].name);
					}
				}
				buffer += tmpArr.join(", ") + ") ";
				//Function definition is finally added
				buffer += fn.value + ";\n";
			} else if (fn instanceof AS3Variable)
			{
				//Variables can be added immediately
				buffer += fn.name;
				buffer += " = " + fn.value + ";\n";
			}
			return buffer;
		}
		
		public function process(classes:Vector.<AS3Class>):void
		{
			var self:AS3Class = this;
			var i:int;
			var index:int;
			var currParent:AS3Class = this;
			var allMembers:Vector.<AS3Member> = new Vector.<AS3Member>();
			var allFuncs:Vector.<AS3Function> = new Vector.<AS3Function>();
			var allStaticMembers:Vector.<AS3Member> = new Vector.<AS3Member>();
			var allStaticFuncs:Vector.<AS3Function> = new Vector.<AS3Function>();

			while (currParent)
			{
				//Parse members of this parent
				for (i in currParent.setters)
				{
					allMembers.push(currParent.setters[i]);
				}
				for (i in currParent.staticSetters)
				{
					allStaticMembers.push(currParent.staticSetters[i]);
				}
				for (i in currParent.getters)
				{
					allMembers.push(currParent.getters[i]);
				}
				for (i in currParent.staticGetters)
				{
					allStaticMembers.push(currParent.staticGetters[i]);
				}
				for (i in currParent.members)
				{
					allMembers.push(currParent.members[i]);
				}
				for (i in currParent.staticMembers)
				{
					allStaticMembers.push(currParent.staticMembers[i]);
				}
					
				//Go to the next parent
				currParent = currParent.parentDefinition;
			}
			
			//Add copies of the setters and getters to the "all" arrays (for convenience)
			for (i in setters)
			{
				if (setters[i] instanceof AS3Function)
				{
					allFuncs.push(setters[i]);
				}
			}
			for (i in staticSetters)
			{
				if (staticSetters[i] instanceof AS3Function)
				{
					allStaticFuncs.push(staticSetters[i]);
				}
			}
			for (i in getters)
			{
				if (getters[i] instanceof AS3Function)
				{
					allFuncs.push(getters[i]);
				}
			}
			for (i in staticGetters)
			{
				if (staticGetters[i] instanceof AS3Function)
				{
					allStaticFuncs.push(staticGetters[i]);
				}
			}
			for (i in members)
			{
				if (members[i] instanceof AS3Function)
				{
					allFuncs.push(members[i]);
				}
				if (members[i] instanceof AS3Variable)
				{
					// Fix any obvious assignments that rely on implicit static class name (only works for simple statements)
					if (members[i].value && retrieveField(members[i].value.replace(/^([a-zA-Z_$][0-9a-zA-Z_$]*)(.*?)$/g, "$1"), true))
					{
						members[i].value = className + '.' + members[i].value;
					}
				}
			}
			for (i in staticMembers)
			{
				if (staticMembers[i] instanceof AS3Function)
				{
					allStaticFuncs.push(staticMembers[i]);
				}
				if (staticMembers[i] instanceof AS3Variable)
				{
					// Fix any obvious assignments that rely on implicit static class name (only works for simple statements)
					if (staticMembers[i].value && retrieveField(staticMembers[i].value.replace(/^([a-zA-Z_$][0-9a-zA-Z_$]*)(.*?)$/g, "$1"), true))
					{
						staticMembers[i].value = className + '.' + staticMembers[i].value;
					}
				}
			}

			// Insert $init function for instantiations
			for (i in allFuncs)
			{
				Main.debug("Now parsing function: " + className + ":" + allFuncs[i].name);
				allFuncs[i].value = AS3Parser.parseFunc(this, allFuncs[i].value, allFuncs[i].buildLocalVariableStack(), allFuncs[i].isStatic)[0];
				allFuncs[i].value = AS3Parser.checkArguments(allFuncs[i]);
				if (allFuncs[i].name === "$init")
				{
					//Inject instantiations here
					allFuncs[i].value = AS3Parser.injectInstantiations(this, allFuncs[i]);
				}
				if (allFuncs[i].name === className)
				{
					//Inject $init() into constructor
					allFuncs[i].value = AS3Parser.injectInit(this, allFuncs[i]);
				}
				allFuncs[i].value = AS3Parser.cleanup(allFuncs[i].value);
				//Fix supers
				allFuncs[i].value = allFuncs[i].value.replace(/super\.(.*?)\(/g, parent + '.prototype.$1.call(this, ').replace(/\.call\(this,\s*\)/g, ".call(this)");
				allFuncs[i].value = allFuncs[i].value.replace(/super\(/g, parent + '.call(this, ').replace(/\.call\(this,\s*\)/g, ".call(this)");
				allFuncs[i].value = allFuncs[i].value.replace(new RegExp("this[.]" + parent, "g"), parent); //Fix extra 'this' on the parent
			}
			
			for (i in allStaticFuncs)
			{
				Main.debug("Now parsing static function: " + className + ":" + allStaticFuncs[i].name);
				allStaticFuncs[i].value = AS3Parser.parseFunc(this, allStaticFuncs[i].value, allStaticFuncs[i].buildLocalVariableStack(), allStaticFuncs[i].isStatic)[0];
				allStaticFuncs[i].value = AS3Parser.checkArguments(allStaticFuncs[i]);
				allStaticFuncs[i].value = AS3Parser.cleanup(allStaticFuncs[i].value);
			}
		}
		public function toString():String
		{
			//Outputs the class inside a JS function
			var i:*;
			var j:*;
			var buffer:String = "";

			if (requires.length > 0)
			{
				if (safeRequire)
				{
					for (i in requires)
					{
						buffer += 'var ' + requires[i].substring(1, requires[i].length-1) + ' = (function () { try { return require(' + requires[i] + '); } catch(e) { return undefined; }})();\n';
					}
				} else
				{
					for (i in requires)
					{
						buffer += 'var ' + requires[i].substring(1, requires[i].length-1) + ' = require(' + requires[i] + ');\n';
					}
				}
				buffer += "\n";
			}
		
			var tmpArr:Array = null;

			//Parent class must be imported if it exists
			if (parentDefinition)
			{
				buffer += "var " + parentDefinition.className + " = module.import('" + parentDefinition.packageName + "', '" + parentDefinition.className + "');\n";
			}

			//Create refs for all the other classes
			if (imports.length > 0)
			{
				tmpArr = [];
				for (i in imports)
				{
					if (!(ignoreFlash && imports[i].indexOf('flash.') >= 0) && parent != imports[i].substr(imports[i].lastIndexOf('.') + 1) && packageName + '.' + className != imports[i]) //Ignore flash imports
					{
						// Must be in the filtered map, otherwise no point in writing
						if (!packageMap[imports[i]])
						{
							Main.warn("Warning, missing class path: " + imports[i] + " (found in " + packageName + '.' + className + ")");
						} else if (classMapFiltered[packageMap[imports[i]].className])
						{
							tmpArr.push(imports[i].substr(imports[i].lastIndexOf('.') + 1)); //<-This will return characters after the final '.', or the entire String if no '.'
						}
					}
				}
				//Join up separated by commas
				if (tmpArr.length > 0)
				{
					buffer += 'var ';
					buffer += tmpArr.join(", ") + ";\n";
				}
			}
			//Check for injection function code
			var injectedText = "";
			for (i in imports)
			{
				if (!(ignoreFlash && imports[i].indexOf('flash.') >= 0) && packageName + '.' + className != imports[i] && !(parentDefinition && parentDefinition.packageName + '.' + parentDefinition.className == imports[i])) //Ignore flash imports and parent for injections
				{
					// Must be in the filtered map, otherwise no point in writing
					if (!packageMap[imports[i]])
					{
						Main.warn("Warning, missing class path: " + imports[i] + " (found in " + packageName + '.' + className + ")");
					} else if (classMapFiltered[packageMap[imports[i]].className])
					{
						injectedText += "\t" + imports[i].substr(imports[i].lastIndexOf('.') + 1) + " = module.import('" + packageMap[imports[i]].packageName + "', '" + packageMap[imports[i]].className + "');\n";
					}
				}
			}
			
			if (injectedText.length > 0)
			{
				buffer += "module.inject = function () {\n";
				buffer += injectedText;
				buffer += "};\n";
			}
			
			buffer += '\n';
			
			buffer += (fieldMap[className]) ? "var " + stringifyFunc(fieldMap[className]) : "var " + className + " = function " + className + "() {};";
			
			buffer += '\n';
			buffer += '\n';
			
			if (parent)
			{
				//Extend parent if necessary
				buffer += className + ".prototype = Object.create(" + parent + ".prototype);";
			}
			
			buffer += '\n\n';
			
			// Deal with static member assigments
			if (staticMembers.length > 0)
			{
				//Place defaults first
				for (i in staticMembers)
				{
					if (staticMembers[i] instanceof AS3Function)
					{
						buffer += className + "." + stringifyFunc(staticMembers[i]);
					} else if (staticMembers[i].type === "Number" || staticMembers[i].type === "int" || staticMembers[i].type === "uint")
					{
						if (isNaN(parseInt(staticMembers[i].value)))
						{
							buffer += className + "." + staticMembers[i].name + ' = 0;\n';
						} else
						{
							buffer += className + "." + stringifyFunc(staticMembers[i]);
						}
					} else if (staticMembers[i].type === "Boolean")
					{
						buffer += className + "." + staticMembers[i].name + ' = false;\n';
					} else
					{
						buffer += className + "." +  staticMembers[i].name + ' = null;\n';
					}
				}
				for (i in staticGetters)
				{
					buffer += className + "." + stringifyFunc(staticGetters[i]);
				}
				for (i in staticSetters)
				{
					buffer += className + "." + stringifyFunc(staticSetters[i]);
				}
				
				buffer += '\n';
				
				buffer += className + ".$cinit = function () {\n";
				
				// Now do the assignments for the rest
				for (i in staticMembers)
				{
					if (!(staticMembers[i] instanceof AS3Function))
					{
						buffer += "\t" + AS3Parser.cleanup( className + '.' + staticMembers[i].name + ' = ' + staticMembers[i].value + ";\n");
					}
				}
				
				buffer += '\n';
				buffer += "};\n";
			}		
			buffer += "\n";
			
			for (i in getters)
			{
				buffer += className + ".prototype." + stringifyFunc(getters[i]);
			}
			for (i in setters)
			{
				buffer += className + ".prototype." + stringifyFunc(setters[i]);
			}
			for (i in members)
			{
				if (members[i].name === className)
				{
					continue;
				}
				if (members[i] instanceof AS3Function || (AS3Class.nativeTypes.indexOf(members[i].type) >= 0 && members[i].value))
				{
					buffer += className + ".prototype." + stringifyFunc(members[i]); //Print functions immediately
				} else if (members[i].type === "Number" || members[i].type === "int" || members[i].type === "uint")
				{
					if (isNaN(parseInt(members[i].value)))
					{
						buffer += className + ".prototype." + members[i].name + ' = 0;\n';
					} else
					{
						buffer += className + ".prototype." + stringifyFunc(members[i]);
					}
				} else if (members[i].type === "Boolean")
				{
					buffer += className + ".prototype." + members[i].name + ' = false;\n';
				} else
				{
					buffer += className + ".prototype." + members[i].name + ' = null;\n';
				}
			}

			buffer = buffer.substr(0, buffer.length - 2) + "\n"; //Strips the final comma out of the string

			buffer += "\n\n";
			buffer += "module.exports = " + className + ";\n";

			//Remaining fixes
			buffer = buffer.replace(/(this\.)+/g, "this.");

			return buffer;
		}
	}
}

================================================
FILE: src/com/mcleodgaming/as3js/parser/AS3Parser.as
================================================
package com.mcleodgaming.as3js.parser
{
	import com.mcleodgaming.as3js.Main;
	import com.mcleodgaming.as3js.enums.*;
	import com.mcleodgaming.as3js.types.*;
	require "path"
	require "fs"
	
	public class AS3Parser 
	{
		/**
		 * Keeps track of previous function name to assist extractBlock() debugging
		 * TODO: This could definitely be implemented better
		 */
		public static var PREVIOUS_BLOCK:String;
		
		//public var index:int;
		public var stack:Array;
		public var src:String;
		public var classPath:String;
		public var parserOptions:Object;
			
		public function AS3Parser(src:String, classPath:String = null):void 
		{
			//index = 0;
			stack = [];
			this.src = src;
			this.classPath = classPath;
			parserOptions = { };
			parserOptions.safeRequire = false;
			parserOptions.ignoreFlash = false;
		}
		
		public static function increaseIndent(str:String, indent:String):String
		{
			return (indent + str).replace(/\n/g, "\n" + indent);
		}
		public static function parseArguments(str:String):Array
		{
			var args:Vector.<AS3Argument> = new Vector.<AS3Argument>();
			var tmpToken:AS3Token;
			var tmpArr:Array = AS3Parser.extractBlock(str, 0, '(', ')');
			var tmpExtractArr:Array = null;
			var index:int = tmpArr[1] - 1; //Ending index of parsed block
			var tmpStr:String = tmpArr[0].trim(); //Parsed block
			tmpStr = tmpStr.substr(1, tmpStr.length - 2); //Remove outer parentheses
			tmpArr = null; //Trash this
			tmpArr = tmpStr.split(','); //Split args by commas
			//Don't bother if there are no arguments
			if (tmpArr.length > 0 && tmpArr[0] != '')
			{
				//Truncate spaces and assign values to arguments as needed
				for (var i = 0; i < tmpArr.length; i++)
				{
					tmpStr = tmpArr[i].trim();
					args.push(new AS3Argument());
					if (tmpStr.indexOf('...') === 0)
					{
						//This is a ...rest argument, stop here
						args[args.length-1].name = tmpStr.substr(3);
						args[args.length-1].isRestParam = true;
						Main.debug('----->Parsed a ...rest param: ' + args[args.length-1].name);
						break;
					} else
					{
						//Grab the function name
						tmpToken = AS3Parser.nextWord(tmpStr, 0, AS3Pattern.VARIABLE[0], AS3Pattern.VARIABLE[1]); //Parse out the function name
						args[args.length-1].name = tmpToken.token; //Set the argument name
						Main.debug('----->Sub-Function argument found: ' + tmpToken.token);
						//If a colon was next, we'll assume it was typed and grab it
						if (tmpToken.index < tmpStr.length && tmpStr.charAt(tmpToken.index) == ':')
						{
							tmpToken = AS3Parser.nextWord(tmpStr, tmpToken.index, AS3Pattern.VARIABLE_TYPE[0], AS3Pattern.VARIABLE_TYPE[1]); //Parse out the argument type
							args[args.length-1].type = tmpToken.token; //Set the argument type
							Main.debug('----->Sub-Function argument typed to: ' + tmpToken.token);
						}
						tmpToken = AS3Parser.nextWord(tmpStr, tmpToken.index, AS3Pattern.ASSIGN_START[0], AS3Pattern.ASSIGN_START[1]);
						if (tmpToken.token == "=")
						{
							//Use all characters after self symbol to set value
							tmpExtractArr = AS3Parser.extractUpTo(tmpStr, tmpToken.index, /[;\r\n]/g);
							//Store value
							args[args.length-1].value =  tmpExtractArr[0].trim();
							//Store value
							Main.debug('----->Sub-Function argument defaulted to: ' + tmpExtractArr[0].trim());
						}
					}
				}
			}
			return args;
		}
		public static function checkForCommentOpen(str:String):String
		{
			return (str == "//") ? AS3ParseState.COMMENT_INLINE : (str == "/*") ? AS3ParseState.COMMENT_MULTILINE : null;
		}
		public static function checkForCommentClose(state, str):Boolean
		{
			return (state == AS3ParseState.COMMENT_INLINE && (str.charAt(0) == '\n' || str.charAt(0) == '\r' || str.charAt(0) == '')) ? true : (state == AS3ParseState.COMMENT_MULTILINE && str == "*/") ? true : false; 
		}
		public static function checkForStringOpen(str:String):String
		{
			return (str == '"') ? AS3ParseState.STRING_DOUBLE_QUOTE : (str == "'") ? AS3ParseState.STRING_SINGLE_QUOTE : null;
		}
		public static function checkForStringClose(state, str):Boolean
		{
			return (state == AS3ParseState.STRING_DOUBLE_QUOTE && str == '"') ? true : (state == AS3ParseState.STRING_SINGLE_QUOTE && str == "'") ? true : false; 
		}
		public static function nextWord(src:String, index:int, characters:String, pattern:String):AS3Token
		{
			characters = characters || AS3Pattern.IDENTIFIER[0];
			pattern = pattern || AS3Pattern.IDENTIFIER[1];
			var tokenBuffer:String = null;
			var extraBuffer:String = ''; //Contains characters that were missed
			var escapeToggle:Boolean = false;
			var innerState:String = null;
			for (; index < src.length; index++)
			{
				var c = src.charAt(index);
				if (c.match(characters))
				{
					tokenBuffer = (tokenBuffer) ? tokenBuffer + c : c; //Create new token buffer if needed, otherwise append
				} else if (!innerState && AS3Parser.checkForCommentOpen(src.substr(index, 2)) && !tokenBuffer)
				{
					tokenBuffer = null;
					Main.debug("Entering comment...");
					innerState = AS3Parser.checkForCommentOpen(src.substr(index, 2));
					extraBuffer += src.substr(index, 2);
					index += 2; //Skip next index
					//Loop until we break out of comment
					for (; index < src.length; index++)
					{
						if (AS3Parser.checkForCommentClose(innerState, src.substr(index, 2)))
						{
							if (innerState == AS3ParseState.COMMENT_MULTILINE)
							{
								extraBuffer += src.substr(index, 2);
								index++; //Skip next token
							} else
							{
								extraBuffer += src.charAt(index);
							}
							innerState = null; //Return to previous state
							Main.debug("Exiting comment...");
							break;
						} else
						{
							extraBuffer += src.charAt(index);
						}
					}
				}  else if (!innerState && AS3Parser.checkForStringOpen(src.charAt(index)) && !tokenBuffer)
				{
					tokenBuffer = null;
					Main.debug("Entering string...");
					innerState = AS3Parser.checkForStringOpen(src.charAt(index));
					extraBuffer += src.substr(index, 1);
					index++; //Skip to next index
					//Loop until we break out of string
					for (; index < src.length; index++)
					{
						extraBuffer += src.charAt(index);
						if (!escapeToggle && src.charAt(index) == '\\')
						{
							escapeToggle = true;
							continue;
						}
						escapeToggle = false;
						if (AS3Parser.checkForStringClose(innerState, src.charAt(index)))
						{
							innerState = null; //Return to previous state
							Main.debug("Exiting string...");
							break;
						}
					}
				} else if (tokenBuffer && tokenBuffer.match(pattern))
				{
					return new AS3Token(tokenBuffer, index, extraBuffer); //[Token, Index]
				} else
				{
					if (tokenBuffer)
					{
						extraBuffer += tokenBuffer + c;
					} else 
					{
						extraBuffer += c;
					}
					tokenBuffer = null;
				}
			}
			return new AS3Token(tokenBuffer || null, index, extraBuffer); //[Token, Index]
		}
		public static function extractBlock(text:String, start:int = 0, opening:String = "{", closing:String = "}"):Array
		{
			var buffer:String = "";
			var i:int = start;
			var count:int = 0;
			var started:Boolean = false;
			var insideString:String = null;
			var insideComment:String = null;
			var escapingChar:Boolean = false;
			while (!(count == 0 && started) && i < text.length)
			{
				if (insideComment)
				{
					//Inside of a comment, wait until we get out
					if (insideComment == '//' && (text.charAt(i) == '\n' || text.charAt(i) == '\r'))
					{
						insideComment = null; //End inline comment
						Main.debug("Exited comment");
					} else if (insideComment == '/*' && text.charAt(i) == '*' && i + 1 < text.length && text.charAt(i + 1) == '/')
					{
						insideComment = null; //End multiline comment
						Main.debug("Exited comment");
					}
				} else if (insideString)
				{
					//Inside of a string, wait until we get out
					if (!escapingChar && text.charAt(i) == "\\")
					{
						escapingChar = true; //Start escape sequence
					} else if (!escapingChar && text.charAt(i) == insideString)
					{
						insideString = null; //Found closing quote
					} else
					{
						escapingChar = false; //Forget escape sequence
					}
				} else if (text.charAt(i) == opening)
				{
					started = true;
					count++; //Found opening
				} else if (text.charAt(i) == closing)
				{
					count--; //Found closing
				} else if ((text.charAt(i) == '\"' || text.charAt(i) == '\''))
				{
					insideString = text.charAt(i); //Now inside of a string
				} else if (text.charAt(i) == '/' && i + 1 < text.length && text.charAt(i + 1) == '/')
				{
					Main.debug("Entering comment... " + "(//)");
					insideComment = '//';
				} else if (text.charAt(i) == '/' && i + 1 < text.length && text.charAt(i + 1) == '*')
				{
					Main.debug("Entering comment..." + "(/*)");
					insideComment = '/*';
				}
				if (started)
				{
					buffer += text.charAt(i);
				}
				i++;
			}
			if (!started)
			{
				throw new Error("Error, no starting '" + opening  + "' found for method body while parsing " + AS3Parser.PREVIOUS_BLOCK);
			} else if (count > 0)
			{
				throw new Error("Error, no closing '" + closing  + "' found for method body while parsing " + AS3Parser.PREVIOUS_BLOCK);
			} else if (count < 0)
			{
				throw new Error("Error, malformed enclosing '" + opening + closing + " body while parsing " + AS3Parser.PREVIOUS_BLOCK);
			}
			return [buffer, i];
		}
		public static function extractUpTo(text:String, start:int, target:String):Array
		{
			var buffer:String = "";
			var i:int = start;
			var insideString:String = null;
			var insideComment:String = null;
			var escapingChar:Boolean = false;
			var pattern:String = new RegExp(target);
			while (i < text.length)
			{
				if (insideComment)
				{
					//Inside of a comment, wait until we get out
					if (insideComment == '//' && (text.charAt(i) == '\n' || text.charAt(i) == '\r'))
					{
						insideComment = null; //End inline comment
						Main.debug("Exited comment");
					} else if (insideComment == '/*' && text.charAt(i) == '*' && i + 1 < text.length && text.charAt(i + 1) == '/')
					{
						insideComment = null; //End multiline comment
						Main.debug("Exited comment");
					}
				} else if (insideString)
				{
					//Inside of a string, wait until we get out
					if (!escapingChar && text.charAt(i) == "\\")
					{
						escapingChar = true; //Start escape sequence
					} else if (!escapingChar && text.charAt(i) == insideString)
					{
						insideString = null; //Found closing quote
					} else
					{
						escapingChar = false; //Forget escape sequence
					}
				} else if ((text.charAt(i) == '\"' || text.charAt(i) == '\''))
				{
					insideString = text.charAt(i); //Now inside of a string
				} else if (text.charAt(i) == '/' && i + 1 < text.length && text.charAt(i + 1) == '/')
				{
					Main.debug("Entering comment... " + "(//)");
					insideComment = '//';
				} else if (text.charAt(i) == '/' && i + 1 < text.length && text.charAt(i + 1) == '*')
				{
					Main.debug("Entering comment..." + "(/*)");
					insideComment = '/*';
				} else if (text.charAt(i).match(pattern))
				{
					break; //Done
				}
				buffer += text.charAt(i);
				i++;
			}
			return [buffer, i];
		}
		
		public static function fixClassPath(clsPath:String):String
		{
			// Class paths at the root level might accidentally be prepended with a "."
			return clsPath.replace(/^\./g, "");
		}
		public function getState():String
		{
			return (this.stack.length > 0) ? this.stack[this.stack.length - 1] : null;
		}
		private function parseHelper(cls:AS3Class, src:String):void
		{
			var i:*;
			var j:*;
			var c:String;
			var currToken:AS3Token = null;
			var tmpToken:AS3Token = null;
			var tmpStr:String = null;
			var tmpArr:Array = null;
			var currMember:AS3Member = null;
			var index:int;
			for (index = 0; index < src.length; index++)
			{
				c = src.charAt(index);
				if (getState() == AS3ParseState.START)
				{
					//String together letters only until we reach a non-letter
					currToken = AS3Parser.nextWord(src, index, AS3Pattern.IDENTIFIER[0], AS3Pattern.IDENTIFIER[1]);
					index = currToken.index - 1; //Update to the new position
					if (currToken.token == 'package')
					{
						stack.push(AS3ParseState.PACKAGE_NAME);
					}
				} else if (getState() == AS3ParseState.PACKAGE_NAME)
				{
					currToken = AS3Parser.nextWord(src, index, AS3Pattern.OBJECT[0], AS3Pattern.OBJECT[1]); //Package name
					tmpToken = AS3Parser.nextWord(src, index, AS3Pattern.CURLY_BRACE[0], AS3Pattern.CURLY_BRACE[1]); //Upcoming curly brace
					
					
					index = currToken.index - 1;
					if (!currToken.token || !tmpToken.token)
					{
						throw new Error("Error parsing package name.");
					} else
					{
						if (tmpToken.index < currToken.index)
						{
							cls.packageName = ''; //Curly brace came before next token
							index = tmpToken.index;
						} else
						{
							cls.packageName = currToken.token; //Just grab the package name
						}
						Main.debug('Found package: ' + cls.packageName);
						cls.importWildcards.push(AS3Parser.fixClassPath(cls.packageName + '.*')); //Add wild card for its own folder
						stack.push(AS3ParseState.PACKAGE);
						Main.debug('Attempting to parse package...');
					}
				} else if (getState() == AS3ParseState.PACKAGE)
				{
					currToken = AS3Parser.nextWord(src, index, AS3Pattern.IDENTIFIER[0], AS3Pattern.IDENTIFIER[1]);
					index = currToken.index - 1;
					if (currToken.token == 'class' || currToken.token == 'interface')
					{
						if(currToken.token == 'interface')
							cls.isInterface = true;
						stack.push(AS3ParseState.CLASS_NAME);
						Main.debug('Found class keyword...');
					} else if (currToken.token == 'import')
					{
						stack.push(AS3ParseState.IMPORT_PACKAGE);
						Main.debug('Found import keyword...');
					} else if (currToken.token == 'require')
					{
						stack.push(AS3ParseState.REQUIRE_MODULE);
						Main.debug('Found require keyword...');
					}
				} else if (getState() == AS3ParseState.CLASS_NAME)
				{
					currToken = AS3Parser.nextWord(src, index, AS3Pattern.IDENTIFIER[0], AS3Pattern.IDENTIFIER[1]);
					tmpToken = AS3Parser.nextWord(src, index, AS3Pattern.CURLY_BRACE[0], AS3Pattern.CURLY_BRACE[1]);
					index = currToken.index;
					if (!currToken.token || !tmpToken.token)
					{
						throw new Error("Error parsing class name.");
					} else if (tmpToken.index < currToken.index)
					{
						throw new Error("Error, no class name found before curly brace.");
					} else
					{
						//Set the class name
						cls.className = currToken.token;
						
						// Update fully qualified class path if needed
						classPath = classPath || AS3Parser.fixClassPath(cls.packageName + '.' + cls.className); //Remove extra "." for top level packages
						
						cls.classMap[cls.className] = cls; //Register self into the import map (used for static detection)
						//Now we will check for parent class and any interfaces
						currToken = AS3Parser.nextWord(src, index, AS3Pattern.IDENTIFIER[0], AS3Pattern.IDENTIFIER[1]);
						if (currToken.token == 'extends' && currToken.index < tmpToken.index)
						{
							index = currToken.index;
							currToken = AS3Parser.nextWord(src, index, AS3Pattern.IDENTIFIER[0], AS3Pattern.IDENTIFIER[1]);
							index = currToken.index;
							//The token following 'extends' must be the parent class
							cls.parent = currToken.token;
							//Prep the next token
							currToken = AS3Parser.nextWord(src, index, AS3Pattern.IDENTIFIER[0], AS3Pattern.IDENTIFIER[1]);
							Main.debug("Found parent: " + cls.parent);
						}
						if (currToken.token == 'implements' && currToken.index < tmpToken.index)
						{
							index = currToken.index;
							currToken = AS3Parser.nextWord(src, index, AS3Pattern.IDENTIFIER[0], AS3Pattern.IDENTIFIER[1]);
							index = currToken.index;
							//The token following 'implements' must be an interface
							cls.interfaces.push(currToken.token);
							Main.debug("Found interface: " + currToken.token);
							currToken = AS3Parser.nextWord(src, index, AS3Pattern.IDENTIFIER[0], AS3Pattern.IDENTIFIER[1]);
							//While we are at a token before the next curly brace
							while (currToken.index < tmpToken.index && currToken.index < src.length)
							{
								//Consider self token another interface being implemented
								index = currToken.index;
								Main.debug("Found interface: " + currToken.token);
								cls.interfaces.push(currToken.token);
								currToken = AS3Parser.nextWord(src, index, AS3Pattern.IDENTIFIER[0], AS3Pattern.IDENTIFIER[1]);
								index = currToken.index;
							}
						}
						Main.debug('Parsed class name: ' + cls.className);
						//Now parsing inside of the class
						stack.push(AS3ParseState.CLASS);
						Main.debug('Attempting to parse class...');
						
						//Extract out the next method block
						AS3Parser.PREVIOUS_BLOCK = cls.className + ":Class";
						tmpStr = AS3Parser.extractBlock(src, index)[0];
						index += tmpStr.length - 1;
						
						//Recursively call parseHelper again under this new state (Once returned, package will be exited)
						parseHelper(cls, tmpStr);
					}
				} else if (getState() == AS3ParseState.CLASS)
				{
					currMember = currMember || new AS3Member(); //Declare a new member to work with if it doesn't exist yet
					currToken = AS3Parser.nextWord(src, index, AS3Pattern.IDENTIFIER[0], AS3Pattern.IDENTIFIER[1]);
					index = currToken.index - 1;
					if (currToken.token == AS3Encapsulation.PUBLIC || currToken.token == AS3Encapsulation.PRIVATE || currToken.token == AS3Encapsulation.PROTECTED)
					{
						currMember.encapsulation = currToken.token;
						Main.debug('->Member encapsulation set to ' + currMember.encapsulation);
					} else if (currToken.token == 'static')
					{
						currMember.isStatic = true;
						Main.debug('-->Static flag set');
					} else if (currToken.token == AS3MemberType.VAR || currToken.token == AS3MemberType.CONST)
					{
						Main.debug('--->Member type "variable" set.');
						currMember = currMember.createVariable(); //Transform the member into a variable
						stack.push(AS3ParseState.MEMBER_VARIABLE);
					} else if (currToken.token == AS3MemberType.FUNCTION)
					{
						currToken = AS3Parser.nextWord(src, index + 1, AS3Pattern.IDENTIFIER[0], AS3Pattern.IDENTIFIER[1]);
						//Check for getter/setter
						if ((currToken.token == 'get' || currToken.token == 'set') && src[index + 1 + currToken.token.length + 1] != '(')
						{
							Main.debug('--->Member sub-type "' + currToken.token + '" set.');
							currMember.subType = currToken.token;
							index = currToken.index - 1;
						}
						currMember = currMember.createFunction(); //Transform the member into a function
						stack.push(AS3ParseState.MEMBER_FUNCTION);
						Main.debug('---->Member type "function" set.');
					}
				} else if (getState() == AS3ParseState.MEMBER_VARIABLE)
				{
					currToken = AS3Parser.nextWord(src, index, AS3Pattern.IDENTIFIER[0], AS3Pattern.IDENTIFIER[1]);
					currMember.name = currToken.token; //Set the member name
					Main.debug('---->Variable name declared: ' + currToken.token);
					index = currToken.index;
					if (src.charAt(index) == ":")
					{
						currToken = AS3Parser.nextWord(src, index, AS3Pattern.VARIABLE_TYPE[0], AS3Pattern.VARIABLE_TYPE[1]);
						index = currToken.index;
						currMember.type = currToken.token;//Set the value type name
						Main.debug('---->Variable type for ' + currMember.name + ' declared as: ' + currToken.token);
					}
					currToken = AS3Parser.nextWord(src, index, AS3Pattern.ASSIGN_START[0], AS3Pattern.ASSIGN_START[1]);
					if (currToken.token == "=")
					{
						//Use all characters after self symbol to set value
						index = currToken.index;
						tmpArr = AS3Parser.extractUpTo(src, index, /[;\r\n]/g);
						//Store value
						currMember.value = tmpArr[0].trim();
						index =  tmpArr[1];
						
						cls.membersWithAssignments.push(currMember);
					}

					//Store and delete current member and exit
					if (currMember.isStatic)
					{
						cls.staticMembers.push(currMember);
					} else
					{
						cls.members.push(currMember);
					}
					cls.registerField(currMember.name, currMember);
					currMember = null;
					stack.pop();
				} else if (getState() == AS3ParseState.MEMBER_FUNCTION)
				{
					//Parse the arguments
					currToken = AS3Parser.nextWord(src, index, AS3Pattern.IDENTIFIER[0], AS3Pattern.IDENTIFIER[1]);
					index = currToken.index;
					currMember.name = currToken.token; //Set the member name
					Main.debug('****>Function name declared: ' + currToken.token);
					
					AS3Parser.PREVIOUS_BLOCK = currMember.name + ":Function";
					tmpArr = AS3Parser.extractBlock(src, index, '(', ')');
					index = tmpArr[1] - 1; //Ending index of parsed block
					tmpStr = tmpArr[0].trim(); //Parsed block
					tmpStr = tmpStr.substr(1, tmpStr.length - 2); //Remove outer parentheses
					tmpArr = null; //Trash this
					tmpArr = tmpStr.split(','); //Split args by commas
					//Don't bother if there are no arguments
					if (tmpArr.length > 0 && tmpArr[0] != '')
					{
						//Truncate spaces and assign values to arguments as needed
						for (i = 0; i < tmpArr.length; i++)
						{
							tmpStr = tmpArr[i];
							//Grab the function name
							tmpToken = AS3Parser.nextWord(tmpStr, 0, AS3Pattern.VARIABLE[0], AS3Pattern.VARIABLE[1]); //Parse out the function name
							currMember.argList.push(new AS3Argument());
							if (tmpStr.indexOf('...') === 0)
							{
								//This is a ...rest argument, stop here
								currMember.argList[currMember.argList.length-1].name = tmpStr.substr(3);
								currMember.argList[currMember.argList.length-1].isRestParam = true;
								Main.debug('----->Parsed a ...rest param: ' + currMember.argList[currMember.argList.length-1].name);
								break;
							} else
							{
								currMember.argList[currMember.argList.length-1].name = tmpToken.token; //Set the argument name
								Main.debug('----->Function argument found: ' + tmpToken.token);
								//If a colon was next, we'll assume it was typed and grab it
								if (tmpToken.index < tmpStr.length && tmpStr.charAt(tmpToken.index) == ':')
								{
									tmpToken = AS3Parser.nextWord(tmpStr, tmpToken.index, AS3Pattern.VARIABLE_TYPE[0], AS3Pattern.VARIABLE_TYPE[1]); //Parse out the argument type
									currMember.argList[currMember.argList.length-1].type = tmpToken.token; //Set the argument type
									Main.debug('----->Function argument typed to: ' + tmpToken.token);
								}
								tmpToken = AS3Parser.nextWord(tmpStr, tmpToken.index, AS3Pattern.ASSIGN_START[0], AS3Pattern.ASSIGN_START[1]);
								if (tmpToken.token == "=")
								{
									//Use all characters after self symbol to set value
									tmpToken = AS3Parser.nextWord(tmpStr, tmpToken.index, AS3Pattern.ASSIGN_UPTO[0], AS3Pattern.ASSIGN_UPTO[1]);
									if (!tmpToken)
									{
										throw new Error("Error during variable assignment in arg" + currMember.argList[currMember.argList.length - 1].name);
									}
									//Store value
									currMember.argList[currMember.argList.length-1].value = tmpToken.token.trim();
									Main.debug('----->Function argument defaulted to: ' + tmpToken.token.trim());
								}
							}
						}
					}
					Main.debug('------>Completed paring args: ', currMember.argList);
					//Type the function if needed
					if (src.charAt(index + 1) == ":")
					{
						tmpToken = AS3Parser.nextWord(src, index + 1, AS3Pattern.VARIABLE_TYPE[0], AS3Pattern.VARIABLE_TYPE[1]); //Parse out the function type if needed
						index = tmpToken.index;
						currMember.type = tmpToken.token;
						Main.debug('------>Typed the function to: ', currMember.type);
					}

					
					if (cls.isInterface)
					{
						//Store and delete current member and exit
						currMember.value = '{}';
						if (currMember.subType == 'get')
						{
							(currMember.isStatic) ? cls.staticGetters.push(currMember) : cls.getters.push(currMember);
						} else if (currMember.subType == 'set')
						{
							(currMember.isStatic) ? cls.staticSetters.push(currMember) : cls.setters.push(currMember);
						} else if (currMember.isStatic)
						{
							cls.staticMembers.push(currMember);
						} else
						{
							cls.members.push(currMember);
						}
						cls.registerField(currMember.name, currMember);
						//Done parsing function
						currMember = null;
						stack.pop();
					} else
					{
						//Save the function body
						AS3Parser.PREVIOUS_BLOCK = currMember.name + ":Function";
						tmpArr = AS3Parser.extractBlock(src, index);
						index = tmpArr[1];
						currMember.value = tmpArr[0].trim();

						//Store and delete current member and exit
						if (currMember.subType == 'get')
						{
							(currMember.isStatic) ? cls.staticGetters.push(currMember) : cls.getters.push(currMember);
						} else if (currMember.subType == 'set')
						{
							(currMember.isStatic) ? cls.staticSetters.push(currMember) : cls.setters.push(currMember);
						} else if (currMember.isStatic)
						{
							cls.staticMembers.push(currMember);
						} else
						{
							cls.members.push(currMember);
						}
						cls.registerField(currMember.name, currMember);

						currMember = null;
						stack.pop();
					}
				} else if (getState() == AS3ParseState.LOCAL_VARIABLE)
				{

				} else if (getState() == AS3ParseState.LOCAL_FUNCTION)
				{

				} else if (getState() == AS3ParseState.IMPORT_PACKAGE)
				{
					//The current token is a class import
					currToken = AS3Parser.nextWord(src, index, AS3Pattern.IMPORT[0], AS3Pattern.IMPORT[1]);
					index = currToken.index - 1;
					if (!currToken.token)
					{
						throw new Error("Error parsing import.");
					} else
					{
						Main.debug("Parsed import name: " + currToken.token);
						if (currToken.token.indexOf("*") >= 0)
						{
							cls.importWildcards.push(currToken.token); //To be resolved later
						}
						else
						{
							cls.imports.push(currToken.token); //No need to resolve
						}
						stack.push(AS3ParseState.PACKAGE);
					}
				} else if (getState() == AS3ParseState.REQUIRE_MODULE)
				{
					//The current token is a module requirement
					currToken = AS3Parser.nextWord(src, index, AS3Pattern.REQUIRE[0], AS3Pattern.REQUIRE[1]);
					index = currToken.index - 1;
					if(!currToken.token)
						throw new Error("Error parsing require.");
					else {
						Main.debug("Parsed require name: " + currToken.token);
						cls.requires.push(currToken.token.trim());
						stack.push(AS3ParseState.PACKAGE);
					}
				}
			}
		}
		public function parse(options:Object = null):AS3Class
		{
			options = options || { };
			if (typeof options.safeRequire !== 'undefined')
			{
				parserOptions.safeRequire = options.safeRequire;
			}
			if (typeof options.ignoreFlash !== 'undefined')
			{
				parserOptions.ignoreFlash = options.ignoreFlash;
			}
			
			var classDefinition:AS3Class = new AS3Class(parserOptions);
			stack.splice(0, stack.length);
			stack.push(AS3ParseState.START);
			
			parseHelper(classDefinition, src);
			
			if (!classDefinition.className)
			{
				throw new Error("Error, no class provided for package: " + classPath);
			}
			return classDefinition;
		}
		
		public static function checkArguments(fn:AS3Function):String
		{
			if (fn.argList.length <= 0)
			{
				return fn.value;
			}
			var start:int = fn.value.indexOf('{');
			var args:String = "";
			for (var i:int = 0; i < fn.argList.length; i++)
			{
				//We will inject arguments into the top of the method definition
				if (fn.argList[i].isRestParam)
				{
					args += "\n\t\t\tvar " + fn.argList[i].name + " = Array.prototype.slice.call(arguments).splice(" + i + ");";
				} else if (fn.argList[i].value)
				{
					args += "\n\t\t\t" + fn.argList[i].name + " = AS3JS.Utils.getDefaultValue(" + fn.argList[i].name + ", " + fn.argList[i].value + ");";
				}
			}
			return fn.value.substr(0, start + 1) + args + fn.value.substr(start + 1);
		}
		public static function injectInstantiations(cls:AS3Class, fn:AS3Function):String
		{
			var start:int = fn.value.indexOf('{');
			var text:String = "";
			for (var i = 0; i < cls.members.length; i++)
			{
				//We will inject instantiated vars into the top of the method definition
				if (cls.members[i] instanceof AS3Variable && AS3Class.nativeTypes.indexOf(cls.members[i].type) < 0)
				{
					text += "\n\t\t\tthis." + cls.members[i].name + " = " + cls.members[i].value + ";";
				}
			}
			return fn.value.substr(0, start + 1) + text + fn.value.substr(start + 1);
		}
		public static function injectInit(cls:AS3Class, fn:AS3Function):String
		{
			var start:int = fn.value.indexOf('{');
			var text:String = "\n\t\t\tthis.$init();";
			
			return fn.value.substr(0, start + 1) + text + fn.value.substr(start + 1);
		}
		public static function checkStack(stack:Array, name:String):void
		{
			if (!name)
			{
				return null;
			}
			for (var i = stack.length - 1; i >= 0; i--)
			{
				if (stack[i].name == name)
				{
					return stack[i];
				}
			}
			return null;
		}
		public static function lookAhead(str:String, index:int):Object
		{
			//Look ahead in the function for assignments
			var originalIndex:int = index;
			var startIndex:int = -1;
			var endIndex:int = -1;
			var semicolonIndex:int = -1;
			var token:String = "";
			var extracted:String = "";
			//Not a setter if there is a dot operator immediately after
			if (str.charAt(index) == '.')
			{
				return { token: null, extracted: '', startIndex: startIndex, endIndex: endIndex };
			}
			for (; index < str.length; index++)
			{
				if(str.charAt(index).match(/[+-\/=*]/g))
				{
					//Append to the assignment instruction
					token += str.charAt(index);
					startIndex = index;
				} else if (startIndex < 0 && str.charAt(index).match(/[\t\s]/g)) //Skip these characters
				{
					continue;
				} else
				{
					break; //Exits when token has already been started and no more regexes pass
				}
			}
			
			//Only allow these patterns
			if (!(token == "=" || token == "++" || token == "--" || token == "+=" || token == "-=" || token == "*=" || token == "/="))
			{
				token = null;
			}
				
			if (token)
			{
				//Pick whatever is closer, new line or semicolon
				endIndex = str.indexOf('\n', startIndex);
				if (endIndex < 0)
				{
					endIndex = str.length - 1;
				}
				//Windows fix
				if (str.charAt(endIndex - 1) == '\r')
				{
					endIndex--;
				}
				//We want to place closing parens before semicolon if it exists
				semicolonIndex = str.indexOf(";", startIndex);
				if (semicolonIndex < endIndex)
				{
					endIndex = semicolonIndex;
				}
				extracted = str.substring(startIndex + token.length, endIndex);
			}
			
			return { token: token, extracted: extracted, startIndex: startIndex, endIndex: endIndex };
		}
		public static function parseFunc(cls:AS3Class, fnText:String, stack:Array, statFlag:Boolean = false):Array
		{
			var i:int;
			var j:int;
			var index:int = 0;
			var result:String = '';
			var tmpStr:String = '';
			var tmpArgs:Vector.<AS3Argument>;
			var tmpMember:AS3Member;
			var tmpClass:AS3Class;
			var tmpField:AS3Member;
			var prevToken:AS3Token;
			var currToken:AS3Token;
			var tmpParse:String;
			var tmpStatic:Boolean = false;
			var tmpPeek:String;
			var objBuffer = ''; //Tracks the current object that is being "pathed" (e.g. "object.field1" or "object.field1[index + 1]", etc)
			var justCreatedVar:Boolean = false; //Keeps track if we just started a var statement (to help test if we're setting a type))
			for (index = 0; index < fnText.length; index++)
			{
				objBuffer = '';
				prevToken = currToken;
				currToken = AS3Parser.nextWord(fnText, index, AS3Pattern.VARIABLE[0], AS3Pattern.VARIABLE[1]);
				result += currToken.extra; //<-Puts all other non-identifier characters into the buffer firs
Download .txt
gitextract_llgholf1/

├── .gitattributes
├── .gitignore
├── AS3JS.as3proj
├── AS3JS.lxml
├── LICENSE
├── Readme.md
├── bin/
│   └── as3jsc.js
├── build.js
├── index.js
├── lib/
│   └── as3.js
├── package.json
├── runtime.js
├── snippets/
│   ├── class-snippet.js
│   └── main-snippet.js
└── src/
    └── com/
        └── mcleodgaming/
            └── as3js/
                ├── Main.as
                ├── enums/
                │   ├── AS3Encapsulation.as
                │   ├── AS3MemberType.as
                │   ├── AS3ParseState.as
                │   └── AS3Pattern.as
                ├── parser/
                │   ├── AS3Class.as
                │   ├── AS3Parser.as
                │   └── AS3Token.as
                └── types/
                    ├── AS3Argument.as
                    ├── AS3Function.as
                    ├── AS3Member.as
                    └── AS3Variable.as
Download .txt
SYMBOL INDEX (1 symbols across 1 files)

FILE: lib/as3.js
  function F (line 52) | function F() {}
Condensed preview — 26 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (235K chars).
[
  {
    "path": ".gitattributes",
    "chars": 480,
    "preview": "# Set the default behavior, in case people don't have core.autocrlf set.\n* text=auto\n\n# Explicitly declare text files yo"
  },
  {
    "path": ".gitignore",
    "chars": 34,
    "preview": "node_modules/\nruntime-compiled.js\n"
  },
  {
    "path": "AS3JS.as3proj",
    "chars": 3056,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<project version=\"2\">\n  <!-- Output SWF options -->\n  <output>\n    <movie output"
  },
  {
    "path": "AS3JS.lxml",
    "chars": 497,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<SWCProject xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http"
  },
  {
    "path": "LICENSE",
    "chars": 1100,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2015 Greg McLeod <cleod9{at}gmail.com>\n\nPermission is hereby granted, free of charg"
  },
  {
    "path": "Readme.md",
    "chars": 15801,
    "preview": "# AS3JS (deprecated) #\n\n----------\n\n### NOTICE: Due to lack of interest this project is no longer maintained. ###\n\nI app"
  },
  {
    "path": "bin/as3jsc.js",
    "chars": 3136,
    "preview": "#!/usr/bin/env node\n\n/**\n* This is the global AS3JS compiler for running 'as3js' as a CLI\n**/\n\nvar pjson = require('../p"
  },
  {
    "path": "build.js",
    "chars": 736,
    "preview": "var fs = require('fs');\nvar beautify = require('js-beautify').js_beautify;\n// Pull in loader library first\nglobal.AS3JS "
  },
  {
    "path": "index.js",
    "chars": 82,
    "preview": "global.AS3JS = require('./lib/as3.js');\n\nmodule.exports = require('./runtime.js');"
  },
  {
    "path": "lib/as3.js",
    "chars": 4985,
    "preview": "/*******************************\n  AS3JS Version 0.3.3\n  \n    AS3 to JS converter for use with ImportJS and OOPS.js.\n  \n"
  },
  {
    "path": "package.json",
    "chars": 416,
    "preview": "{\n\t\"name\": \"as3js\",\n\t\"version\": \"0.3.3\",\n\t\"author\": \"Greg McLeod <cleod9@gmail.com>\",\n\t\"description\": \"AS3 to JS convert"
  },
  {
    "path": "runtime.js",
    "chars": 98539,
    "preview": "(function() {\n  var Program = {};\n  Program[\"com.mcleodgaming.as3js.enums.AS3Encapsulation\"] = function(module, exports)"
  },
  {
    "path": "snippets/class-snippet.js",
    "chars": 69,
    "preview": "Program[\"{{module}}\"] = function ( module, exports ) {\n{{source}}\n};\n"
  },
  {
    "path": "snippets/main-snippet.js",
    "chars": 402,
    "preview": "(function ( ) {\n  var Program = {};\n{{packages}}\n\n  if (typeof module !== 'undefined') {\n    module.exports = AS3JS.load"
  },
  {
    "path": "src/com/mcleodgaming/as3js/Main.as",
    "chars": 9090,
    "preview": "package com.mcleodgaming.as3js\n{\n\timport com.mcleodgaming.as3js.parser.AS3Class;\n\timport com.mcleodgaming.as3js.parser.A"
  },
  {
    "path": "src/com/mcleodgaming/as3js/enums/AS3Encapsulation.as",
    "chars": 230,
    "preview": "package com.mcleodgaming.as3js.enums\n{\n\tpublic class AS3Encapsulation \n\t{\n\t\tpublic static const PUBLIC:String = \"public\""
  },
  {
    "path": "src/com/mcleodgaming/as3js/enums/AS3MemberType.as",
    "chars": 215,
    "preview": "package com.mcleodgaming.as3js.enums\n{\n\tpublic class AS3MemberType \n\t{\n\t\tpublic static const VAR:String = \"var\";\n\t\tpubli"
  },
  {
    "path": "src/com/mcleodgaming/as3js/enums/AS3ParseState.as",
    "chars": 1176,
    "preview": "package com.mcleodgaming.as3js.enums\n{\n\tpublic class AS3ParseState \n\t{\n\t\tpublic static const START:String = \"start\";\n\t\tp"
  },
  {
    "path": "src/com/mcleodgaming/as3js/enums/AS3Pattern.as",
    "chars": 1384,
    "preview": "package com.mcleodgaming.as3js.enums\n{\n\tpublic class AS3Pattern \n\t{\n\t\tpublic static const IDENTIFIER:Array = [ /\\w/g, /\\"
  },
  {
    "path": "src/com/mcleodgaming/as3js/parser/AS3Class.as",
    "chars": 23939,
    "preview": "package com.mcleodgaming.as3js.parser\n{\n\timport com.mcleodgaming.as3js.Main;\n\timport com.mcleodgaming.as3js.enums.*;\n\tim"
  },
  {
    "path": "src/com/mcleodgaming/as3js/parser/AS3Parser.as",
    "chars": 46451,
    "preview": "package com.mcleodgaming.as3js.parser\n{\n\timport com.mcleodgaming.as3js.Main;\n\timport com.mcleodgaming.as3js.enums.*;\n\tim"
  },
  {
    "path": "src/com/mcleodgaming/as3js/parser/AS3Token.as",
    "chars": 298,
    "preview": "package com.mcleodgaming.as3js.parser \n{\n\tpublic class AS3Token \n\t{\n\t\tpublic var token:String;\n\t\tpublic var index:int;\n\t"
  },
  {
    "path": "src/com/mcleodgaming/as3js/types/AS3Argument.as",
    "chars": 183,
    "preview": "package com.mcleodgaming.as3js.types\n{\n\tpublic class AS3Argument extends AS3Variable\n\t{\n\t\tpublic var isRestParam:Boolean"
  },
  {
    "path": "src/com/mcleodgaming/as3js/types/AS3Function.as",
    "chars": 972,
    "preview": "package com.mcleodgaming.as3js.types\n{\n\tpublic class AS3Function extends AS3Member\n\t{\n\t\tpublic var argList:Array;\n\t\t\n\t\tp"
  },
  {
    "path": "src/com/mcleodgaming/as3js/types/AS3Member.as",
    "chars": 919,
    "preview": "package com.mcleodgaming.as3js.types\n{\n\tpublic class AS3Member \n\t{\n\t\tpublic var name:String;\n\t\tpublic var type:String;\n\t"
  },
  {
    "path": "src/com/mcleodgaming/as3js/types/AS3Variable.as",
    "chars": 178,
    "preview": "package com.mcleodgaming.as3js.types\n{\n\t/**\n\t * ...\n\t * @author Greg McLeod\n\t */\n\tpublic class AS3Variable extends AS3Me"
  }
]

About this extraction

This page contains the full source code of the Cleod9/as3js GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 26 files (209.3 KB), approximately 56.3k tokens, and a symbol index with 1 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!