it's the end of the world as we know it
authorRichard Fairhurst <richard@systemed.net>
Sat, 30 May 2009 11:02:06 +0000 (11:02 +0000)
committerRichard Fairhurst <richard@systemed.net>
Sat, 30 May 2009 11:02:06 +0000 (11:02 +0000)
150 files changed:
README.txt [new file with mode: 0644]
halcyon.mxml [new file with mode: 0755]
halcyon.tmproj [new file with mode: 0644]
net/systemeD/halcyon/AMFConnection.as [new file with mode: 0755]
net/systemeD/halcyon/Connection.as [new file with mode: 0755]
net/systemeD/halcyon/Globals.as [new file with mode: 0755]
net/systemeD/halcyon/Map.as [new file with mode: 0755]
net/systemeD/halcyon/Node.as [new file with mode: 0755]
net/systemeD/halcyon/POI.as [new file with mode: 0644]
net/systemeD/halcyon/Way.as [new file with mode: 0755]
net/systemeD/halcyon/fonts/DejaVuSans-Bold.ttf [new file with mode: 0644]
net/systemeD/halcyon/fonts/DejaVuSans-BoldOblique.ttf [new file with mode: 0644]
net/systemeD/halcyon/fonts/DejaVuSans-ExtraLight.ttf [new file with mode: 0644]
net/systemeD/halcyon/fonts/DejaVuSans-Oblique.ttf [new file with mode: 0644]
net/systemeD/halcyon/fonts/DejaVuSans.ttf [new file with mode: 0644]
net/systemeD/halcyon/fonts/DejaVuSansCondensed-Bold.ttf [new file with mode: 0644]
net/systemeD/halcyon/fonts/DejaVuSansCondensed-BoldOblique.ttf [new file with mode: 0644]
net/systemeD/halcyon/fonts/DejaVuSansCondensed-Oblique.ttf [new file with mode: 0644]
net/systemeD/halcyon/fonts/DejaVuSansCondensed.ttf [new file with mode: 0644]
net/systemeD/halcyon/fonts/DejaVuSansMono-Bold.ttf [new file with mode: 0644]
net/systemeD/halcyon/fonts/DejaVuSansMono-BoldOblique.ttf [new file with mode: 0644]
net/systemeD/halcyon/fonts/DejaVuSansMono-Oblique.ttf [new file with mode: 0644]
net/systemeD/halcyon/fonts/DejaVuSansMono.ttf [new file with mode: 0644]
net/systemeD/halcyon/fonts/DejaVuSerif-Bold.ttf [new file with mode: 0644]
net/systemeD/halcyon/fonts/DejaVuSerif-BoldItalic.ttf [new file with mode: 0644]
net/systemeD/halcyon/fonts/DejaVuSerif-Italic.ttf [new file with mode: 0644]
net/systemeD/halcyon/fonts/DejaVuSerif.ttf [new file with mode: 0644]
net/systemeD/halcyon/fonts/DejaVuSerifCondensed-Bold.ttf [new file with mode: 0644]
net/systemeD/halcyon/fonts/DejaVuSerifCondensed-BoldItalic.ttf [new file with mode: 0644]
net/systemeD/halcyon/fonts/DejaVuSerifCondensed-Italic.ttf [new file with mode: 0644]
net/systemeD/halcyon/fonts/DejaVuSerifCondensed.ttf [new file with mode: 0644]
net/systemeD/halcyon/styleparser/Condition.as [new file with mode: 0644]
net/systemeD/halcyon/styleparser/PointRule.as [new file with mode: 0644]
net/systemeD/halcyon/styleparser/PointStyle.as [new file with mode: 0644]
net/systemeD/halcyon/styleparser/Rule.as [new file with mode: 0644]
net/systemeD/halcyon/styleparser/RuleSet.as [new file with mode: 0644]
net/systemeD/halcyon/styleparser/ShapeRule.as [new file with mode: 0644]
net/systemeD/halcyon/styleparser/ShapeStyle.as [new file with mode: 0644]
net/systemeD/halcyon/styleparser/ShieldStyle.as [new file with mode: 0644]
net/systemeD/halcyon/styleparser/TextStyle.as [new file with mode: 0644]
org/as3yaml/BaseConstructor.as [new file with mode: 0755]
org/as3yaml/Composer.as [new file with mode: 0755]
org/as3yaml/ComposerException.as [new file with mode: 0755]
org/as3yaml/Constructor.as [new file with mode: 0755]
org/as3yaml/ConstructorException.as [new file with mode: 0755]
org/as3yaml/ConstructorImpl.as [new file with mode: 0755]
org/as3yaml/DefaultYAMLConfig.as [new file with mode: 0755]
org/as3yaml/DefaultYAMLFactory.as [new file with mode: 0755]
org/as3yaml/Emitter.as [new file with mode: 0755]
org/as3yaml/EmitterEnvironment.as [new file with mode: 0755]
org/as3yaml/EmitterException.as [new file with mode: 0755]
org/as3yaml/Parser.as [new file with mode: 0755]
org/as3yaml/ParserException.as [new file with mode: 0755]
org/as3yaml/PrivateType.as [new file with mode: 0755]
org/as3yaml/Representer.as [new file with mode: 0755]
org/as3yaml/RepresenterException.as [new file with mode: 0755]
org/as3yaml/Resolver.as [new file with mode: 0755]
org/as3yaml/ResolverException.as [new file with mode: 0755]
org/as3yaml/SafeConstructor.as [new file with mode: 0755]
org/as3yaml/ScalarAnalysis.as [new file with mode: 0755]
org/as3yaml/Scanner.as [new file with mode: 0755]
org/as3yaml/ScannerException.as [new file with mode: 0755]
org/as3yaml/Serializer.as [new file with mode: 0755]
org/as3yaml/SerializerException.as [new file with mode: 0755]
org/as3yaml/SimpleKey.as [new file with mode: 0755]
org/as3yaml/YAML.as [new file with mode: 0755]
org/as3yaml/YAMLConfig.as [new file with mode: 0755]
org/as3yaml/YAMLException.as [new file with mode: 0755]
org/as3yaml/YAMLFactory.as [new file with mode: 0755]
org/as3yaml/YAMLNodeCreator.as [new file with mode: 0755]
org/as3yaml/YamlConstructor.as [new file with mode: 0755]
org/as3yaml/YamlConstructorImpl.as [new file with mode: 0755]
org/as3yaml/YamlMultiAdapter.as [new file with mode: 0755]
org/as3yaml/YamlMultiConstructor.as [new file with mode: 0755]
org/as3yaml/YamlMultiConstructorImpl.as [new file with mode: 0755]
org/as3yaml/events/AliasEvent.as [new file with mode: 0755]
org/as3yaml/events/CollectionEndEvent.as [new file with mode: 0755]
org/as3yaml/events/CollectionStartEvent.as [new file with mode: 0755]
org/as3yaml/events/DocumentEndEvent.as [new file with mode: 0755]
org/as3yaml/events/DocumentStartEvent.as [new file with mode: 0755]
org/as3yaml/events/Event.as [new file with mode: 0755]
org/as3yaml/events/MappingEndEvent.as [new file with mode: 0755]
org/as3yaml/events/MappingStartEvent.as [new file with mode: 0755]
org/as3yaml/events/NodeEvent.as [new file with mode: 0755]
org/as3yaml/events/ScalarEvent.as [new file with mode: 0755]
org/as3yaml/events/SequenceEndEvent.as [new file with mode: 0755]
org/as3yaml/events/SequenceStartEvent.as [new file with mode: 0755]
org/as3yaml/events/StreamEndEvent.as [new file with mode: 0755]
org/as3yaml/events/StreamStartEvent.as [new file with mode: 0755]
org/as3yaml/nodes/CollectionNode.as [new file with mode: 0755]
org/as3yaml/nodes/MappingNode.as [new file with mode: 0755]
org/as3yaml/nodes/Node.as [new file with mode: 0755]
org/as3yaml/nodes/ScalarNode.as [new file with mode: 0755]
org/as3yaml/nodes/SequenceNode.as [new file with mode: 0755]
org/as3yaml/tokens/AliasToken.as [new file with mode: 0755]
org/as3yaml/tokens/AnchorToken.as [new file with mode: 0755]
org/as3yaml/tokens/BlockEndToken.as [new file with mode: 0755]
org/as3yaml/tokens/BlockEntryToken.as [new file with mode: 0755]
org/as3yaml/tokens/BlockMappingStartToken.as [new file with mode: 0755]
org/as3yaml/tokens/BlockSequenceStartToken.as [new file with mode: 0755]
org/as3yaml/tokens/DirectiveToken.as [new file with mode: 0755]
org/as3yaml/tokens/DocumentEndToken.as [new file with mode: 0755]
org/as3yaml/tokens/DocumentStartToken.as [new file with mode: 0755]
org/as3yaml/tokens/FlowEntryToken.as [new file with mode: 0755]
org/as3yaml/tokens/FlowMappingEndToken.as [new file with mode: 0755]
org/as3yaml/tokens/FlowMappingStartToken.as [new file with mode: 0755]
org/as3yaml/tokens/FlowSequenceEndToken.as [new file with mode: 0755]
org/as3yaml/tokens/FlowSequenceStartToken.as [new file with mode: 0755]
org/as3yaml/tokens/KeyToken.as [new file with mode: 0755]
org/as3yaml/tokens/ScalarToken.as [new file with mode: 0755]
org/as3yaml/tokens/StreamEndToken.as [new file with mode: 0755]
org/as3yaml/tokens/StreamStartToken.as [new file with mode: 0755]
org/as3yaml/tokens/TagToken.as [new file with mode: 0755]
org/as3yaml/tokens/Token.as [new file with mode: 0755]
org/as3yaml/tokens/Tokens.as [new file with mode: 0755]
org/as3yaml/tokens/ValueToken.as [new file with mode: 0755]
org/as3yaml/util/StringUtils.as [new file with mode: 0755]
org/idmedia/as3commons/lang/ConcurrentModificationException.as [new file with mode: 0755]
org/idmedia/as3commons/lang/Exception.as [new file with mode: 0755]
org/idmedia/as3commons/lang/IllegalArgumentException.as [new file with mode: 0755]
org/idmedia/as3commons/lang/IllegalStateException.as [new file with mode: 0755]
org/idmedia/as3commons/lang/IndexOutOfBoundsException.as [new file with mode: 0755]
org/idmedia/as3commons/lang/NoSuchElementException.as [new file with mode: 0755]
org/idmedia/as3commons/lang/NullPointerException.as [new file with mode: 0755]
org/idmedia/as3commons/lang/Throwable.as [new file with mode: 0755]
org/idmedia/as3commons/lang/UnsupportedOperationException.as [new file with mode: 0755]
org/idmedia/as3commons/util/AbstractCollection.as [new file with mode: 0755]
org/idmedia/as3commons/util/AbstractList.as [new file with mode: 0755]
org/idmedia/as3commons/util/AbstractMap.as [new file with mode: 0755]
org/idmedia/as3commons/util/AbstractSet.as [new file with mode: 0755]
org/idmedia/as3commons/util/ArrayList.as [new file with mode: 0755]
org/idmedia/as3commons/util/Arrays.as [new file with mode: 0755]
org/idmedia/as3commons/util/Collection.as [new file with mode: 0755]
org/idmedia/as3commons/util/Collections.as [new file with mode: 0755]
org/idmedia/as3commons/util/Comparator.as [new file with mode: 0755]
org/idmedia/as3commons/util/Entry.as [new file with mode: 0755]
org/idmedia/as3commons/util/EntrySet.as [new file with mode: 0755]
org/idmedia/as3commons/util/EntrySetIterator.as [new file with mode: 0755]
org/idmedia/as3commons/util/HashMap.as [new file with mode: 0755]
org/idmedia/as3commons/util/HashSet.as [new file with mode: 0755]
org/idmedia/as3commons/util/Iterator.as [new file with mode: 0755]
org/idmedia/as3commons/util/List.as [new file with mode: 0755]
org/idmedia/as3commons/util/ListIterator.as [new file with mode: 0755]
org/idmedia/as3commons/util/Map.as [new file with mode: 0755]
org/idmedia/as3commons/util/Observable.as [new file with mode: 0755]
org/idmedia/as3commons/util/Observer.as [new file with mode: 0755]
org/idmedia/as3commons/util/Set.as [new file with mode: 0755]
org/idmedia/as3commons/util/StringUtils.as [new file with mode: 0755]
org/rxr/actionscript/io/StringReader.as [new file with mode: 0755]
org/rxr/actionscript/io/StringWriter.as [new file with mode: 0755]

diff --git a/README.txt b/README.txt
new file mode 100644 (file)
index 0000000..7e94cd3
--- /dev/null
@@ -0,0 +1,32 @@
+== Halcyon - ActionScript 3 renderer for Potlatch 2.0 ==
+
+Here's some embryonic unfinished stuff to play with.
+
+This is a live OSM renderer written in AS3 which will one day grow into a beautiful map editor.
+
+=== What you'll need ===
+
+* OSM Rails port installed on your local machine
+* Flex SDK - http://www.adobe.com/products/flex/ (free, OS X/Windows/Linux)
+* AS3 docs - http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/
+* Flash debug player - http://www.adobe.com/support/flashplayer/downloads.html
+* Basically you might as well just sell your soul to Adobe
+
+=== How to compile and run ===
+
+Compiling:
+mxmlc -managers=flash.fonts.AFEFontManager -output=/path/to/halcyon.swf /path/to/halcyon.mxml
+
+Running:
+* Make sure test.yaml is in the same directory as halcyon.swf
+* Open halcyon.swf in your browser
+
+=== Some other stuff you might need to know ===
+
+* The as3yaml library has been patched a bit to actually make it work.
+* The stuff about -managers=flash.fonts.AFEFontManager is probably only required on OS X.
+* Flex compiler runs at about the speed of a tortoise soaked in molasses which happens also to be dead.
+
+
+Richard Fairhurst
+richard@systemeD.net
diff --git a/halcyon.mxml b/halcyon.mxml
new file mode 100755 (executable)
index 0000000..ab3f6d7
--- /dev/null
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<mx:Application 
+       xmlns:mx="http://www.adobe.com/2006/mxml" 
+       xmlns:halcyon="net.systemeD.halcyon.*"
+       layout="vertical"
+       horizontalAlign="center" 
+       addedToStage="initApp()">
+
+<!--    <halcyon:CountryComboBox /> -->
+
+<!--   <halcyon:Map width="400" height="200" id="theMap" /> -->
+<!-- applicationComplete -->
+<!-- rawChildren -->
+
+       <mx:Script><![CDATA[
+               import net.systemeD.halcyon.*;
+               import flash.system.Security;
+               import flash.net.*;
+               import flash.events.MouseEvent;
+               import flash.display.Sprite;
+               import mx.core.IChildList;
+
+               private function initApp():void {
+
+                       Globals.vars.root=rawChildren;                  // set up global reference to root level
+                       var _root:IChildList=rawChildren;               // convenient local shorthand
+
+                       // map backdrop object
+                       var b:Sprite=new Sprite();
+                       b.graphics.beginFill(0xFFFFEA,100);
+                       b.graphics.drawRect(0,0,200,200);
+                       b.graphics.endFill();
+                       _root.addChild(b);
+
+                       // add map
+                       var theMap:Map=new Map();
+                       theMap.backdrop=b;
+                       _root.addChild(theMap);
+
+                       // add mask for map
+                       var s:Sprite=new Sprite();
+                       s.graphics.beginFill(0xFFFFFF,100);
+                       s.graphics.drawRect(0,0,200,200);
+                       s.graphics.endFill();
+                       _root.addChild(s);
+
+                       theMap.mask=s;
+
+                       // mouse-up handler attached to stage, so the user can release outside the map
+                       stage.addEventListener(MouseEvent.MOUSE_UP, theMap.mouseUpHandler);
+                       theMap.backdrop.addEventListener(MouseEvent.MOUSE_MOVE, theMap.mouseMoveHandler);
+                       theMap.backdrop.addEventListener(MouseEvent.MOUSE_DOWN, theMap.mouseDownHandler);
+
+                       // keyboard event attached to stage
+                       stage.addEventListener(KeyboardEvent.KEY_UP, theMap.keyUpHandler);
+
+                       // add debug field
+                       var t:TextField=new TextField();
+                       t.width=400; t.height=100; t.border=true; 
+                       t.multiline=true;
+                       _root.addChild(t);
+                       Globals.vars.debug=t;
+               }
+
+       ]]></mx:Script>
+
+</mx:Application>
+
diff --git a/halcyon.tmproj b/halcyon.tmproj
new file mode 100644 (file)
index 0000000..a01c864
--- /dev/null
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>documents</key>
+       <array>
+               <dict>
+                       <key>filename</key>
+                       <string>net/systemeD/halcyon/AMFConnection.as</string>
+                       <key>lastUsed</key>
+                       <date>2009-05-30T10:52:22Z</date>
+               </dict>
+               <dict>
+                       <key>filename</key>
+                       <string>net/systemeD/halcyon/Connection.as</string>
+               </dict>
+               <dict>
+                       <key>filename</key>
+                       <string>net/systemeD/halcyon/Globals.as</string>
+               </dict>
+               <dict>
+                       <key>filename</key>
+                       <string>net/systemeD/halcyon/Map.as</string>
+                       <key>lastUsed</key>
+                       <date>2009-05-30T10:43:34Z</date>
+               </dict>
+               <dict>
+                       <key>filename</key>
+                       <string>net/systemeD/halcyon/Node.as</string>
+                       <key>lastUsed</key>
+                       <date>2009-05-30T08:37:45Z</date>
+               </dict>
+               <dict>
+                       <key>filename</key>
+                       <string>net/systemeD/halcyon/POI.as</string>
+               </dict>
+               <dict>
+                       <key>filename</key>
+                       <string>net/systemeD/halcyon/Way.as</string>
+                       <key>lastUsed</key>
+                       <date>2009-05-30T10:43:35Z</date>
+               </dict>
+               <dict>
+                       <key>expanded</key>
+                       <true/>
+                       <key>name</key>
+                       <string>styleparser</string>
+                       <key>regexFolderFilter</key>
+                       <string>!.*/(\.[^/]*|CVS|_darcs|_MTN|\{arch\}|blib|.*~\.nib|.*\.(framework|app|pbproj|pbxproj|xcode(proj)?|bundle))$</string>
+                       <key>sourceDirectory</key>
+                       <string>net/systemeD/halcyon/styleparser</string>
+               </dict>
+               <dict>
+                       <key>filename</key>
+                       <string>halcyon.mxml</string>
+                       <key>lastUsed</key>
+                       <date>2009-05-30T10:52:25Z</date>
+                       <key>selected</key>
+                       <true/>
+               </dict>
+       </array>
+       <key>fileHierarchyDrawerWidth</key>
+       <integer>200</integer>
+       <key>metaData</key>
+       <dict/>
+       <key>showFileHierarchyDrawer</key>
+       <true/>
+       <key>windowFrame</key>
+       <string>{{272, 182}, {710, 564}}</string>
+</dict>
+</plist>
diff --git a/net/systemeD/halcyon/AMFConnection.as b/net/systemeD/halcyon/AMFConnection.as
new file mode 100755 (executable)
index 0000000..19cca2e
--- /dev/null
@@ -0,0 +1,43 @@
+package net.systemeD.halcyon {
+
+       import flash.system.Security;
+       import flash.net.*;
+
+       public class AMFConnection extends Connection {
+
+               public var readConnection:NetConnection;
+               public var writeConnection:NetConnection;
+               
+               // ------------------------------------------------------------
+               // Constructor for new AMFConnection
+
+               public function AMFConnection(readURL:String,writeURL:String,policyURL:String='') {
+
+                       if (policyURL!='') { Security.loadPolicyFile(policyURL); }
+
+                       readConnection=new NetConnection();
+                       readConnection.objectEncoding = flash.net.ObjectEncoding.AMF0;
+                       readConnection.connect(readURL);
+                       
+                       writeConnection=new NetConnection();
+                       writeConnection.objectEncoding = flash.net.ObjectEncoding.AMF0;
+                       writeConnection.connect(writeURL);
+                       
+               }
+
+               public function getEnvironment(responder:Responder):void {
+                       readConnection.call("getpresets",responder,"en");
+               }
+               
+               public function getBbox(left:Number,right:Number,
+                                                               top:Number,bottom:Number,
+                                                               responder:Responder):void {
+                       readConnection.call("whichways",responder,left,bottom,right,top);
+               }
+
+               public function getWay(id:uint,responder:Responder):void {
+                       readConnection.call("getway",responder,id);
+               }
+
+       }
+}
diff --git a/net/systemeD/halcyon/Connection.as b/net/systemeD/halcyon/Connection.as
new file mode 100755 (executable)
index 0000000..f5dfd09
--- /dev/null
@@ -0,0 +1,4 @@
+package net.systemeD.halcyon {
+       public class Connection {
+       }
+}
diff --git a/net/systemeD/halcyon/Globals.as b/net/systemeD/halcyon/Globals.as
new file mode 100755 (executable)
index 0000000..5d69c77
--- /dev/null
@@ -0,0 +1,5 @@
+package net.systemeD.halcyon {
+       public class Globals {
+               public static var vars:Object=[];
+       }
+}
diff --git a/net/systemeD/halcyon/Map.as b/net/systemeD/halcyon/Map.as
new file mode 100755 (executable)
index 0000000..4ff86bd
--- /dev/null
@@ -0,0 +1,269 @@
+package net.systemeD.halcyon {
+
+       import flash.text.TextField;
+       import flash.display.DisplayObjectContainer;
+       import flash.display.Sprite;
+       import flash.display.Shape;
+       import flash.display.Stage;
+       import flash.events.*;
+       import net.systemeD.halcyon.styleparser.*;
+       import flash.net.*;
+       
+    public class Map extends Sprite {
+
+               public const MASTERSCALE:Number=5825.4222222222;// master map scale - how many Flash pixels in 1 degree longitude
+                                                                                                               // (for Landsat, 5120)
+               public const MINSCALE:uint=13;                                  // don't zoom out past this
+               public const MAXSCALE:uint=19;                                  // don't zoom in past this
+
+               public var ruleset:RuleSet=new RuleSet();               // rules
+               
+               public var ways:Object=new Object();                    // geodata
+               public var nodes:Object=new Object();                   //  |
+               public var pois:Object=new Object();                    //  |
+               public var relations:Object=new Object();               //  |
+
+               public var scale:uint=14;                                               // map scale
+               public var scalefactor:Number=MASTERSCALE;              // current scaling factor for lon/latp
+               public var bigedge_l:Number= 999999;                    // area of largest whichways
+               public var bigedge_r:Number=-999999;                    //  |
+               public var bigedge_b:Number= 999999;                    //  |
+               public var bigedge_t:Number=-999999;                    //  |
+               public var bscale:Number=Math.pow(2,scale-13);  // scale factor (2**(zoom-13))
+
+               public var waycount:uint=0;                                             // ways:                number currently loaded
+               public var waysrequested:uint=0;                                //                              total number requested
+               public var waysreceived:uint=0;                                 //                              total number received
+               public var relcount:uint=0;                                             // relations:   number currently loaded
+               public var relsrequested:uint=0;                                //                              total number requested
+               public var relsreceived:uint=0;                                 //                              total number received
+               public var poicount:uint=0;                                             // POIs:                number currently loaded
+               public var whichrequested:uint=0;                               // whichways:   total number requested
+               public var whichreceived:uint=0;                                //                              total number received
+
+               public var edge_l:Number;                                               // current bounding box
+               public var edge_r:Number;                                               //  |
+               public var edge_t:Number;                                               //  |
+               public var edge_b:Number;                                               //  |
+
+               public var baselon:Number;                                              // urllon-xradius/masterscale/bscale;
+               public var basey:Number;                                                // lat2lat2p(urllat)+yradius/masterscale/bscale;
+               public var mapwidth:uint;                                               // width (Flash pixels)
+               public var mapheight:uint;                                              // height (Flash pixels)
+
+               private var dragging:Boolean=false;                             // dragging map?
+               private var lastxmouse:Number;                                  //  |
+               private var lastymouse:Number;                                  //  |
+               
+               public var backdrop:Object;                                             // reference to backdrop sprite
+               
+               public var connection:AMFConnection;                    // server connection
+
+               // ------------------------------------------------------------------------------------------
+               // Map constructor function
+
+        public function Map() {
+
+                       for (var l:int=0; l<11; l++) {                          // 11 layers (10 is +5, 0 is -5)
+                               var s:Sprite=new Sprite();
+                               s.addChild(new Sprite());                               // [layer][0]=fill, [1]=stroke, [2]=names
+                               s.addChild(new Sprite());
+                               s.addChild(new Sprite());
+                               addChild(s);
+                       }
+
+                       connection=new AMFConnection(
+                               "http://127.0.0.1:3000/api/0.6/amf/read",
+                               "http://127.0.0.1:3000/api/0.6/amf/write",
+                               "http://127.0.0.1:3000/api/crossdomain.xml");
+                       connection.getEnvironment(new Responder(gotEnvironment,connectionError));
+
+        }
+
+               public function gotEnvironment(r:Object):void {
+                       init(52.022,-1.2745);
+               }
+
+               // ------------------------------------------------------------------------------------------
+               // Initialise map at a given lat/lon
+
+        public function init(startlat:Number,startlon:Number):void {
+
+                       ruleset.load("test.yaml?d="+Math.random());
+//                     rules.initExample();            // initialise dummy rules
+
+                       updateSize();
+                       baselon  =startlon                      -(mapwidth /2)/MASTERSCALE/bscale;
+                       basey    =lat2latp(startlat)+(mapheight/2)/MASTERSCALE/bscale;
+                       addDebug("Baselon "+baselon+", basey "+basey);
+                       updateCoords(0,0);
+                       addDebug("L "+edge_l+", R "+edge_r);
+                       download();
+                       
+        }
+
+               // ------------------------------------------------------------------------------------------
+               // Recalculate co-ordinates from new Flash origin
+
+               public function updateCoords(tx:Number,ty:Number):void {
+
+                       bscale=Math.pow(2,scale-13);
+                       x=tx; y=ty;
+//                     scaleX=bscale; scaleY=bscale;
+
+                       // ** calculate tile_l etc.
+                       edge_t=coord2lat((-y          )/bscale);
+                       edge_b=coord2lat((-y+mapheight)/bscale);
+                       edge_l=coord2lon((-x          )/bscale);
+                       edge_r=coord2lon((-x+mapwidth )/bscale);
+
+               }
+
+               // Co-ordinate conversion functions
+
+               public function latp2coord(a:Number):Number     { return -(a-basey)*scalefactor; }
+               public function coord2latp(a:Number):Number     { return a/-scalefactor+basey; }
+               public function lon2coord(a:Number):Number      { return (a-baselon)*scalefactor; }
+               public function coord2lon(a:Number):Number      { return a/scalefactor+baselon; }
+
+               public function latp2lat(a:Number):Number       { return 180/Math.PI * (2 * Math.atan(Math.exp(a*Math.PI/180)) - Math.PI/2); }
+               public function lat2latp(a:Number):Number       { return 180/Math.PI * Math.log(Math.tan(Math.PI/4+a*(Math.PI/180)/2)); }
+
+               public function lat2coord(a:Number):Number      { return -(lat2latp(a)-basey)*scalefactor; }
+               public function coord2lat(a:Number):Number      { return latp2lat(a/-scalefactor+basey); }
+
+//             public function centrelat(o) { return coord2lat((yradius-_root.map._y-o)/Math.pow(2,_root.scale-13)); }
+//             public function centrelon(o) { return coord2lon((xradius-_root.map._x-o)/Math.pow(2,_root.scale-13)); }
+
+
+               // ------------------------------------------------------------------------------------------
+               // Resize map size based on current stage and height
+
+               public function updateSize():void {
+                       mapwidth =stage.stageWidth; mask.width=mapwidth; backdrop.width=mapwidth;
+                       mapheight=stage.stageHeight; mask.height=mapheight; backdrop.height=mapheight;
+                       // addDebug("Mapwidth "+mapwidth+", mapheight "+mapheight);
+               }
+
+               // ------------------------------------------------------------------------------------------
+               // Download map data
+               // (typically from whichways, but will want to add more connections)
+
+               public function download():void {
+                       if (edge_l>=bigedge_l && edge_r<=bigedge_r &&
+                               edge_b>=bigedge_b && edge_t<=bigedge_t) { return; }     // we have already loaded this area, so ignore
+                       bigedge_l=edge_l; bigedge_r=edge_r;
+                       bigedge_b=edge_b; bigedge_t=edge_t;
+                       addDebug("Calling with "+edge_l+"-"+edge_r+", "+edge_t+"-"+edge_b);
+                       connection.getBbox(edge_l,edge_r,edge_t,edge_b,new Responder(gotBbox,connectionError));
+               }
+
+               public function gotBbox(r:Object):void {
+                       addDebug("got whichways");
+                       var code:uint         =r.shift(); if (code) { connectionError(); return; }
+                       var message:String    =r.shift();
+                       var waylist:Array     =r[0];
+                       var pointlist:Array   =r[1];
+                       var relationlist:Array=r[2];
+                       var i:uint, v:uint;
+
+                       for each (var w:Array in waylist) {
+                               i=w[0]; v=w[1];
+                               if (ways[i] && ways[i].version==v) { continue; }
+                               ways[i]=new Way(i,v,this);
+                               ways[i].load(connection);
+                       }
+
+                       for each (var p:Array in pointlist) {
+                               i=w[0]; v=w[4];
+                               if (pois[i] && pois[i].version==v) { continue; }
+                               pois[i]=new POI(i,v,w[1],w[2],w[3],this);
+                       }
+
+                       addDebug("waylist is "+waylist);
+               }
+
+
+               // ------------------------------------------------------------------------------------------
+               // Redraw all items, zoom in and out
+               
+               public function redraw():void {
+                       addDebug("redrawing");
+                       var s:String='';
+                       for each (var w:Way in ways) { w.redraw(); s+=w.id+","; }
+                       addDebug(s);
+                       // ** do POIs, etc.
+               }
+
+               public function zoomIn():void {
+                       if (scale==MAXSCALE) { return; }
+                       changeScale(scale+1);
+               }
+
+               public function zoomOut():void {
+                       if (scale==MINSCALE) { return; }
+                       changeScale(scale-1);
+               }
+
+               private function changeScale(newscale:uint):void {
+                       addDebug("new scale "+newscale);
+                       scale=newscale;
+                       scalefactor=MASTERSCALE/Math.pow(2,14-scale);
+                       redraw();
+               }
+               
+               private function reportPosition():void {
+                       addDebug("lon "+coord2lon(mouseX)+", lat "+coord2lat(mouseY));
+               }
+
+
+               // ==========================================================================================
+               // Events
+               
+               // ------------------------------------------------------------------------------------------
+               // Mouse events
+               
+               public function mouseDownHandler(event:MouseEvent):void {
+                       dragging=true;
+                       lastxmouse=mouseX; lastymouse=mouseY;
+               }
+        
+               public function mouseUpHandler(event:MouseEvent):void {
+                       if (!dragging) { return; }
+                       dragging=false;
+                       updateCoords(x,y);
+                       download();
+               }
+        
+               public function mouseMoveHandler(event:MouseEvent):void {
+                       if (!dragging) { return; }
+                       x+=mouseX-lastxmouse;
+                       y+=mouseY-lastymouse;
+                       lastxmouse=mouseX; lastymouse=mouseY;
+               }
+        
+               // ------------------------------------------------------------------------------------------
+               // Miscellaneous events
+               
+               public function keyUpHandler(event:KeyboardEvent):void {
+addDebug("pressed "+event.keyCode);
+                       if (event.keyCode==82) { this.redraw(); }                       // R - redraw
+                       if (event.keyCode==73) { this.zoomIn(); }                       // I - zoom in
+                       if (event.keyCode==79) { this.zoomOut(); }                      // O - zoom out
+                       if (event.keyCode==76) { this.reportPosition(); }       // L - report lat/long
+               }
+
+               public function connectionError(err:Object=null): void {
+                       addDebug("got error"); 
+               }
+
+               // ------------------------------------------------------------------------------------------
+               // Debugging
+               
+               public function addDebug(text:String):void {
+                       Globals.vars.debug.appendText(text+"\n");
+                       Globals.vars.debug.scrollV=Globals.vars.debug.maxScrollV;
+               }
+               
+       }
+}
diff --git a/net/systemeD/halcyon/Node.as b/net/systemeD/halcyon/Node.as
new file mode 100755 (executable)
index 0000000..5a6682a
--- /dev/null
@@ -0,0 +1,21 @@
+package net.systemeD.halcyon {
+       public class Node extends Object {
+               public var lon:Number;                  // raw longitude
+               public var latp:Number;                 // projected latitude
+               public var tags:Object;
+               public var tagged:Boolean;
+               public var id:int;
+               public var version:uint;
+               public var clean:Boolean;
+
+               public function Node(id:int,lon:Number,latp:Number,tags:Object,version:uint) {
+                       this.id=id;
+                       this.lon=lon;
+                       this.latp=latp;
+                       this.tags=tags;
+//                     this.tagged=hasTags();
+                       this.version=version;
+                       this.clean=false;               // set to true if just loaded from server
+               }
+       }
+}
diff --git a/net/systemeD/halcyon/POI.as b/net/systemeD/halcyon/POI.as
new file mode 100644 (file)
index 0000000..8907c86
--- /dev/null
@@ -0,0 +1,38 @@
+package net.systemeD.halcyon {
+
+       public class POI extends Object {
+
+               import flash.display.*;
+               import flash.text.TextField;
+               import flash.text.TextFormat;
+               import net.systemeD.halcyon.styleparser.*;
+
+               public var id:int;
+               public var tags:Object;
+               public var clean:Boolean=true;                          // altered since last upload?
+               public var uploading:Boolean=false;                     // currently uploading?
+               public var locked:Boolean=false;                        // locked against upload?
+               public var version:uint=0;                                      // version number?
+               public var map:Map;                                                     // reference to parent map
+               public var icon:Sprite;                                         // instance in display list
+               public var name:Sprite;                                         //  |
+
+               [Embed(source="fonts/DejaVuSans.ttf", fontFamily="DejaVu", fontWeight="normal", mimeType="application/x-font-truetype")]
+               public static var DejaVu:Class;
+               public var nameformat:TextFormat;
+
+               public function POI(id:int,version:int,lon:Number,lat:Number,tags:Object,map:Map) {
+                       this.id=id;
+                       this.version=version;
+                       this.map=map;
+                       this.tags=tags;
+                       if (map.nodes[id]) {
+                               // ** already exists - do stuff if it's moved, or in a way
+                       } else {
+                               map.nodes[id]=new Node(id,lon,map.lat2latp(lat),tags,version);
+                       }
+               }
+               
+               // redraw
+       }
+}
diff --git a/net/systemeD/halcyon/Way.as b/net/systemeD/halcyon/Way.as
new file mode 100755 (executable)
index 0000000..64672d2
--- /dev/null
@@ -0,0 +1,311 @@
+package net.systemeD.halcyon {
+
+       import flash.net.*;
+       import flash.display.*;
+       import flash.geom.Matrix;
+       import flash.geom.Point;
+       import flash.geom.Rectangle;
+       import flash.text.AntiAliasType;
+       import flash.text.GridFitType;
+       import flash.text.TextField;
+       import flash.text.TextFormat;
+       import net.systemeD.halcyon.styleparser.*;
+
+       public class Way extends Object {
+
+               public var id:int;
+               public var path:Array;
+               public var pathlength:Number;                           // length of path
+
+               public var tags:Object;
+               public var clean:Boolean=true;                          // altered since last upload?
+               public var uploading:Boolean=false;                     // currently uploading?
+               public var locked:Boolean=false;                        // locked against upload?
+               public var version:uint=0;                                      // version number?
+               public var layer:int=0;                                         // map layer
+               public var map:Map;                                                     // reference to parent map
+               public var stroke:Sprite;                                       // instance in display list
+               public var fill:Sprite;                                         //  |
+               public var roadname:Sprite;                                     //  |
+
+               public static const DEFAULT_TEXTFIELD_PARAMS:Object = {
+                       embedFonts: true,
+                       antiAliasType: AntiAliasType.ADVANCED,
+                       gridFitType: GridFitType.NONE
+               };
+               [Embed(source="fonts/DejaVuSans.ttf", fontFamily="DejaVu", fontWeight="normal", mimeType="application/x-font-truetype")]
+               public static var DejaVu:Class;
+               public var nameformat:TextFormat;
+
+//             public var depth:int=-1;                                        // child id ('depth') of sprite: -1=undrawn
+//             public var historic:Boolean=false;                      // is this an undeleted, not-uploaded way?
+//             public var checkconnections:Boolean=false;      // check shared nodes on reload
+//             public var mergedways:Array;
+
+               public function Way(id:int,version:int,map:Map) {
+                       this.id=id;
+                       this.version=version;
+                       this.map=map;
+               }
+
+               // ------------------------------------------------------------------------------------------
+               // Load from server
+
+               public function load(connection:AMFConnection):void {
+                       connection.getWay(id,new Responder(gotWay,null));
+                       // ** should be connectionError, not null
+               }
+               
+               public function gotWay(r:Object):void {
+                       var lx:Number,ly:Number;
+                       var code:uint     =r.shift(); if (code) { map.connectionError(); return; }
+                       var message:String=r.shift();
+                       clean=true;
+                       locked=false;
+                       tags=r[2];
+                       version=r[3];
+//                     this.historic=false;
+//                     removeNodeIndex();
+//                     resetBbox();
+                       path=[];
+                       pathlength=0;
+                       
+                       for each (var p:Array in r[1]) {
+//                             updateBbox(p[0],p[1]);
+                               if (!isNaN(lx)) { pathlength+=Math.sqrt( Math.pow(p[0]-lx,2)+Math.pow(p[1]-ly,2) ) };
+                               lx=p[0]; ly=p[1];
+                               var n:uint=p[2];
+                               // ** what to do if node exists?
+                               map.nodes[n]=new Node(n, p[0], map.lat2latp(p[1]), p[3], p[4]);
+                               map.nodes[n].clean=true;
+                               path.push(map.nodes[n]);
+//                             map.nodes[id].addWay(this.id);
+                       }
+                       pathlength*=map.scalefactor;
+                       redraw();
+                       // ** various other stuff
+               }
+
+               // ------------------------------------------------------------------------------------------
+               // Redraw
+
+               public function redraw():void {
+
+                       // ** remove previous version from any layer
+                       layer=5;
+                       if (tags['layer']) { layer=Math.min(Math.max(tags['layer']+5,-5),5)+5; }
+
+                       // find/create sprites
+                       if (stroke) {
+                               fill.graphics.clear(); 
+                               stroke.graphics.clear(); 
+                               roadname.graphics.clear();
+                               while (roadname.numChildren) { roadname.removeChildAt(0); }
+                       } else {
+                               fill=new Sprite(); addToLayer(fill,0);
+                               stroke=new Sprite(); addToLayer(stroke,1); 
+                               roadname=new Sprite(); addToLayer(roadname,2); 
+                       }
+                       var g:Graphics=stroke.graphics;
+                       var f:Graphics=fill.graphics;
+
+                       // set style
+                       var styles:Array=map.ruleset.getStyle(false,tags,map.scale);
+
+                       // ShapeStyle
+                       // ** do line-caps/joints
+                       var doStroke:Boolean=false, doDashed:Boolean=false;
+                       var doFill:Boolean=false, fill_colour:uint, fill_opacity:Number;
+                       var doCasing:Boolean=false, doDashedCasing:Boolean=false;
+                       if (styles[0]) {
+                               var ss:ShapeStyle=styles[0];
+                               if (ss.isStroked) {     doStroke=true;
+                                                                       doDashed=(ss.stroke_dashArray.length>0);
+                                                                       g.lineStyle(ss.stroke_width, ss.stroke_colour, ss.stroke_opacity/100,
+                                                                                               false,"normal", ss.stroke_linecap,ss.stroke_linejoin); }
+                               if (ss.isCased)   { doCasing=true;
+                                                                       doDashedCasing=(ss.casing_dashArray.length>0);
+                                                                       f.lineStyle(ss.casing_width, ss.casing_colour, ss.casing_opacity/100,
+                                                                                               false,"normal", ss.stroke_linecap, ss.stroke_linejoin); }
+                               if (ss.isFilled)  { doFill=true;
+                                                                       fill_colour = ss.fill_colour;
+                                                                       fill_opacity= ss.fill_opacity/100; }
+                       }
+
+                       // draw line
+                       if (doFill            ) { f.beginFill(fill_colour,fill_opacity); }
+                       if (doStroke          ) { g.moveTo(map.lon2coord(path[0].lon),map.latp2coord(path[0].latp)); }
+                       if (doFill || doCasing) { f.moveTo(map.lon2coord(path[0].lon),map.latp2coord(path[0].latp)); }
+
+                       if (doDashed) { dashedLine(g,ss.stroke_dashArray); }
+                       else if (doStroke) { solidLine(g); }
+                       
+                       if (doDashedCasing) { dashedLine(f,ss.casing_dashArray); f.lineStyle(); }
+                       if (doFill) {
+                               f.beginFill(fill_colour,fill_opacity); 
+                               solidLine(f);
+                               f.endFill(); 
+                       } else if (doCasing && !doDashedCasing) { solidLine(f); }
+
+                       // TextStyle
+                       // ** do pull-out
+                       if (styles[2] && styles[2].tag && tags[styles[2].tag]) {
+                               var ts:TextStyle=styles[2];
+                               nameformat = new TextFormat(ts.font_name   ? ts.font_name : "DejaVu",
+                                                                                       ts.text_size   ? ts.text_size : 8,
+                                                                                       ts.text_colour ? ts.text_colour: 0,
+                                                                                       ts.font_bold   ? ts.font_bold : false,
+                                                                                       ts.font_italic ? ts.font_italic: false);
+                               var a:String=tags[ts.tag]; if (ts.font_caps) { a=a.toUpperCase(); }
+                               writeName(roadname,a,ts.text_offset ? ts.text_offset : 0);
+                       }
+                       // ShieldStyle - 3
+                       // ** to do
+               }
+               
+               // ------------------------------------------------------------------------------------------
+               // Drawing support functions
+
+               // Draw solid polyline
+               
+               private function solidLine(g:Graphics):void {
+                       g.moveTo(map.lon2coord(path[0].lon),map.latp2coord(path[0].latp));
+                       for (var i:uint=1; i<path.length; i++) {
+                               g.lineTo(map.lon2coord(path[i].lon),map.latp2coord(path[i].latp));
+                       }
+               }
+
+               // Draw dashed polyline
+               
+               private function dashedLine(g:Graphics,dashes:Array):void {
+                       var draw:Boolean=false, dashleft:Number=0, dc:Array=new Array();
+                       var a:Number, xc:Number, yc:Number;
+                       var curx:Number, cury:Number;
+                       var dx:Number, dy:Number, segleft:Number=0;
+                       var i:int=0;
+                       g.moveTo(map.lon2coord(path[0].lon),map.latp2coord(path[0].latp));
+                       while (i<path.length-1 || segleft>0) {
+                               if (dashleft<=0) {      // should be ==0
+                                       if (dc.length==0) { dc=dashes.slice(0); }
+                                       dashleft=dc.shift();
+                                       draw=!draw;
+                               }
+                               if (segleft<=0) {       // should be ==0
+                                       curx=map.lon2coord(path[i].lon ); dx=map.lon2coord(path[i+1].lon )-curx;
+                                       cury=map.latp2coord(path[i].latp); dy=map.latp2coord(path[i+1].latp)-cury;
+                                       a=Math.atan2(dy,dx); xc=Math.cos(a); yc=Math.sin(a);
+                                       segleft=Math.sqrt(dx*dx+dy*dy);
+                                       i++;
+                               }
+
+                               if (segleft<=dashleft) {
+                                       // the path segment is shorter than the dash
+                                       curx+=dx; cury+=dy;
+                                       moveLine(g,curx,cury,draw);
+                                       dashleft-=segleft; segleft=0;
+                               } else {
+                                       // the path segment is longer than the dash
+                                       curx+=dashleft*xc; dx-=dashleft*xc;
+                                       cury+=dashleft*yc; dy-=dashleft*yc;
+                                       moveLine(g,curx,cury,draw);
+                                       segleft-=dashleft; dashleft=0;
+                               }
+                       }
+               }
+
+               private function moveLine(g:Graphics,x:Number,y:Number,draw:Boolean):void {
+                       if (draw) { g.lineTo(x,y); }
+                                else { g.moveTo(x,y); }
+               }
+
+               
+               // Find point partway (0-1) along a path
+               // returns (x,y,angle)
+               // inspired by senocular's Path.as
+               
+               private function pointAt(t:Number):Array {
+                       var totallen:Number = t*pathlength;
+                       var curlen:Number = 0;
+                       var dx:Number, dy:Number, seglen:Number;
+                       for (var i:int=1; i<path.length; i++){
+                               dx=map.lon2coord(path[i].lon )-map.lon2coord(path[i-1].lon );
+                               dy=map.latp2coord(path[i].latp)-map.latp2coord(path[i-1].latp);
+                               seglen=Math.sqrt(dx*dx+dy*dy);
+                               if (totallen > curlen+seglen) { curlen+=seglen; continue; }
+                               return new Array(map.lon2coord(path[i-1].lon )+(totallen-curlen)/seglen*dx,
+                                                                map.latp2coord(path[i-1].latp)+(totallen-curlen)/seglen*dy,
+                                                                Math.atan2(dy,dx));
+                       }
+                       return new Array(0, 0, 0);
+               }
+
+               // Draw name along path
+               // based on code by Tom Carden
+               // ** needs styling
+               
+               private function writeName(s:Sprite,a:String,textOffset:Number=0):void {
+
+                       // make a dummy textfield so we can measure its width
+                       var tf:TextField = new TextField();
+                       tf.defaultTextFormat = nameformat;
+                       tf.text = a;
+                       tf.width = tf.textWidth+4;
+                       tf.height = tf.textHeight+4;
+                       if (pathlength<tf.width) { return; }    // no room for text?
+
+                       var t1:Number = (pathlength/2 - tf.width/2) / pathlength; var p1:Array=pointAt(t1);
+                       var t2:Number = (pathlength/2 + tf.width/2) / pathlength; var p2:Array=pointAt(t2);
+
+                       var angleOffset:Number; // so we can do a 180º if we're running backwards
+                       var offsetSign:Number;  // -1 if we're starting at t2
+                       var tStart:Number;      // t1 or t2
+
+                       // make sure text doesn't run right->left or upside down
+                       if (p1[0] < p2[0] && 
+                               p1[2] < Math.PI/2 &&
+                               p1[2] > -Math.PI/2) {
+                               angleOffset = 0; offsetSign = 1; tStart = t1;
+                       } else {
+                               angleOffset = Math.PI; offsetSign = -1; tStart = t2;
+                       } 
+
+                       // make a textfield for each char, centered on the line,
+                       // using getCharBoundaries to rotate it around its center point
+                       var chars:Array = a.split('');
+                       for (var i:int = 0; i < chars.length; i++) {
+                               var rect:Rectangle = tf.getCharBoundaries(i);
+                               if (rect) {
+                                       s.addChild(rotatedLetter(chars[i],
+                                                                                        tStart + offsetSign*(rect.left+rect.width/2)/pathlength,
+                                                                                        rect.width, tf.height, angleOffset, textOffset));
+                               }
+                       }
+               }
+
+               private function rotatedLetter(char:String, t:Number, w:Number, h:Number, a:Number, o:Number):TextField {
+                       var tf:TextField = new TextField();
+                       tf.embedFonts = true;
+                       tf.defaultTextFormat = nameformat;
+                       tf.text = char;
+                       tf.width = tf.textWidth+4;
+                       tf.height = tf.textHeight+4;
+
+                       var p:Array=pointAt(t);
+                       var matrix:Matrix = new Matrix();
+                       matrix.translate(-w/2, -h/2-o);
+                       // ** add (say) -4 to the height to move it up by 4px
+                       matrix.rotate(p[2]+a);
+                       matrix.translate(p[0], p[1]);
+                       tf.transform.matrix = matrix;
+                       return tf;
+               }
+               
+               // Add object (stroke/fill/roadname) to layer sprite
+               
+               private function addToLayer(s:Sprite,sublayer:uint):void {
+                       var l:DisplayObject=Map(map).getChildAt(layer);
+                       var o:DisplayObject=Sprite(l).getChildAt(sublayer);
+                       Sprite(o).addChild(s);
+               }
+       }
+}
diff --git a/net/systemeD/halcyon/fonts/DejaVuSans-Bold.ttf b/net/systemeD/halcyon/fonts/DejaVuSans-Bold.ttf
new file mode 100644 (file)
index 0000000..ebefb0c
Binary files /dev/null and b/net/systemeD/halcyon/fonts/DejaVuSans-Bold.ttf differ
diff --git a/net/systemeD/halcyon/fonts/DejaVuSans-BoldOblique.ttf b/net/systemeD/halcyon/fonts/DejaVuSans-BoldOblique.ttf
new file mode 100644 (file)
index 0000000..b76a556
Binary files /dev/null and b/net/systemeD/halcyon/fonts/DejaVuSans-BoldOblique.ttf differ
diff --git a/net/systemeD/halcyon/fonts/DejaVuSans-ExtraLight.ttf b/net/systemeD/halcyon/fonts/DejaVuSans-ExtraLight.ttf
new file mode 100644 (file)
index 0000000..2124d7a
Binary files /dev/null and b/net/systemeD/halcyon/fonts/DejaVuSans-ExtraLight.ttf differ
diff --git a/net/systemeD/halcyon/fonts/DejaVuSans-Oblique.ttf b/net/systemeD/halcyon/fonts/DejaVuSans-Oblique.ttf
new file mode 100644 (file)
index 0000000..f53ca19
Binary files /dev/null and b/net/systemeD/halcyon/fonts/DejaVuSans-Oblique.ttf differ
diff --git a/net/systemeD/halcyon/fonts/DejaVuSans.ttf b/net/systemeD/halcyon/fonts/DejaVuSans.ttf
new file mode 100644 (file)
index 0000000..6253857
Binary files /dev/null and b/net/systemeD/halcyon/fonts/DejaVuSans.ttf differ
diff --git a/net/systemeD/halcyon/fonts/DejaVuSansCondensed-Bold.ttf b/net/systemeD/halcyon/fonts/DejaVuSansCondensed-Bold.ttf
new file mode 100644 (file)
index 0000000..5e2081d
Binary files /dev/null and b/net/systemeD/halcyon/fonts/DejaVuSansCondensed-Bold.ttf differ
diff --git a/net/systemeD/halcyon/fonts/DejaVuSansCondensed-BoldOblique.ttf b/net/systemeD/halcyon/fonts/DejaVuSansCondensed-BoldOblique.ttf
new file mode 100644 (file)
index 0000000..a98f6e1
Binary files /dev/null and b/net/systemeD/halcyon/fonts/DejaVuSansCondensed-BoldOblique.ttf differ
diff --git a/net/systemeD/halcyon/fonts/DejaVuSansCondensed-Oblique.ttf b/net/systemeD/halcyon/fonts/DejaVuSansCondensed-Oblique.ttf
new file mode 100644 (file)
index 0000000..418cbd3
Binary files /dev/null and b/net/systemeD/halcyon/fonts/DejaVuSansCondensed-Oblique.ttf differ
diff --git a/net/systemeD/halcyon/fonts/DejaVuSansCondensed.ttf b/net/systemeD/halcyon/fonts/DejaVuSansCondensed.ttf
new file mode 100644 (file)
index 0000000..f4c6622
Binary files /dev/null and b/net/systemeD/halcyon/fonts/DejaVuSansCondensed.ttf differ
diff --git a/net/systemeD/halcyon/fonts/DejaVuSansMono-Bold.ttf b/net/systemeD/halcyon/fonts/DejaVuSansMono-Bold.ttf
new file mode 100644 (file)
index 0000000..830a00a
Binary files /dev/null and b/net/systemeD/halcyon/fonts/DejaVuSansMono-Bold.ttf differ
diff --git a/net/systemeD/halcyon/fonts/DejaVuSansMono-BoldOblique.ttf b/net/systemeD/halcyon/fonts/DejaVuSansMono-BoldOblique.ttf
new file mode 100644 (file)
index 0000000..3fd0eec
Binary files /dev/null and b/net/systemeD/halcyon/fonts/DejaVuSansMono-BoldOblique.ttf differ
diff --git a/net/systemeD/halcyon/fonts/DejaVuSansMono-Oblique.ttf b/net/systemeD/halcyon/fonts/DejaVuSansMono-Oblique.ttf
new file mode 100644 (file)
index 0000000..108e2f2
Binary files /dev/null and b/net/systemeD/halcyon/fonts/DejaVuSansMono-Oblique.ttf differ
diff --git a/net/systemeD/halcyon/fonts/DejaVuSansMono.ttf b/net/systemeD/halcyon/fonts/DejaVuSansMono.ttf
new file mode 100644 (file)
index 0000000..3d1ae27
Binary files /dev/null and b/net/systemeD/halcyon/fonts/DejaVuSansMono.ttf differ
diff --git a/net/systemeD/halcyon/fonts/DejaVuSerif-Bold.ttf b/net/systemeD/halcyon/fonts/DejaVuSerif-Bold.ttf
new file mode 100644 (file)
index 0000000..0a063ca
Binary files /dev/null and b/net/systemeD/halcyon/fonts/DejaVuSerif-Bold.ttf differ
diff --git a/net/systemeD/halcyon/fonts/DejaVuSerif-BoldItalic.ttf b/net/systemeD/halcyon/fonts/DejaVuSerif-BoldItalic.ttf
new file mode 100644 (file)
index 0000000..3d73ee7
Binary files /dev/null and b/net/systemeD/halcyon/fonts/DejaVuSerif-BoldItalic.ttf differ
diff --git a/net/systemeD/halcyon/fonts/DejaVuSerif-Italic.ttf b/net/systemeD/halcyon/fonts/DejaVuSerif-Italic.ttf
new file mode 100644 (file)
index 0000000..5057bd0
Binary files /dev/null and b/net/systemeD/halcyon/fonts/DejaVuSerif-Italic.ttf differ
diff --git a/net/systemeD/halcyon/fonts/DejaVuSerif.ttf b/net/systemeD/halcyon/fonts/DejaVuSerif.ttf
new file mode 100644 (file)
index 0000000..77f769e
Binary files /dev/null and b/net/systemeD/halcyon/fonts/DejaVuSerif.ttf differ
diff --git a/net/systemeD/halcyon/fonts/DejaVuSerifCondensed-Bold.ttf b/net/systemeD/halcyon/fonts/DejaVuSerifCondensed-Bold.ttf
new file mode 100644 (file)
index 0000000..9429786
Binary files /dev/null and b/net/systemeD/halcyon/fonts/DejaVuSerifCondensed-Bold.ttf differ
diff --git a/net/systemeD/halcyon/fonts/DejaVuSerifCondensed-BoldItalic.ttf b/net/systemeD/halcyon/fonts/DejaVuSerifCondensed-BoldItalic.ttf
new file mode 100644 (file)
index 0000000..a07fda6
Binary files /dev/null and b/net/systemeD/halcyon/fonts/DejaVuSerifCondensed-BoldItalic.ttf differ
diff --git a/net/systemeD/halcyon/fonts/DejaVuSerifCondensed-Italic.ttf b/net/systemeD/halcyon/fonts/DejaVuSerifCondensed-Italic.ttf
new file mode 100644 (file)
index 0000000..a2d8bc5
Binary files /dev/null and b/net/systemeD/halcyon/fonts/DejaVuSerifCondensed-Italic.ttf differ
diff --git a/net/systemeD/halcyon/fonts/DejaVuSerifCondensed.ttf b/net/systemeD/halcyon/fonts/DejaVuSerifCondensed.ttf
new file mode 100644 (file)
index 0000000..f5cbd17
Binary files /dev/null and b/net/systemeD/halcyon/fonts/DejaVuSerifCondensed.ttf differ
diff --git a/net/systemeD/halcyon/styleparser/Condition.as b/net/systemeD/halcyon/styleparser/Condition.as
new file mode 100644 (file)
index 0000000..e19e532
--- /dev/null
@@ -0,0 +1,40 @@
+package net.systemeD.halcyon.styleparser {
+
+       // valid conditions:
+       // _type_       _params_
+       // regex        key, regex
+       // eq           key, value
+
+       public class Condition {
+               public var type:String;         // eq, regex, lt, gt etc.
+               public var params:Array;        // e.g. ('highway','primary')
+               
+               // ------------------------------------------------------------------------------------------
+               // Constructor function
+               
+               public function Condition(t:String='', ...a) {
+                       type=t; params=a;
+               }
+               
+               // ------------------------------------------------------------------------------------------
+               // Test a hash against this condition
+
+               public function test(tags:Object):Boolean {
+                       switch (type) {
+                               case 'eq':              return (tags[params[0]]==params[1]); break;
+                               case 'regex':   var r:RegExp=new RegExp(params[1],"i");
+                                                               return (r.test(tags[params[0]])); break;
+                               case 'true':    return (tags[params[0]]=='true' || tags[params[0]]=='yes' || tags[params[0]]=='1'); break;
+                               case 'untrue':  return (tags[params[0]]!='true' && tags[params[0]]!='yes' && tags[params[0]]!='1'); break;
+                               case 'set':             return (tags[params[0]]!=undefined && tags[params[0]]!=''); break;
+                               case 'unset':   return (tags[params[0]]==undefined || tags[params[0]]==''); break;
+                               case '<':               return (Number(tags[params[0]])< Number(params[1])); break;
+                               case '<=':              return (Number(tags[params[0]])<=Number(params[1])); break;
+                               case '>':               return (Number(tags[params[0]])> Number(params[1])); break;
+                               case '>=':              return (Number(tags[params[0]])>=Number(params[1])); break;
+                       }
+                       return false;
+               }
+       }
+
+}
diff --git a/net/systemeD/halcyon/styleparser/PointRule.as b/net/systemeD/halcyon/styleparser/PointRule.as
new file mode 100644 (file)
index 0000000..b053b66
--- /dev/null
@@ -0,0 +1,13 @@
+package net.systemeD.halcyon.styleparser {
+
+       public class PointRule extends Rule {
+               public var pointStyle:PointStyle;
+               public var textStyle:TextStyle;
+
+               public function PointRule(c:Array=null,ps:PointStyle=null,ts:TextStyle=null) {
+                       conditions=c;
+                       pointStyle=ps;
+                       textStyle=ts;
+               }
+       }
+}
diff --git a/net/systemeD/halcyon/styleparser/PointStyle.as b/net/systemeD/halcyon/styleparser/PointStyle.as
new file mode 100644 (file)
index 0000000..1a28a50
--- /dev/null
@@ -0,0 +1,11 @@
+package net.systemeD.halcyon.styleparser {
+
+       public class PointStyle {
+
+               public var icon:String;
+               public var width:uint;
+               public var height:uint;
+
+       }
+
+}
diff --git a/net/systemeD/halcyon/styleparser/Rule.as b/net/systemeD/halcyon/styleparser/Rule.as
new file mode 100644 (file)
index 0000000..d9853ce
--- /dev/null
@@ -0,0 +1,23 @@
+package net.systemeD.halcyon.styleparser {
+
+       public class Rule {
+
+               public var conditions:Array;
+               public var breaker:Boolean = true;
+               public var isAnd:Boolean = true;
+               public var minScale:uint = 19;
+               public var maxScale:uint = 13;
+
+               public function test(tags:Object):Boolean {
+                       var v:Boolean; var i:uint=0;
+                       for each (var condition:Condition in conditions) {
+                               var r:Boolean=condition.test(tags);
+                               if (i==0) { v=r; }
+                               else if (isAnd) { v=v && r; }
+                               else { v = v || r;}
+                               i++;
+                       }
+                       return v;
+               }
+       }
+}
\ No newline at end of file
diff --git a/net/systemeD/halcyon/styleparser/RuleSet.as b/net/systemeD/halcyon/styleparser/RuleSet.as
new file mode 100644 (file)
index 0000000..131f195
--- /dev/null
@@ -0,0 +1,88 @@
+package net.systemeD.halcyon.styleparser {
+
+       import org.as3yaml.*;
+       import flash.events.*;
+       import flash.net.*;
+
+       public class RuleSet {
+
+               public var rules:Array=new Array();             // list of rules
+
+               // variables for name, author etc.
+
+               // returns array of ShapeStyle,PointStyle,TextStyle,ShieldStyle
+               public function getStyle(isPoint:Boolean,tags:Object,scale:uint):Array {
+                       var ss:ShapeStyle;
+                       var ps:PointStyle;
+                       var ts:TextStyle;
+                       var hs:ShieldStyle;
+                       for each (var rule:* in rules) {
+                               if ( isPoint && rule is ShapeRule) { continue; }
+                               if (!isPoint && rule is PointRule) { continue; }
+                               if (scale>rule.minScale) { continue; }
+                               if (scale<rule.maxScale) { continue; }
+                               if (rule.test(tags)) {
+                                       if (rule is ShapeRule && rule.shapeStyle)  { ss=rule.shapeStyle; }
+                                       if (rule is PointRule && rule.pointStyle)  { ps=rule.pointStyle; }
+                                       if (                     rule.textStyle )  { ts=rule.textStyle; }
+                                       if (rule is ShapeRule && rule.shieldStyle) { hs=rule.shieldStyle; }
+                                       if (rule.breaker)     { break; }
+                               }
+                       }
+                       return new Array(ss,ps,ts,hs);
+               }
+
+               // Save and load rulesets
+
+               public function save(url:String,name:String):void {
+
+                       var request:URLRequest=new URLRequest(url);
+                       var requestVars:URLVariables=new URLVariables();
+                       var loader:URLLoader=new URLLoader();
+                       
+                       // send to server
+                       requestVars['name']=name;
+                       requestVars['data']=YAML.encode(rules);
+                       request.data=requestVars;
+                       request.method = URLRequestMethod.POST;  
+                       loader.dataFormat = URLLoaderDataFormat.TEXT;
+                       loader.addEventListener(Event.COMPLETE,                                         savedRuleSet,                   false, 0, true);
+                       loader.addEventListener(HTTPStatusEvent.HTTP_STATUS,            httpStatusHandler,              false, 0, true);
+                       loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR,      securityErrorHandler,   false, 0, true);
+                       loader.addEventListener(IOErrorEvent.IO_ERROR,                          ioErrorHandler,                 false, 0, true);
+                       loader.load(request);
+               }
+
+               public function load(url:String):void {
+
+                       var request:URLRequest=new URLRequest(url);
+                       var loader:URLLoader=new URLLoader();
+
+                       request.method=URLRequestMethod.GET;
+                       loader.dataFormat = URLLoaderDataFormat.TEXT;
+                       loader.addEventListener(Event.COMPLETE,                                         loadedRuleSet,                  false, 0, true);
+                       loader.addEventListener(HTTPStatusEvent.HTTP_STATUS,            httpStatusHandler,              false, 0, true);
+                       loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR,      securityErrorHandler,   false, 0, true);
+                       loader.addEventListener(IOErrorEvent.IO_ERROR,                          ioErrorHandler,                 false, 0, true);
+                       loader.load(request);
+               }
+
+               // data handlers
+               private function savedRuleSet(event:Event):void {
+                       var loader:URLLoader = URLLoader(event.target);  
+                       // do something with loader.data
+               }
+               
+               private function loadedRuleSet(event:Event):void {
+                       var loader:URLLoader = URLLoader(event.target);  
+                       rules=YAML.decode(event.target.data) as Array;
+                       // fire some event or other to tell map to redraw
+               }
+
+               private function httpStatusHandler( event:HTTPStatusEvent ):void { }
+               private function securityErrorHandler( event:SecurityErrorEvent ):void { }
+               private function ioErrorHandler( event:IOErrorEvent ):void { }
+               
+               // serialise/deserialise methods
+       }
+}
diff --git a/net/systemeD/halcyon/styleparser/ShapeRule.as b/net/systemeD/halcyon/styleparser/ShapeRule.as
new file mode 100644 (file)
index 0000000..59f4876
--- /dev/null
@@ -0,0 +1,15 @@
+package net.systemeD.halcyon.styleparser {
+
+       public class ShapeRule extends Rule {
+               public var shapeStyle:ShapeStyle;
+               public var textStyle:TextStyle;
+               public var shieldStyle:ShieldStyle;
+
+               public function ShapeRule(c:Array=null,ss:ShapeStyle=null,ts:TextStyle=null,hs:ShieldStyle=null) {
+                       conditions=c;
+                       shapeStyle=ss;
+                       textStyle=ts;
+                       shieldStyle=hs;
+               }
+       }
+}
diff --git a/net/systemeD/halcyon/styleparser/ShapeStyle.as b/net/systemeD/halcyon/styleparser/ShapeStyle.as
new file mode 100644 (file)
index 0000000..bcf79b2
--- /dev/null
@@ -0,0 +1,26 @@
+package net.systemeD.halcyon.styleparser {
+
+       public class ShapeStyle {
+
+               public var isStroked:Boolean=true;
+               public var stroke_colour:uint=0x777777;
+               public var stroke_width:Number=1;
+               public var stroke_opacity:uint=100;
+               public var stroke_dashArray:Array=[];
+               public var stroke_linecap:String="none";
+               public var stroke_linejoin:String="round";
+               
+               public var isFilled:Boolean=false;
+               public var fill_colour:uint=0xFFFFFF;
+               public var fill_opacity:Number=100;
+               public var fill_pattern:String;
+               
+               public var isCased:Boolean=false;
+               public var casing_width:Number=1;
+               public var casing_colour:uint=0;
+               public var casing_opacity:Number=100;
+               public var casing_dashArray:Array=[];
+               
+       }
+
+}
diff --git a/net/systemeD/halcyon/styleparser/ShieldStyle.as b/net/systemeD/halcyon/styleparser/ShieldStyle.as
new file mode 100644 (file)
index 0000000..f243a82
--- /dev/null
@@ -0,0 +1,11 @@
+package net.systemeD.halcyon.styleparser {
+
+       public class ShieldStyle extends TextStyle {
+
+               public var shield:String;
+               public var shield_width:uint;
+               public var shield_height:uint;
+
+       }
+
+}
diff --git a/net/systemeD/halcyon/styleparser/TextStyle.as b/net/systemeD/halcyon/styleparser/TextStyle.as
new file mode 100644 (file)
index 0000000..fabd48b
--- /dev/null
@@ -0,0 +1,19 @@
+package net.systemeD.halcyon.styleparser {
+
+       public class TextStyle {
+
+               public var font_name:String;
+               public var font_bold:Boolean;
+               public var font_italic:Boolean;
+               public var font_caps:Boolean;
+               public var text_size:uint;
+               public var text_colour:uint;
+               public var text_offset:Number;  // Y offset - i.e. within or outside casing?
+               public var tag:String;
+               public var pullout_colour:uint;
+               public var pullout_radius:uint;
+               public var isLine:Boolean;
+
+       }
+
+}
diff --git a/org/as3yaml/BaseConstructor.as b/org/as3yaml/BaseConstructor.as
new file mode 100755 (executable)
index 0000000..1761c62
--- /dev/null
@@ -0,0 +1,332 @@
+/* Copyright (c) 2007 Derek Wischusen
+ *
+ * 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.
+ */
+
+package org.as3yaml {
+
+import flash.utils.Dictionary;
+import flash.utils.getQualifiedClassName;
+
+import mx.logging.LogLogger;
+
+import org.as3yaml.nodes.*;
+import org.idmedia.as3commons.util.*;
+
+public class BaseConstructor implements Constructor {
+    private static var yamlConstructors : Dictionary = new Dictionary();
+    private static var yamlMultiConstructors : Dictionary = new Dictionary();
+    private static var yamlMultiRegexps : Map = new HashMap();
+   
+    public function getYamlConstructor(key : Object) : Function {
+        return yamlConstructors[key] as Function;
+    }
+
+    public function getYamlMultiConstructor(key : Object) : Function {
+        return yamlMultiConstructors[key] as Function;
+    }
+
+    public function getYamlMultiRegexp(key : Object) : RegExp {
+        return yamlMultiRegexps[key] as RegExp;
+    }
+
+    public function getYamlMultiRegexps() : Map {
+        return yamlMultiRegexps;
+    }
+
+    public static function addConstructor(tag : String, ctor : Function) : void {
+        yamlConstructors[tag] = ctor;
+    }
+
+    public static function addMultiConstructor(tagPrefix : String, ctor : Function) : void {
+        yamlMultiConstructors[tagPrefix] = ctor;
+        yamlMultiRegexps.put(tagPrefix, new RegExp("^"+tagPrefix));
+    }
+
+    private var composer : Composer;
+    private var constructedObjects : Dictionary = new Dictionary();
+    private var recursiveObjects : Dictionary = new Dictionary();
+
+    public function BaseConstructor(composer : Composer) {
+        this.composer = composer;
+    }
+
+    public function checkData() : Boolean {
+        return composer.checkNode();
+    }
+
+    public function getData() : Object {
+        if(composer.checkNode()) {
+            var node : Node = composer.getNode();
+            if(null != node) {
+                return constructDocument(node);
+            }
+        }
+        return null;
+    }
+
+    
+    public function eachDocument(ctor : Constructor) : Iterator {
+        return new DocumentIterator(ctor);
+    }
+
+    public function iterator() : Iterator {
+        return eachDocument(this);
+    }
+    
+    public function constructDocument(node : Node) : Object {
+        var data : Object = constructObject(node);
+        constructedObjects = new Dictionary();
+        recursiveObjects = new Dictionary();
+        return data;
+    }
+
+    public function constructObject(node : Node) : Object {
+        if(constructedObjects[node]) {
+            return constructedObjects[node];
+        }
+        if(recursiveObjects[node]) {
+            throw new ConstructorException(null,"found recursive node",null);
+        }
+        recursiveObjects[node] = null;
+        var data : Object;
+        var ctor : Function = getYamlConstructor(node.getTag());
+        if(ctor == null) {
+            var through : Boolean = true;
+            var yamlMultiRegExps : Array = getYamlMultiRegexps().keySet().toArray();
+            
+            for each(var tagPrefix : String in yamlMultiRegExps) {
+                var reg : RegExp = getYamlMultiRegexp(tagPrefix);
+                if(reg.exec(node.getTag())) {
+                    var tagSuffix : String = node.getTag().substring(tagPrefix.length);
+                    ctor = getYamlMultiConstructor(tagPrefix);
+                    data = ctor(this, tagSuffix, node);
+                    through = false;
+                    break;
+                }
+            }
+            if(through) {
+                var xctor : Function = getYamlMultiConstructor(null);
+                if(null != xctor) {
+                    data = xctor(this, node.getTag(), node);
+                } else {
+                    ctor = getYamlConstructor(null);
+                    if(ctor != null) {
+                        data = ctor(this,node)
+                    }
+                }
+            }
+        } else {
+               data = ctor(this,node);
+        }
+        constructedObjects[node] = data;
+        delete recursiveObjects[node];
+        return data;
+    }
+
+    public function constructPrimitive(node : Node) : Object {
+        if(node is ScalarNode) {
+            return constructScalar(node);
+        } else if(node is SequenceNode) {
+            return constructSequence(node);
+        } else if(node is MappingNode) {
+            return constructMapping(node);
+        } else {
+            new LogLogger('error').error(node.getTag());
+        }
+        return null;
+    }
+
+    public function constructScalar(node : Node) : Object {
+        if(!(node is ScalarNode)) {
+            if(node is MappingNode) {
+                var vals : Dictionary = node.getValue() as Dictionary;
+                for(var key : Object in vals) {
+                    if("tag:yaml.org,2002:value" == (key.getTag())) {
+                        return constructScalar(Node(vals.get(key)));
+                    }
+                }
+            }
+            throw new ConstructorException(null,"expected a scalar node, but found " + getQualifiedClassName(node),null);
+        }
+        return node.getValue();
+    }
+
+    public function constructPrivateType(node : Node) : Object {
+        var val : Object = null;
+        if(node.getValue() is Map) {
+            val = constructMapping(node);
+        } else if(node.getValue() is List) {
+            val = constructSequence(node);
+        } else if (node.getValue() is Dictionary) {
+               val = constructMapping(node);
+       } else {
+            val = node.getValue().toString();
+        }
+        return new PrivateType(node.getTag(),val);
+    } 
+    
+    public function constructSequence(node : Node) : Object {
+        if(!(node is SequenceNode)) {
+            throw new ConstructorException(null,"expected a sequence node, but found " + getQualifiedClassName(node),null);
+        }
+        var seq : Array = node.getValue() as Array;
+        var val : Array = new Array();
+        for each(var item:Node in seq) {
+            val.push(constructObject(item));
+        }
+        return val;
+    }
+
+    public function constructMapping(node : Node) : Object {
+        if(!(node is MappingNode)) {
+            throw new ConstructorException(null,"expected a mapping node, but found " + getQualifiedClassName(node),null);
+        }
+        var mapping : Dictionary = new Dictionary();
+        var merge : Array;
+        var val : Dictionary = node.getValue() as Dictionary;
+               var key : Object;
+               for (key in val) {
+            var key_v : Node = key as Node;
+            var value_v : Node = val[key];
+            if(key_v.getTag() == ("tag:yaml.org,2002:merge")) {
+                if(merge != null) {
+                    throw new ConstructorException("while constructing a mapping", "found duplicate merge key",null);
+                }
+                if(value_v is MappingNode) {
+                    merge = new Array();
+                    merge.push(constructMapping(value_v));
+                } else if(value_v is SequenceNode) {
+                    merge = new Array();
+                    var vals : Array = value_v.getValue() as Array;
+                    for each(var subnode : Node in vals) {
+                        if(!(subnode is MappingNode)) {
+                            throw new ConstructorException("while constructing a mapping","expected a mapping for merging, but found " + getQualifiedClassName(subnode),null);
+                        }
+                        merge.unshift(constructMapping(subnode));
+                    }
+                } else {
+                    throw new ConstructorException("while constructing a mapping","expected a mapping or list of mappings for merging, but found " + getQualifiedClassName(value_v),null);
+                }
+            } else if(key_v.getTag() == ("tag:yaml.org,2002:value")) {
+                if(mapping["="]) {
+                    throw new ConstructorException("while construction a mapping", "found duplicate value key", null);
+                }
+                mapping["="] = constructObject(value_v);
+            } else {
+               var kObj : Object = constructObject(key_v), vObj : Object = constructObject(value_v);
+                mapping[kObj] = vObj;
+            }
+        }
+        if(null != merge) {
+            merge.push(mapping);
+            mapping = new Dictionary();
+            for each(var item : Dictionary in merge) {
+                for (key in item)
+                       mapping[key] = item[key];
+            }
+        }
+        return mapping;
+    }
+
+    public function constructPairs(node : Node) : Object {
+        if(!(node is MappingNode)) {
+            throw new ConstructorException(null,"expected a mapping node, but found " + getQualifiedClassName(node), null);
+        }
+        var value : Array = new Array();
+        var vals : Dictionary = node.getValue() as Dictionary;
+        for (var key : Object in vals) {
+            var val : Node = vals[key] as Node;
+            value.push([constructObject(key as Node),constructObject(val)]);
+        }
+        return value;
+    }
+    
+    
+    public function constructOmap (node : Node) : Object {
+        if(!(node is SequenceNode)) {
+            throw new ConstructorException(null,"expected a sequence node, but found " + getQualifiedClassName(node), null);
+        }
+        var value : Array = new Array();
+        var vals : Array = node.getValue() as Array;
+               var addedKeyValHash : Object = new Object();
+               
+        for each(var val : Node in vals) {  
+          
+            var hash : Dictionary = constructObject(val) as Dictionary;
+                       var hashSize: int = 0;
+            var hashKey: Object;
+            for (var key: Object in hash)
+            {  
+               hashKey = key;
+               hashSize++;
+            }
+            
+            if (hashSize > 1)
+               throw new YAMLException("Each Map in an Ordered Map (!omap) is permitted to have only one key");
+          
+            var hashValue : Object = hash[hashKey];
+            
+            if(!(addedKeyValHash[hashKey] && (addedKeyValHash[hashKey] == hashValue)))
+            {
+               value.push(hash);
+               addedKeyValHash[hashKey] = hashValue;
+            }
+           
+        }
+        
+        return value;          
+    }
+    
+
+    public static function CONSTRUCT_PRIMITIVE(self : Constructor, node : Node) : Object {
+                return self.constructPrimitive(node);
+            }
+    public static function CONSTRUCT_SCALAR(self : Constructor, node : Node) : Object {
+                return self.constructScalar(node);
+            }
+    public static function CONSTRUCT_PRIVATE(self : Constructor, node : Node) : Object {
+                return self.constructPrivateType(node);
+            }
+    public static function CONSTRUCT_SEQUENCE(self : Constructor, node : Node) : Object {
+                return self.constructSequence(node);
+            }
+    public static function CONSTRUCT_MAPPING(self : Constructor, node : Node) : Object {
+                return self.constructMapping(node);
+            }
+}// BaseConstructorImpl
+}
+       
+       import org.as3yaml.Constructor;
+       import org.as3yaml.nodes.Node
+
+       import org.idmedia.as3commons.util.Iterator;    
+
+internal class DocumentIterator implements Iterator {
+       
+       private var _constructor : Constructor;
+       
+       public function DocumentIterator(ctor : Constructor) : void
+       {
+               _constructor = ctor;
+       }
+    public function hasNext() : Boolean {return _constructor.checkData();}
+    public function next() : * {return _constructor.getData();}
+    public function remove() : void {}
+}
diff --git a/org/as3yaml/Composer.as b/org/as3yaml/Composer.as
new file mode 100755 (executable)
index 0000000..553d801
--- /dev/null
@@ -0,0 +1,162 @@
+/* Copyright (c) 2007 Derek Wischusen
+ *
+ * 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.
+ */
+
+package org.as3yaml {
+
+import flash.utils.Dictionary;
+
+import org.as3yaml.events.*;
+import org.as3yaml.nodes.*;
+
+public class Composer {
+    private var parser : Parser;
+    private var resolver : Resolver;
+    private var anchors : Dictionary;
+
+    public function Composer(parser : Parser, resolver : Resolver) : void {
+        this.parser = parser;
+        this.resolver = resolver;
+        this.anchors = new Dictionary();
+    }
+
+    public function checkNode() : Boolean {
+        return !(parser.peekEvent() is StreamEndEvent);
+    }
+    
+    public function getNode() : Node {
+        return checkNode() ? composeDocument() : Node(null);
+    }
+
+    public function eachNode(composer : Composer) : NodeIterator {
+        return new NodeIterator(composer);
+    }
+
+    public function iterator() : NodeIterator {
+        return eachNode(this);
+    }
+
+    public function composeDocument() : Node {
+        if(parser.peekEvent() is StreamStartEvent) {
+            //Drop STREAM-START event
+            parser.getEvent();
+        }
+        //Drop DOCUMENT-START event
+        parser.getEvent();
+        var node : Node = composeNode(null,null);
+        //Drop DOCUMENT-END event
+        parser.getEvent();
+        this.anchors = new Dictionary();
+        return node;
+    }
+
+    private static var FALS : Array = [false];
+    private static var TRU : Array = [true];
+
+    public function composeNode(parent : Node, index : Object) : Node {
+               var event : Event = parser.peekEvent();
+               var anchor : String;
+        if(event is AliasEvent) {
+            var eve : AliasEvent = parser.getEvent() as AliasEvent;
+            anchor = eve.getAnchor();
+            if(!anchors[anchor]) {
+                
+                throw new ComposerException(null,"found undefined alias " + anchor,null);
+            }
+            return anchors[anchor] as Node;
+        }
+        anchor = null;
+        if(event is NodeEvent) {
+            anchor = NodeEvent(event).getAnchor();
+        }
+        if(null != anchor) {
+            if(anchors[anchor]) {
+                throw new ComposerException("found duplicate anchor "+anchor+"; first occurence",null,null);
+            }
+        }
+        resolver.descendResolver(parent,index);
+        var node : Node = null;
+               var tag : String;
+        if(event is ScalarEvent) {
+            var ev : ScalarEvent = parser.getEvent() as ScalarEvent;
+            tag = ev.getTag();
+            if(tag == null || tag == ("!")) {
+                tag = resolver.resolve(ScalarNode,ev.getValue(),ev.getImplicit());
+            }
+            node = new ScalarNode(tag,ev.getValue(),ev.getStyle());
+            if(null != anchor) {
+                anchors[anchor] = node;
+            }
+        } else if(event is SequenceStartEvent) {
+            var start : SequenceStartEvent = parser.getEvent() as SequenceStartEvent;
+            tag = start.getTag();
+            if(tag == null || tag == ("!")) {
+                tag = resolver.resolve(SequenceNode,null,start.getImplicit()  ? TRU : FALS);
+            }
+            node = new SequenceNode(tag,[],start.getFlowStyle());
+            if(null != anchor) {
+                anchors[anchor] = node;
+            }
+            var ix : int = 0;
+            var nodeVal: Array = node.getValue() as Array;
+            while(!(parser.peekEvent() is SequenceEndEvent)) {
+                nodeVal.push(composeNode(node, ix++));
+            }
+            parser.getEvent();
+        } else if(event is MappingStartEvent) {
+            var st : MappingStartEvent = parser.getEvent() as MappingStartEvent;
+            tag = st.getTag();
+            if(tag == null || tag == ("!")) {
+                tag = resolver.resolve(MappingNode,null, st.getImplicit() ? TRU : FALS);
+            }
+            node = new MappingNode(tag, new Dictionary(), st.getFlowStyle());
+            if(null != anchor) {
+                anchors[anchor] = node;
+            }
+            var mapNodeVal: Dictionary = node.getValue() as Dictionary;
+            while(!(parser.peekEvent() is MappingEndEvent)) {
+                var key : Event = parser.peekEvent();
+                var itemKey : Node = composeNode(node,null);
+                if(mapNodeVal[itemKey]) {
+                    composeNode(node,itemKey);
+                } else {
+                    mapNodeVal[itemKey] = composeNode(node,itemKey);
+                }
+            }
+            parser.getEvent();
+        }
+        resolver.ascendResolver();
+        return node;
+    }
+    
+}
+}
+
+import org.as3yaml.Composer;
+import org.as3yaml.nodes.Node;
+       
+
+internal class NodeIterator {
+       private var composer : Composer;
+       public function NodeIterator(composer : Composer) : void { this.composer = composer; }
+    public function hasNext() : Boolean {return composer.checkNode();}
+    public function next() :  Node{return composer.getNode();}
+    public function remove() : void {}
+}
diff --git a/org/as3yaml/ComposerException.as b/org/as3yaml/ComposerException.as
new file mode 100755 (executable)
index 0000000..42b1f38
--- /dev/null
@@ -0,0 +1,51 @@
+/* Copyright (c) 2007 Derek Wischusen
+ *
+ * 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.
+ */
+
+package org.as3yaml {
+
+public class ComposerException extends YAMLException {
+    private var when : String;
+    private var what : String;
+    private var note : String;
+
+    public function ComposerException(when : String, what : String, note : String) {
+        super("ComposerException " + when + " we had this " + what);
+        this.when = when;
+        this.what = what;
+        this.note = note;
+    }
+    
+    override public function toString() : String {
+        var lines : String = new String();
+        if(this.when != null) {
+            lines += (this.when) + ("\n");
+        }
+        if(this.what != null) {
+            lines += (this.what) + ("\n");
+        }
+        if(this.note != null) {
+            lines += (this.note) + ("\n");
+        }
+        lines += (super.toString());
+        return lines.toString();
+    }
+}// ComposerException
+}
\ No newline at end of file
diff --git a/org/as3yaml/Constructor.as b/org/as3yaml/Constructor.as
new file mode 100755 (executable)
index 0000000..3266b69
--- /dev/null
@@ -0,0 +1,43 @@
+/* Copyright (c) 2007 Derek Wischusen
+ *
+ * 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.
+ */
+
+package org.as3yaml{
+
+import org.as3yaml.nodes.Node;
+import org.idmedia.as3commons.util.Iterator;
+
+public interface Constructor {
+    function checkData() : Boolean;
+    function getData() : Object;
+    function eachDocument(ctor : Constructor) : Iterator;
+    function iterator() : Iterator;
+    function constructDocument(node : Node) : Object;
+    //function constructfunction(node : Node) : Object;
+    function constructPrimitive(node : Node) : Object;
+    function constructScalar(node : Node) : Object;
+    function constructPrivateType(node : Node) : Object;
+    function constructSequence(node : Node) : Object;
+    function constructMapping(node : Node) : Object;
+    function constructPairs(node : Node) : Object;
+    function constructOmap(node : Node ) : Object;
+
+}// Constructor
+}
\ No newline at end of file
diff --git a/org/as3yaml/ConstructorException.as b/org/as3yaml/ConstructorException.as
new file mode 100755 (executable)
index 0000000..88a1d56
--- /dev/null
@@ -0,0 +1,51 @@
+/* Copyright (c) 2007 Derek Wischusen
+ *
+ * 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.
+ */
+
+package org.as3yaml {
+
+public class ConstructorException extends YAMLException {
+    private var when : String;
+    private var what : String;
+    private var note : String;
+
+    public function ConstructorException(when : String, what : String, note : String) {
+        super("ConstructorException " + when + " we had this " + what);
+        this.when = when;
+        this.what = what;
+        this.note = note;
+    }
+    
+    override public function toString() : String {
+        var lines : String = new String();
+        if(this.when != null) {
+           lines += this.when + "\n"
+        }
+        if(this.what != null) {
+            lines += this.what + "\n"
+        }
+        if(this.note != null) {
+           lines += this.note + "\n"
+        }
+        //lines += super.toString();
+        return lines;
+    }
+}// ConstructorException
+}
\ No newline at end of file
diff --git a/org/as3yaml/ConstructorImpl.as b/org/as3yaml/ConstructorImpl.as
new file mode 100755 (executable)
index 0000000..ab8bb5f
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2007 Derek Wischusen
+ * 
+ * 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.
+ */
+
+package org.as3yaml {
+
+    import flash.utils.Dictionary;
+    
+    import org.idmedia.as3commons.util.HashMap;
+    import org.idmedia.as3commons.util.Map;;
+       
+       public class ConstructorImpl extends SafeConstructor 
+       {
+           private static var yamlConstructors : Dictionary = new Dictionary();
+           private static var yamlMultiConstructors : Dictionary = new Dictionary();
+           private static var yamlMultiRegexps : HashMap = new HashMap();
+           
+           override public function getYamlConstructor(key:Object) : Function {
+               
+               var ctor : Function = yamlConstructors[key];
+               
+               if(ctor == null) {
+                 ctor = super.getYamlConstructor(key);
+               }   
+               return ctor;
+           }
+       
+           override public function getYamlMultiConstructor(key : Object) : Function {
+               
+               var ctor : Function = yamlMultiConstructors[key];
+               
+               if(ctor == null) {
+                ctor = super.getYamlMultiConstructor(key);
+               } 
+                  
+               return ctor;
+           }
+       
+           override public function getYamlMultiRegexp(key : Object) : RegExp {
+               var mine : RegExp =  yamlMultiRegexps.get(key);
+               if(mine == null) {
+                   mine = super.getYamlMultiRegexp(key);
+               }
+               return mine;
+           }
+       
+           override public function getYamlMultiRegexps() : Map {
+               var all : Map = new HashMap();
+               all.putAll(super.getYamlMultiRegexps());
+               all.putAll(yamlMultiRegexps);
+               return all;
+           }
+       
+           public static function addConstructor(tag : String, ctor : YamlConstructor) : void {
+               yamlConstructors.put(tag,ctor);
+           }
+       
+           public static function addMultiConstructor(tagPrefix : String, ctor : YamlMultiConstructor) : void {
+               yamlMultiConstructors.put(tagPrefix,ctor);
+               yamlMultiRegexps.put(tagPrefix,new RegExp("^"+tagPrefix));
+           }
+       
+           public function ConstructorImpl( composer : Composer) {
+               super(composer);
+           }
+       
+       }
+}
\ No newline at end of file
diff --git a/org/as3yaml/DefaultYAMLConfig.as b/org/as3yaml/DefaultYAMLConfig.as
new file mode 100755 (executable)
index 0000000..9e057dc
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2007 Derek Wischusen
+ * 
+ * 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.
+ */
+
+package org.as3yaml {
+
+public class DefaultYAMLConfig implements YAMLConfig {
+    private var _indent:int= 2;
+    private var _useHeader:Boolean= false;
+    private var _useVersion:Boolean= false;
+    private var _version:String= "1.1";
+    private var _expStart:Boolean= true;
+    private var _expEnd:Boolean= false;
+    private var _format:String= "id{0}";
+    private var _expTypes:Boolean= false;
+    private var _canonical:Boolean= false;
+    private var _bestWidth:int= 80;
+    private var _useBlock:Boolean= false;
+    private var _useFlow:Boolean= false;
+    private var _usePlain:Boolean= false;
+    private var _useSingle:Boolean= false;
+    private var _useDouble:Boolean= false;
+    private var _processorFunction: Function = null;
+    
+    public function indent(indent:int):YAMLConfig{ _indent = indent; return this; }
+    public function getIndent():int{ return _indent; }
+    public function useHeader(useHead:Boolean):YAMLConfig{ _useHeader = useHead; return this; }
+    public function getUseHeader():Boolean{ return _useHeader; }
+    public function useVersion(useVersion:Boolean):YAMLConfig{ _useVersion = useVersion; return this; }
+    public function getUseVersion():Boolean{ return _useVersion; }
+    public function version(version:String):YAMLConfig{ _version = version; return this; }
+    public function getVersion():String{ return _version; }
+    public function explicitStart(expStart:Boolean):YAMLConfig{ _expStart = expStart; return this; }
+    public function explicitEnd(expEnd:Boolean):YAMLConfig{ _expEnd = expEnd; return this; }
+    public function getExplicitEnd() : Boolean { return _expEnd };
+    public function getExplicitStart() : Boolean { return _expStart };
+    public function anchorFormat(format:String):YAMLConfig{ _format = format; return this; }
+    public function getAnchorFormat():String{return _format; }
+    public function explicitTypes(expTypes:Boolean = false):YAMLConfig{ _expTypes = expTypes; return this; }
+    public function getExplicitTypes():Boolean{ return _expTypes; }
+
+    public function canonical(canonical:Boolean):YAMLConfig{ _canonical = canonical; return this; }
+    public function getCanonical():Boolean{ return _canonical; }
+
+    public function bestWidth(bestWidth:int):YAMLConfig{ _bestWidth = bestWidth; return this; }
+    public function getBestWidth():int{ return _bestWidth; }
+
+    public function useBlock(useBlock:Boolean):YAMLConfig{ _useBlock = useBlock; return this; }
+
+    public function useFlow(useFlow:Boolean):YAMLConfig{ _useFlow = useFlow; return this; }
+
+    public function usePlain(usePlain:Boolean):YAMLConfig{ _usePlain = usePlain; return this; }
+
+    public function useSingle(useSingle:Boolean):YAMLConfig{ _useSingle = useSingle; return this; }
+
+    public function useDouble(useDouble:Boolean):YAMLConfig{ _useDouble = useDouble; return this; }
+
+    public function getUseSingle():Boolean{ return _useSingle; }
+
+    public function getUseDouble():Boolean{ return _useDouble; }
+    
+}
+}
diff --git a/org/as3yaml/DefaultYAMLFactory.as b/org/as3yaml/DefaultYAMLFactory.as
new file mode 100755 (executable)
index 0000000..a3921d3
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2007 Derek Wischusen
+ * 
+ * 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.
+ */
+package org.as3yaml {\r
+\r
+import org.rxr.actionscript.io.*;
+
+public class DefaultYAMLFactory implements YAMLFactory {
+    public function createScanner(io : String) : Scanner {
+        return new Scanner(io);
+    }
+    public function createParser(scanner : Scanner, cfg : YAMLConfig) : Parser {
+        return new Parser(scanner,cfg);
+    }
+    public function createResolver() : Resolver {
+        return new Resolver();
+    }
+    public function createComposer(parser : Parser,  resolver : Resolver) : Composer {
+        return new Composer(parser,resolver);
+    }
+    public function createConstructor(composer : Composer) : Constructor {
+        return new ConstructorImpl(composer);
+    }
+    public function createEmitter(output : StringWriter, cfg : YAMLConfig) : Emitter {
+        return new Emitter(output,cfg);
+    }
+    public function createSerializer(emitter : Emitter, resolver : Resolver, cfg : YAMLConfig) : Serializer {
+        return new Serializer(emitter,resolver,cfg);
+    }
+    public function createRepresenter(serializer : Serializer, cfg : YAMLConfig) : Representer {
+        return new Representer(serializer,cfg);
+    }
+}
+}
\ No newline at end of file
diff --git a/org/as3yaml/Emitter.as b/org/as3yaml/Emitter.as
new file mode 100755 (executable)
index 0000000..34ecf15
--- /dev/null
@@ -0,0 +1,821 @@
+/*
+ * Copyright (c) 2007 Derek Wischusen
+ * 
+ * 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.
+ */
+
+package org.as3yaml {
+
+import org.as3yaml.events.*;
+import org.idmedia.as3commons.util.Iterator;
+import org.idmedia.as3commons.util.Map;
+import org.idmedia.as3commons.util.HashMap;
+import org.rxr.actionscript.io.StringWriter;
+
+
+
+public class Emitter {
+
+    internal static const STREAM_START : int = 0;
+    internal static const FIRST_DOCUMENT_START : int = 1;
+    internal static const DOCUMENT_ROOT : int = 2;
+    internal static const NOTHING : int = 3;
+    internal static const DOCUMENT_START : int = 4;
+    internal static const DOCUMENT_END : int = 5;
+    internal static const FIRST_FLOW_SEQUENCE_ITEM : int = 6;
+    internal static const FLOW_SEQUENCE_ITEM : int = 7;
+    internal static const FIRST_FLOW_MAPPING_KEY : int = 8;
+    internal static const FLOW_MAPPING_SIMPLE_VALUE : int = 9;
+    internal static const FLOW_MAPPING_VALUE : int = 10;
+    internal static const FLOW_MAPPING_KEY : int = 11;
+    internal static const BLOCK_SEQUENCE_ITEM : int = 12;
+    internal static const FIRST_BLOCK_MAPPING_KEY : int = 13;
+    internal static const BLOCK_MAPPING_SIMPLE_VALUE : int = 14;
+    internal static const BLOCK_MAPPING_VALUE : int = 15;
+    internal static const BLOCK_MAPPING_KEY : int = 16;
+    internal static const FIRST_BLOCK_SEQUENCE_ITEM : int = 17;
+    
+    private static var STATES : Array = new Array();
+    
+    static: {
+        STATES[STREAM_START] = function expect(env : EmitterEnvironment) : void {
+                    env.expectStreamStart();
+                };
+
+        STATES[FIRST_DOCUMENT_START] = function expect(env : EmitterEnvironment) : void {
+                    env.expectDocumentStart(true);
+                };
+            
+        STATES[DOCUMENT_ROOT] = function expect(env : EmitterEnvironment) : void {
+                    env.expectDocumentRoot();
+                };
+            
+        STATES[NOTHING] =  function expect(env : EmitterEnvironment) : void {
+                    env.expectNothing();
+                };
+            
+        STATES[DOCUMENT_START] = function expect(env : EmitterEnvironment) : void {
+                    env.expectDocumentStart(false);
+                };
+            
+        STATES[DOCUMENT_END] = function expect(env : EmitterEnvironment ) : void {
+                    env.expectDocumentEnd();
+                };
+            
+        STATES[FIRST_FLOW_SEQUENCE_ITEM] = function expect(env : EmitterEnvironment) : void {
+                    env.expectFirstFlowSequenceItem();
+                };
+            
+        STATES[FLOW_SEQUENCE_ITEM] = function expect(env : EmitterEnvironment) : void {
+                    env.expectFlowSequenceItem();
+                };
+            
+        STATES[FIRST_FLOW_MAPPING_KEY] = function expect(env : EmitterEnvironment) : void {
+                    env.expectFirstFlowMappingKey();
+                };
+            
+        STATES[FLOW_MAPPING_SIMPLE_VALUE] = function expect(env : EmitterEnvironment) : void {
+                    env.expectFlowMappingSimpleValue();
+                };
+            
+        STATES[FLOW_MAPPING_VALUE] = function expect(env : EmitterEnvironment) : void {
+                    env.expectFlowMappingValue();
+                };
+            
+        STATES[FLOW_MAPPING_KEY] = function expect(env : EmitterEnvironment) : void {
+                    env.expectFlowMappingKey();
+                };
+            
+        STATES[BLOCK_SEQUENCE_ITEM] = function expect(env : EmitterEnvironment) : void {
+                    env.expectBlockSequenceItem(false);
+                };
+            
+        STATES[FIRST_BLOCK_MAPPING_KEY] = function expect(env : EmitterEnvironment) : void {
+                    env.expectFirstBlockMappingKey();
+                };
+            
+        STATES[BLOCK_MAPPING_SIMPLE_VALUE] = function expect(env : EmitterEnvironment) : void {
+                    env.expectBlockMappingSimpleValue();
+                };
+            
+        STATES[BLOCK_MAPPING_VALUE] = function expect(env : EmitterEnvironment) : void {
+                    env.expectBlockMappingValue();
+                };
+            
+        STATES[BLOCK_MAPPING_KEY] = function expect(env : EmitterEnvironment) : void {
+                    env.expectBlockMappingKey(false);
+                };
+            
+        STATES[FIRST_BLOCK_SEQUENCE_ITEM] = function expect(env : EmitterEnvironment) : void  {
+                    env.expectBlockSequenceItem(true);
+                };
+            
+    }
+
+    public static var DEFAULT_TAG_PREFIXES_1_0 : Map;
+    public static var DEFAULT_TAG_PREFIXES_1_1 : Map;
+    static: {
+        private static var defInit0 : Map = new HashMap();
+        defInit0.put("tag:yaml.org,2002:","!");
+        DEFAULT_TAG_PREFIXES_1_0 = defInit0;
+        private static var defInit : Map = new HashMap();
+        defInit.put("!","!");
+        defInit.put("tag:yaml.org,2002:","!!");
+        DEFAULT_TAG_PREFIXES_1_1 = defInit;
+    }
+
+    private var stream : StringWriter;
+    private var options : YAMLConfig;
+    private var env : EmitterEnvironment;
+
+    public function Emitter(stream : StringWriter, opts : YAMLConfig) {
+        this.stream = stream;
+        this.options = opts;
+        this.env = new EmitterEnvironment();
+        this.env.emitter = this;
+        this.env.canonical = this.options.getCanonical();
+        var propIndent : int = this.options.getIndent();
+        if(propIndent>=2 && propIndent<10) {
+            this.env.bestIndent = propIndent;
+        }
+        var propWidth : int = this.options.getBestWidth();
+        if(propWidth != 0 && propWidth > (this.env.bestIndent*2)) {
+            this.env.bestWidth = propWidth;
+        }
+    }
+
+    public function getOptions() : YAMLConfig {
+        return options;
+    }
+
+    public function emit(event : Event) : void {
+        this.env.events.add(event);
+        while(!this.env.needMoreEvents()) {
+            this.env.event = this.env.events.removeAtAndReturn(0);
+            STATES[this.env.state](env);
+            this.env.event = null;
+        }
+    }
+
+    internal function writeStreamStart() : void {
+    }
+
+    internal function writeStreamEnd() : void {
+        flushStream();
+    }
+    
+    internal function writeIndicator(indicator : String, needWhitespace : Boolean, whitespace : Boolean, indentation : Boolean) : void {
+        var data : String = null;
+        if(!(env.whitespace || !needWhitespace)) {
+             data = " " + indicator;
+        } else {
+               data = indicator;
+        }
+        env.whitespace = whitespace;
+        env.indentation = env.indentation && indentation;
+        env.column += data.length;
+        stream.write(data);
+    }
+
+    internal function writeIndent() : void {
+        var indent : int = 0;
+        if(env.indent != -1) {
+            indent = env.indent;
+        }
+
+        if(!env.indentation || env.column > indent || (env.column == indent && !env.whitespace)) {
+            writeLineBreak(null);
+        }
+
+        if(env.column < indent) {
+            env.whitespace = true;
+            var data : String = new String();
+            for(var i:int=0;i<(indent-env.column);i++) {
+                data += " ";
+            }
+            env.column = indent;
+            stream.write(data);
+        }
+    }
+
+    internal function writeVersionDirective(version_text : String) : void {
+        stream.write("%YAML " + version_text);
+        writeLineBreak(null);
+    }
+    
+    internal function writeTagDirective(handle : String, prefix : String) : void {
+        stream.write("%TAG " + handle + " " + prefix);
+        writeLineBreak(null);
+    }
+
+    internal function writeDoubleQuoted(text : String, split : Boolean) : void {
+        writeIndicator("\"",true,false,false);
+        var start : int = 0;
+        var ending : int = 0;
+        var data : String = null;
+        var textLen: uint = text.length;
+        while(ending <= textLen) {
+            var ch : * = 0;
+            if(ending < textLen) {
+                ch = text.charAt(ending);
+            }
+            if(ch==0 || "\"\\\u0085".indexOf(ch) != -1 || !('\u0020' <= ch && ch <= '\u007E')) {
+                if(start < ending) {
+                    data = text.substring(start,ending);
+                    env.column+=data.length;
+                    stream.write(data);
+                    start = ending;
+                }
+                if(ch != 0) {
+                    if(YAML.ESCAPE_REPLACEMENTS[ch]) {
+                        data = "\\" + YAML.ESCAPE_REPLACEMENTS[ch];
+                    } else if(ch <= '\u00FF') {
+                        var str : String = new int(ch).toString(16);
+                        if(str.length == 1) {
+                            str = "0" + str;
+                        }
+                        data = "\\x" + str;
+                    }
+                    env.column += data.length;
+                    stream.write(data);
+                    start = ending+1;
+                }
+            }
+            if((0 < ending && ending < (textLen-1)) && (ch == ' ' || start >= ending) && (env.column+(ending-start)) > env.bestWidth && split) {
+                data = text.substring(start,ending) + "\\";
+                if(start < ending) {
+                    start = ending;
+                }
+                env.column += data.length;
+                stream.write(data);
+                writeIndent();
+                env.whitespace = false;
+                env.indentation = false;
+                if(text.charAt(start) == ' ') {
+                    data = "\\";
+                    env.column += data.length;
+                    stream.write(data);
+                }
+            }
+            ending += 1;
+        }
+
+        writeIndicator("\"",false,false,false);
+    }
+
+    internal function writeSingleQuoted(text : String, split : Boolean) : void {
+        writeIndicator("'",true,false,false);
+        var spaces : Boolean = false;
+        var breaks : Boolean = false;
+        var start : int = 0; 
+        var ending : int = 0;
+        var ceh : String = null;
+        var data : String = null;
+        while(ending <= text.length) {
+            ceh = null;
+            if(ending < text.length) {
+                ceh = text.charAt(ending);
+            }
+            if(spaces) {
+                if(ceh == null || int(ceh) != 32) {
+                    if(start+1 == ending && env.column > env.bestWidth && split && start != 0 && ending != text.length) {
+                        writeIndent();
+                    } else {
+                        data = text.substring(start,ending);
+                        env.column += data.length;
+                        stream.write(data);
+                    }
+                    start = ending;
+                }
+            } else if(breaks) {
+                if(ceh == null || !('\n' == ceh)) {
+                    data = text.substring(start,ending);
+                    for(var i:int=0,j:int=data.length;i<j;i++) {
+                        var cha : String = data.charAt(i);
+                        if('\n' == cha) {
+                            writeLineBreak(null);
+                        } else {
+                            writeLineBreak(""+cha);
+                        }
+                    }
+                    writeIndent();
+                    start = ending;
+                }
+            } else {
+                if(ceh == null || !('\n' == ceh)) {
+                    if(start < ending) {
+                        data = text.substring(start,ending);
+                        env.column += data.length;
+                        stream.write(data);
+                        start = ending;
+                    }
+                    if(ceh == '\'') {
+                        data = "''";
+                        env.column += 2;
+                        stream.write(data);
+                        start = ending + 1;
+                    }
+                }
+            }
+            if(ceh != null) {
+                spaces = (ceh == ' ');
+                breaks = (ceh == '\n');
+            }
+            ending++;
+        }
+        writeIndicator("'",false,false,false);
+    }
+
+    internal function writeFolded(text : String) : void  {
+        var chomp : String = determineChomp(text);
+        writeIndicator(">" + chomp, true, false, false);
+        writeIndent();
+        var leadingSpace : Boolean = false;
+        var spaces : Boolean = false;
+        var breaks : Boolean = false;
+        var start:int=0,ending:int=0;
+        var data : String = null;
+        while(ending <= text.length) {
+            var ceh : String = null;
+            if(ending < text.length) {
+                ceh = text.charAt(ending);
+            }
+            if(breaks) {
+                if(ceh == null || !('\n' == ceh || '\u0085' == ceh)) {
+                    if(!leadingSpace && ceh != null && ceh != ' ' && text.charAt(start) == '\n') {
+                        writeLineBreak(null);
+                    }
+                    leadingSpace = ceh == ' ';
+                    data = text.substring(start,ending);
+                    for(var i:int=0,j:int=data.length;i<j;i++) {
+                        var cha : String = data.charAt(i);
+                        if('\n' == cha) {
+                            writeLineBreak(null);
+                        } else {
+                            writeLineBreak(""+cha);
+                        }
+                    }
+                    if(ceh != null) {
+                        writeIndent();
+                    }
+                    start = ending;
+                }
+            } else if(spaces) {
+                if(ceh != ' ') {
+                    if(start+1 == ending && env.column > env.bestWidth) {
+                        writeIndent();
+                    } else {
+                        data = text.substring(start,ending);
+                        env.column += data.length;
+                        stream.write(data);
+                    }
+                    start = ending;
+                }
+            } else {
+                if(ceh == null || ' ' == ceh || '\n' == ceh || '\u0085' == ceh) {
+                    data = text.substring(start,ending);
+                    stream.write(data);
+                    if(ceh == null) {
+                        writeLineBreak(null);
+                    } 
+                    start = ending;
+                }
+            }
+            if(ceh != null) {
+                breaks = '\n' == ceh || '\u0085' == ceh;
+                spaces = ceh == ' ';
+            }
+            ending++;
+        }
+    }
+
+    internal function writeLiteral(text : String):void {
+        var chomp:String= determineChomp(text);
+        writeIndicator("|" + chomp, true, false, false);
+        writeIndent();
+        var breaks:Boolean= false;
+        var start:int=0,ending:int=0;
+        var data:String= null;
+        while(ending <= text.length) {
+            var ceh : String = null;
+            if(ending < text.length) {
+                ceh = text.charAt(ending);
+            }
+            if(breaks) {
+                if(ceh == null || !('\n' == ceh || '\u0085' == ceh)) {
+                    data = text.substring(start,ending);
+                    for(var i:int=0,j:int=data.length;i<j;i++) {
+                        var cha : String = data.charAt(i);
+                        if('\n' == cha) {
+                            writeLineBreak(null);
+                        } else {
+                            writeLineBreak(""+cha);
+                        }
+                    }
+                    if(ceh != null) {
+                        writeIndent();
+                    }
+                    start = ending;
+                }
+            } else {
+                if(ceh == null || '\n' == ceh || '\u0085' == ceh) {
+                    data = text.substring(start,ending);
+                    stream.write(data);
+                    if(ceh == null) {
+                        writeLineBreak(null);
+                    }
+                    start = ending;
+                }
+            }
+            if(ceh != null) {
+                breaks = '\n' == ceh || '\u0085' == ceh;
+            }
+            ending++;
+        }
+    }
+
+    internal function writePlain(text : String, split : Boolean):void {
+        if(text == null || "" == text) {
+            return;
+        }
+        var data : String = null;
+        if(!env.whitespace) {
+            data = " ";
+            env.column += data.length;
+            stream.write(data);
+        }
+        env.whitespace = false;
+        env.indentation = false;
+        var spaces:Boolean=false, breaks : Boolean = false;
+        var start:int=0,ending : int=0;
+        while(ending <= text.length) {
+            var ceh : String = null;
+            if(ending < text.length) {
+                ceh = text.charAt(ending);
+            }
+            if(spaces) {
+                if(ceh != ' ') {
+                    if(start+1 == ending && env.column > env.bestWidth && split) {
+                        writeIndent();
+                        env.whitespace = false;
+                        env.indentation = false;
+                    } else {
+                        data = text.substring(start,ending);
+                        env.column += data.length;
+                       stream.write(data);
+                    }
+                    start = ending;
+                }
+            } else if(breaks) {
+                if(ceh != '\n' && ceh != '\u0085') {
+                    if(text.charAt(start) == '\n') {
+                        writeLineBreak(null);
+                    }
+                    data = text.substring(start,ending);
+                    for(var i:int=0,j:int=data.length;i<j;i++) {
+                        var cha : String = data.charAt(i);
+                        if('\n' == cha) {
+                            writeLineBreak(null);
+                        } else {
+                            writeLineBreak(""+cha);
+                        }
+                    }
+                    writeIndent();
+                    env.whitespace = false;
+                    env.indentation = false;
+                    start = ending;
+                }
+            } else {
+                if(ceh == null || ' ' == String(ceh) || '\n' == String(ceh) || '\u0085' == String(ceh)) {
+                    data = text.substring(start,ending);
+                    env.column += data.length;
+                    stream.write(data);
+                    start = ending;
+                }
+            }
+            if(ceh != null) {
+                spaces = String(ceh) == ' ';
+                breaks = String(ceh) == '\n' || String(ceh) == '\u0085';
+            }
+            ending++;
+        }
+    }
+
+    internal function writeLineBreak(data:String):void {
+        var xdata:String= data;
+        if(xdata == null) {
+            xdata = env.bestLineBreak;
+        }
+        env.whitespace = true;
+        env.indentation = true;
+        env.line++;
+        env.column = 0;
+        stream.write(xdata);
+    }
+
+    internal function flushStream() : void {
+        stream.flush();
+    }
+
+    internal function prepareVersion(version : Array) : String {
+        if(version[0] != 1) {
+            throw new EmitterException("unsupported YAML version: " + version[0] + "." + version[1]);
+        }
+        return ""+version[0] + "." + version[1];
+    }
+    
+    private static var HANDLE_FORMAT : RegExp = new RegExp("^![-\\w]*!$");
+    
+    internal static function prepareTagHandle(handle : String):String{
+        if(handle == null || "" == handle) {
+            throw new EmitterException("tag handle must not be empty");
+        } else if(handle.charAt(0) != '!' || handle.charAt(handle.length-1) != '!') {
+            throw new EmitterException("tag handle must start and end with '!': " + handle);
+        } else if(!"!" == handle && !HANDLE_FORMAT.exec(handle)) {
+            throw new EmitterException("invalid syntax for tag handle: " + handle);
+        }
+        return handle;
+    }
+
+    internal static function prepareTagPrefix(prefix : String) : String {
+        if(prefix == null || "" == prefix) {
+            throw new EmitterException("tag prefix must not be empty");
+        }
+        var chunks : String = new String();
+        var start:int=0,ending:int=0;
+        if(prefix.charAt(0) == '!') {
+            ending = 1;
+        }
+        while(ending < prefix.length) {
+            ending++;
+        }
+        if(start < ending) {
+            chunks += prefix.substring(start,ending);
+        }
+        return chunks;
+    }
+
+    private static var ANCHOR_FORMAT : RegExp = new RegExp("^[-\\w]*$");
+    internal static function prepareAnchor(anchor : String) : String {
+        if(anchor == null || "" == anchor) {
+            throw new EmitterException("anchor must not be empty");
+        }
+        if(!ANCHOR_FORMAT.exec(anchor)) {
+            throw new EmitterException("invalid syntax for anchor: " + anchor);
+        }
+        return anchor;
+    }
+
+    internal function prepareTag(tag : String) : String {
+        if(tag == null || "" == tag) {
+            throw new EmitterException("tag must not be empty");
+        }
+        if(tag == "!") {
+            return tag;
+        }
+        var handle : String = null;
+        var suffix : String = tag;
+        for(var iter : Iterator = env.tagPrefixes.keySet().iterator();iter.hasNext();) {
+            var prefix : String = iter.next() as String;
+            if(new RegExp("^" + prefix + ".+$").exec(tag) && (prefix == "!" || prefix.length < tag.length)) {
+                handle = env.tagPrefixes.get(prefix) as String;
+                suffix = tag.substring(prefix.length);
+            }
+        }
+        var chunks : String = new String();
+        var start:int=0,ending:int=0;
+        while(ending < suffix.length) {
+            ending++;
+        }
+        if(start < ending) {
+            chunks += suffix.substring(start,ending);
+        }
+        var suffixText : String = chunks;
+        if(handle != null) {
+            return handle + suffixText;
+        } else {
+            return "!<" + suffixText + ">";
+        }
+    }
+
+    private static var DOC_INDIC : RegExp = new RegExp("^(---|\\.\\.\\.)");
+    private static var NULL_BL_T_LINEBR : String = "\x00 \t\r\n\u0085";
+    private static var SPECIAL_INDIC : String = "#,[]{}#&*!|>'\"%@`";
+    private static var FLOW_INDIC : String = ",?[]{}";
+    internal static function analyzeScalar(scalar : String) : ScalarAnalysis {
+        if(scalar == null || "" == scalar) {
+            return new ScalarAnalysis(scalar,true,false,false,true,true,true,false,false);
+        }
+               var blockIndicators:Boolean= false;
+        var flowIndicators:Boolean= false;
+        var lineBreaks:Boolean= false;
+        var specialCharacters:Boolean= false;
+
+        // Whitespaces.
+        var inlineSpaces: Boolean = false;          // non-space space+ non-space
+        var inlineBreaks: Boolean = false;          // non-space break+ non-space
+        var leadingSpaces: Boolean = false;         // ^ space+ (non-space | $)
+        var leadingBreaks: Boolean = false;         // ^ break+ (non-space | $)
+        var trailingSpaces: Boolean = false;        // (^ | non-space) space+ $
+        var trailingBreaks: Boolean = false;        // (^ | non-space) break+ $
+        var inlineBreaksSpaces: Boolean = false;   // non-space break+ space+ non-space
+        var mixedBreaksSpaces: Boolean = false;    // anything else
+        
+        if(DOC_INDIC.exec(scalar)) {
+            blockIndicators = true;
+            flowIndicators = true;
+        }
+
+               var preceededBySpace:Boolean= true;
+        var followedBySpace:Boolean= scalar.length == 1|| NULL_BL_T_LINEBR.indexOf(scalar.charAt(1)) != -1;
+
+        var spaces:Boolean= false;
+        var breaks:Boolean= false;
+        var mixed:Boolean= false;
+        var leading:Boolean= false;
+        
+        var index:int= 0;
+
+        while(index < scalar.length) {
+            var ceh : String = scalar.charAt(index);
+            if(index == 0) {
+                if(SPECIAL_INDIC.indexOf(ceh) != -1) {
+                    flowIndicators = true;
+                    blockIndicators = true;
+                }
+                if(ceh == '?' || ceh == ':') {
+                    flowIndicators = true;
+                    if(followedBySpace) {
+                        blockIndicators = true;
+                    }
+                }
+                if(ceh == '-' && followedBySpace) {
+                    flowIndicators = true;
+                    blockIndicators = true;
+                }
+            } else {
+                if(FLOW_INDIC.indexOf(ceh) != -1) {
+                    flowIndicators = true;
+                }
+                if(ceh == ':') {
+                    flowIndicators = true;
+                    if(followedBySpace) {
+                        blockIndicators = true;
+                    }
+                }
+                if(ceh == '#' && preceededBySpace) {
+                    flowIndicators = true;
+                    blockIndicators = true;
+                }
+            }
+            if(ceh == '\n' || '\u0085' == ceh) {
+                lineBreaks = true;
+            }
+            if(!(ceh == '\n' || ('\u0020' <= ceh && ceh <= '\u007E'))) {
+                specialCharacters = true;
+
+            }
+            if(' ' == ceh || '\n' == ceh || '\u0085' == ceh) {
+                if(spaces && breaks) {
+                    if(ceh != ' ') {
+                        mixed = true;
+                    }
+                } else if(spaces) {
+                    if(ceh != ' ') {
+                        breaks = true;
+                        mixed = true;
+                    }
+                } else if(breaks) {
+                    if(ceh == ' ') {
+                        spaces = true;
+                    }
+                } else {
+                    leading = (index == 0);
+                    if(ceh == ' ') {
+                        spaces = true;
+                    } else {
+                        breaks = true;
+                    }
+                }
+            } else if(spaces || breaks) {
+                if(leading) {
+                    if(spaces && breaks) {
+                        mixedBreaksSpaces = true;
+                    } else if(spaces) {
+                        leadingSpaces = true;
+                    } else if(breaks) {
+                        leadingBreaks = true;
+                    }
+                } else {
+                    if(mixed) {
+                        mixedBreaksSpaces = true;
+                    } else if(spaces && breaks) {
+                        inlineBreaksSpaces = true;
+                    } else if(spaces) {
+                        inlineSpaces = true;
+                    } else if(breaks) {
+                        inlineBreaks = true;
+                    }
+                }
+                spaces = breaks = mixed = leading = false;
+            }
+
+            if((spaces || breaks) && (index == scalar.length-1)) {
+                if(spaces && breaks) {
+                    mixedBreaksSpaces = true;
+                } else if(spaces) {
+                    trailingSpaces = true;
+                    if(leading) {
+                        leadingSpaces = true;
+                    }
+                } else if(breaks) {
+                    trailingBreaks = true;
+                    if(leading) {
+                        leadingBreaks = true;
+                    }
+                }
+                spaces = breaks = mixed = leading = false;
+            }
+            index++;
+            preceededBySpace = NULL_BL_T_LINEBR.indexOf(ceh) != -1;
+            followedBySpace = index+1 >= scalar.length || NULL_BL_T_LINEBR.indexOf(scalar.charAt(index+1)) != -1;
+        }
+               var allowFlowPlain:Boolean= true;
+        var allowBlockPlain:Boolean= true;
+        var allowSingleQuoted:Boolean= true;
+        var allowDoubleQuoted:Boolean= true;
+        var allowBlock:Boolean= true;
+        
+        if(leadingSpaces || leadingBreaks || trailingSpaces) {
+            allowFlowPlain = allowBlockPlain = allowBlock = false;
+        }
+
+        if(trailingBreaks) {
+            allowFlowPlain = allowBlockPlain = false;
+        }
+
+        if(inlineBreaksSpaces) {
+            allowFlowPlain = allowBlockPlain = allowSingleQuoted = false;
+        }
+
+        if(mixedBreaksSpaces || specialCharacters) {
+            allowFlowPlain = allowBlockPlain = allowSingleQuoted = allowBlock = false;
+        }
+
+        if(inlineBreaks) {
+            allowFlowPlain = allowBlockPlain = allowSingleQuoted = false;
+        }
+        
+        if(trailingBreaks) {
+            allowSingleQuoted = false;
+        }
+
+        if(lineBreaks) {
+            allowFlowPlain = allowBlockPlain = false;
+        }
+
+        if(flowIndicators) {
+            allowFlowPlain = false;
+        }
+        
+        if(blockIndicators) {
+            allowBlockPlain = false;
+        }
+
+        return new ScalarAnalysis(scalar,false,lineBreaks,allowFlowPlain,allowBlockPlain,allowSingleQuoted,allowDoubleQuoted,allowBlock, specialCharacters);
+    }
+
+    internal static function determineChomp(text : String) : String {
+        var ceh : String = ' ';
+        var ceh2 : String =  ' ';
+        
+        if(text.length > 0) {
+            ceh = text.charAt(text.length-1);
+            if(text.length > 1) {
+                ceh2 = text.charAt(text.length-2);
+            }
+        }
+                
+        return (ceh == '\n' || ceh == '\u0085') ? ((ceh2 == '\n' || ceh2 == '\u0085') ? "+" : "") : "-";
+    }
+
+}
+}
+   
\ No newline at end of file
diff --git a/org/as3yaml/EmitterEnvironment.as b/org/as3yaml/EmitterEnvironment.as
new file mode 100755 (executable)
index 0000000..f90d410
--- /dev/null
@@ -0,0 +1,568 @@
+/*
+ * Copyright (c) 2007 Derek Wischusen
+ * 
+ * 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.
+ */
+
+package org.as3yaml {
+       import org.as3yaml.events.*;
+       import org.idmedia.as3commons.util.ArrayList;
+       import org.idmedia.as3commons.util.HashMap;
+       import org.idmedia.as3commons.util.HashSet;
+       import org.idmedia.as3commons.util.Iterator;
+       import org.idmedia.as3commons.util.Map;
+       import org.idmedia.as3commons.util.Set;
+       
+
+    public class EmitterEnvironment {
+        public var states : ArrayList = new ArrayList();
+        public var state : int = Emitter.STREAM_START;
+        public var events : ArrayList = new ArrayList();
+        public var event : Event;
+        public var flowLevel : int = 0;
+        public var indents : ArrayList = new ArrayList();
+        public var indent : int = -1;
+        public var rootContext : Boolean = false;
+        public var sequenceContext : Boolean = false;
+        public var mappingContext : Boolean = false;
+        public var simpleKeyContext : Boolean = false;
+
+        public var line:int= 0;
+        public var column:int= 0;
+        public var whitespace:Boolean= true;
+        public var indentation:Boolean= true;
+        
+        public var canonical:Boolean= false;
+        public var bestIndent:int= 2;
+        public var bestWidth:int= 80;
+
+        public var bestLinebreak:String= "\n";
+
+        public var tagPrefixes:Map;
+
+        public var preparedAnchor:String;
+        public var preparedTag:String;
+        
+        public var analysis:ScalarAnalysis;
+        public var style:*= 0;
+
+        public var emitter:Emitter;
+
+        public var bestLineBreak:String= "\n";
+
+        public function needMoreEvents() : Boolean {
+            if(events.isEmpty()) {
+                return true;
+            }
+            event = events.get(0) as Event;
+            if(event is DocumentStartEvent) {
+                return needEvents(1);
+            } else if(event is SequenceStartEvent) {
+                return needEvents(2);
+            } else if(event is MappingStartEvent) {
+                return needEvents(3);
+            } else {
+                return false;
+            }
+        }
+
+        private function needEvents(count : int) : Boolean {
+            var level : int = 0;
+            var iter : Iterator = events.iterator();
+            iter.next();
+            for(;iter.hasNext();) {
+                var curr : Object = iter.next();
+                if(curr is DocumentStartEvent || curr is CollectionStartEvent) {
+                    level++;
+                } else if(curr is DocumentEndEvent || curr is CollectionEndEvent) {
+                    level--;
+                } else if(curr is StreamEndEvent) {
+                    level = -1;
+                }
+                if(level<0) {
+                    return false;
+                }
+            }
+            return events.size() < count+1;
+        }
+
+        private function increaseIndent(flow : Boolean, indentless : Boolean) : void {
+            indents.addAt(0,  new int(indent));
+            if(indent == -1) {
+                if(flow) {
+                    indent = bestIndent;
+                } else {
+                    indent = 0;
+                }
+            } else if(!indentless) {
+                indent += bestIndent;
+            }
+        }
+
+        public function expectStreamStart() : void {
+            if(this.event is StreamStartEvent) {
+                emitter.writeStreamStart();
+                this.state = Emitter.FIRST_DOCUMENT_START;
+            } else {
+                throw new EmitterException("expected StreamStartEvent, but got " + this.event);
+            }
+        }
+        
+        public function expectNothing() : void {
+            throw new EmitterException("expecting nothing, but got " + this.event);
+        }
+
+        public function expectDocumentStart(first : Boolean) : void {
+            if(event is DocumentStartEvent) {
+                var ev : DocumentStartEvent = DocumentStartEvent(event);
+                if(first) {
+                    if(null != ev.getVersion()) {
+                        emitter.writeVersionDirective(emitter.prepareVersion(ev.getVersion()));
+                    }
+
+                    if((null != ev.getVersion() && ev.getVersion()[1] == 0) || emitter.getOptions().getVersion() == "1.0") {
+                        tagPrefixes = new HashMap();
+                        tagPrefixes.putAll(Emitter.DEFAULT_TAG_PREFIXES_1_0);
+                    } else {
+                        tagPrefixes = new HashMap();
+                        tagPrefixes.putAll(Emitter.DEFAULT_TAG_PREFIXES_1_1);
+                    }
+
+                    if(null != ev.getTags()) {
+                        var handles : Set = new HashSet();
+                        handles.addAll(ev.getTags().keySet());
+                        for(var iter : Iterator = handles.iterator();iter.hasNext();) {
+                            var handle : String = iter.next() as String;
+                            var prefix : String = ev.getTags().get(handle) as String;
+                            tagPrefixes.put(prefix,handle);
+                            var handleText : String = Emitter.prepareTagHandle(handle);
+                            var prefixText : String = Emitter.prepareTagPrefix(prefix);
+                            emitter.writeTagDirective(handleText,prefixText);
+                        }
+                    }
+                }
+
+                var implicit : Boolean = first && !ev.getExplicit() && !canonical && ev.getVersion() == null && ev.getTags() == null && !checkEmptyDocument();
+                if(!implicit) {
+                    emitter.writeIndent();
+                    emitter.writeIndicator("--- ",true,true,false);
+                    if(canonical) {
+                        emitter.writeIndent();
+                    }
+                }
+                state = Emitter.DOCUMENT_ROOT;
+            } else if(event is StreamEndEvent) {
+                emitter.writeStreamEnd();
+                state = Emitter.NOTHING;
+            } else {
+                throw new EmitterException("expected DocumentStartEvent, but got " + event);
+            }
+        }
+
+        public function expectDocumentRoot() : void {
+            states.addAt(0,new int(Emitter.DOCUMENT_END));
+            expectNode(true,false,false,false);
+        }
+
+        public function expectDocumentEnd() : void {
+            if(event is DocumentEndEvent) {
+                emitter.writeIndent();
+                if((DocumentEndEvent(event)).getExplicit()) {
+                    emitter.writeIndicator("...",true,false,false);
+                    emitter.writeIndent();
+                }
+                emitter.flushStream();
+                state = Emitter.DOCUMENT_START;
+            } else {
+                throw new EmitterException("expected DocumentEndEvent, but got " + event);
+            }
+        }
+
+        public function expectFirstFlowSequenceItem() : void {
+            if(event is SequenceEndEvent) {
+                indent = int(indents.removeAtAndReturn(0));
+                flowLevel--;
+                emitter.writeIndicator("]",false,false,false);
+                state = int(states.removeAtAndReturn(0));
+            } else {
+                if(canonical || column > bestWidth) {
+                    emitter.writeIndent();
+                }
+                states.addAt(0,new int(Emitter.FLOW_SEQUENCE_ITEM));
+                expectNode(false,true,false,false);
+            }
+        }
+
+        public function expectFlowSequenceItem() : void {
+            if(event is SequenceEndEvent) {
+                indent = int(indents.removeAtAndReturn(0));
+                flowLevel--;
+                if(canonical) {
+                    emitter.writeIndicator(",",false,false,false);
+                    emitter.writeIndent();
+                }
+                emitter.writeIndicator("]",false,false,false);
+                state = int(states.removeAtAndReturn(0));
+            } else {
+                emitter.writeIndicator(",",false,false,false);
+                if(canonical || column > bestWidth) {
+                    emitter.writeIndent();
+                }
+                states.addAt(0,new int(Emitter.FLOW_SEQUENCE_ITEM));
+                expectNode(false,true,false,false);
+            }
+        }
+
+        public function expectFirstFlowMappingKey() : void {
+            if(event is MappingEndEvent) {
+                indent = int(indents.removeAtAndReturn(0));
+                flowLevel--;
+                emitter.writeIndicator("}",false,false,false);
+                state = int(states.removeAtAndReturn(0));
+            } else {
+                if(canonical || column > bestWidth) {
+                    emitter.writeIndent();
+                }
+                if(!canonical && checkSimpleKey()) {
+                    states.addAt(0,new int(Emitter.FLOW_MAPPING_SIMPLE_VALUE));
+                    expectNode(false,false,true,true);
+                } else {
+                    emitter.writeIndicator("?",true,false,false);
+                    states.addAt(0,new int(Emitter.FLOW_MAPPING_VALUE));
+                    expectNode(false,false,true,false);
+                }
+            }
+        }
+
+        public function expectFlowMappingSimpleValue() : void {
+            emitter.writeIndicator(": ",false,true,false);
+            states.addAt(0,new int(Emitter.FLOW_MAPPING_KEY));
+            expectNode(false,false,true,false);
+        }
+
+        public function expectFlowMappingValue() : void {
+            if(canonical || column > bestWidth) {
+                emitter.writeIndent();
+            }
+            emitter.writeIndicator(": ",false,true,false);
+            states.addAt(0,new int(Emitter.FLOW_MAPPING_KEY));
+            expectNode(false,false,true,false);
+        }
+
+        public function expectFlowMappingKey() : void {
+            if(event is MappingEndEvent) {
+                indent = (int(indents.removeAtAndReturn(0)));
+                flowLevel--;
+                if(canonical) {
+                    emitter.writeIndicator(",",false,false,false);
+                    emitter.writeIndent();
+                }
+                emitter.writeIndicator("}",false,false,false);
+                state = int(states.removeAtAndReturn(0));
+            } else {
+                emitter.writeIndicator(",",false,false,false);
+                if(canonical || column > bestWidth) {
+                    emitter.writeIndent();
+                }
+                if(!canonical && checkSimpleKey()) {
+                    states.addAt(0,new int(Emitter.FLOW_MAPPING_SIMPLE_VALUE));
+                    expectNode(false,false,true,true);
+                } else {
+                    emitter.writeIndicator("?",true,false,false);
+                    states.addAt(0,new int(Emitter.FLOW_MAPPING_VALUE));
+                    expectNode(false,false,true,false);
+                }
+            }
+        }
+
+        public function expectBlockSequenceItem(first : Boolean) : void  {
+            if(!first && event is SequenceEndEvent) {
+                indent = int(indents.removeAtAndReturn(0));
+                state = int(states.removeAtAndReturn(0));
+            } else {
+                emitter.writeIndent();
+                emitter.writeIndicator("-",true,false,true);
+                states.addAt(0,new int(Emitter.BLOCK_SEQUENCE_ITEM));
+                expectNode(false,true,false,false);
+            }
+        }
+
+        public function expectFirstBlockMappingKey() : void {
+            expectBlockMappingKey(true);
+        }
+
+        public function expectBlockMappingSimpleValue() : void {
+            emitter.writeIndicator(": ",false,true,false);
+            states.addAt(0,new int(Emitter.BLOCK_MAPPING_KEY));
+            expectNode(false,false,true,false);
+        }
+
+        public function expectBlockMappingValue() : void {
+            emitter.writeIndent();
+            emitter.writeIndicator(": ",true,true,true);
+            states.addAt(0,new int(Emitter.BLOCK_MAPPING_KEY));
+            expectNode(false,false,true,false);
+        }
+
+        public function expectBlockMappingKey(first : Boolean) : void {
+            if(!first && event is MappingEndEvent) {
+                indent = int(indents.removeAtAndReturn(0));
+                state = int(states.removeAtAndReturn(0));
+            } else {
+                emitter.writeIndent();
+                if(checkSimpleKey()) {
+                    states.addAt(0,new int(Emitter.BLOCK_MAPPING_SIMPLE_VALUE));
+                    expectNode(false,false,true,true);
+                } else {
+                    emitter.writeIndicator("?",true,false,true);
+                    states.addAt(0,new int(Emitter.BLOCK_MAPPING_VALUE));
+                    expectNode(false,false,true,false);
+                }
+            }
+        }
+
+        private function expectNode(root : Boolean, sequence : Boolean, mapping : Boolean, simpleKey : Boolean) : void {
+            rootContext = root;
+            sequenceContext = sequence;
+            mappingContext = mapping;
+            simpleKeyContext = simpleKey;
+            if(event is AliasEvent) {
+                expectAlias();
+            } else if(event is ScalarEvent || event is CollectionStartEvent) {
+                processAnchor("&");
+                processTag();
+                if(event is ScalarEvent) {
+                    expectScalar();
+                } else if(event is SequenceStartEvent) {
+                    if(flowLevel != 0 || canonical || ((SequenceStartEvent(event))).getFlowStyle() || checkEmptySequence()) {
+                        expectFlowSequence();
+                    } else {
+                        expectBlockSequence();
+                    }
+                } else if(event is MappingStartEvent) {
+                    if(flowLevel != 0 || canonical || ((MappingStartEvent(event))).getFlowStyle() || checkEmptyMapping()) {
+                        expectFlowMapping();
+                    } else {
+                        expectBlockMapping();
+                    }
+                }
+            } else {
+                throw new EmitterException("expected NodeEvent, but got " + event);
+            }
+        }
+        
+        private function expectAlias() : void {
+            if((NodeEvent(event)).getAnchor() == null) {
+                throw new EmitterException("anchor is not specified for alias");
+            }
+            processAnchor("*");
+            state = int(states.removeAtAndReturn(0));
+        }
+
+        private function expectScalar() : void {
+            increaseIndent(true,false);
+            processScalar();
+            indent = int(indents.removeAtAndReturn(0));
+            state = int(states.removeAtAndReturn(0));
+        }
+
+        private function expectFlowSequence() : void {
+            emitter.writeIndicator("[",true,true,false);
+            flowLevel++;
+            increaseIndent(true,false);
+            state = Emitter.FIRST_FLOW_SEQUENCE_ITEM;
+        }
+
+        private function expectBlockSequence() : void {
+            increaseIndent(false, !mappingContext && !indentation);
+            state = Emitter.FIRST_BLOCK_SEQUENCE_ITEM;
+        }
+
+        private function expectFlowMapping(): void {
+            emitter.writeIndicator("{",true,true,false);
+            flowLevel++;
+            increaseIndent(true,false);
+            state = Emitter.FIRST_FLOW_MAPPING_KEY;
+        }
+
+        private function expectBlockMapping() : void { 
+            increaseIndent(false,false);
+            state = Emitter.FIRST_BLOCK_MAPPING_KEY;
+        }
+
+        private function checkEmptySequence() : Boolean {
+            return event is SequenceStartEvent && !events.isEmpty() && events.get(0) is SequenceEndEvent;
+        }
+
+        private function checkEmptyMapping() : Boolean {
+            return event is MappingStartEvent && !events.isEmpty() && events.get(0) is MappingEndEvent;
+        }
+
+        private function checkEmptyDocument() : Boolean {
+            if(!(event is DocumentStartEvent) || events.isEmpty()) {
+                return false;
+            }
+            var ev : Event = Event(events.get(0));
+            return ev is ScalarEvent && (ScalarEvent(ev)).getAnchor() == null && (ScalarEvent(ev)).getTag() == null && (ScalarEvent(ev)).getImplicit() != null && (ScalarEvent(ev)).getValue() == "";
+        }
+
+        private function checkSimpleKey() : Boolean {
+            var length : int = 0;
+            if(event is NodeEvent && null != (NodeEvent(event)).getAnchor()) {
+                if(null == preparedAnchor) {
+                    preparedAnchor = Emitter.prepareAnchor((NodeEvent(event)).getAnchor());
+                }
+                length += preparedAnchor.length;
+            }
+            var tag : String = null;
+            if(event is ScalarEvent) {
+                tag = (ScalarEvent(event)).getTag();
+            } else if(event is CollectionStartEvent) {
+                tag = (CollectionStartEvent(event)).getTag();
+            }
+            if(tag != null) {
+                if(null == preparedTag) {
+                    preparedTag = emitter.prepareTag(tag);
+                }
+                length += preparedTag.length;
+            }
+            if(event is ScalarEvent) {
+                if(null == analysis) {
+                    analysis = Emitter.analyzeScalar((ScalarEvent(event)).getValue());
+                    length += analysis.scalar.length;
+                }
+            }
+
+            return (length < 128 && (event is AliasEvent || (event is ScalarEvent && !analysis.empty && !analysis.multiline) || checkEmptySequence() || checkEmptyMapping()));
+        }
+        
+        private function processAnchor(indicator : String) : void {
+            var ev : NodeEvent = event as NodeEvent;
+            if(null == ev.getAnchor()) {
+                preparedAnchor = null;
+                return;
+            }
+            if(null == preparedAnchor) {
+                preparedAnchor = Emitter.prepareAnchor(ev.getAnchor());
+            }
+            if(preparedAnchor != null && "" != preparedAnchor) {
+                emitter.writeIndicator(indicator+preparedAnchor,true,false,false);
+            }
+            preparedAnchor = null;
+        }
+        
+        private function processTag() : void {
+            var tag : String = null;
+            if(event is ScalarEvent) {
+                var ev : ScalarEvent = ScalarEvent(event);
+                tag = ev.getTag();
+                if(style == 0) {
+                    style = chooseScalarStyle();
+                }
+                if(((!canonical || tag == null) && (('0' == style && ev.getImplicit()[0]) || ('0' != style && ev.getImplicit()[1])))) {
+                    preparedTag = null;
+                    return;
+                }
+                if(ev.getImplicit()[0] && null == tag) {
+                    tag = "!";
+                    preparedTag = null;
+                }
+            } else {
+                var eve : CollectionStartEvent = event as CollectionStartEvent;
+                tag = eve.getTag();
+                if((!canonical || tag == null) && eve.getImplicit()) {
+                    preparedTag = null;
+                    return;
+                }
+            }
+            if(tag == null) {
+                throw new EmitterException("tag is not specified");
+            }
+            if(null == preparedTag) {
+                preparedTag = emitter.prepareTag(tag);
+            }
+            if(preparedTag != null && "" != preparedTag) {
+                emitter.writeIndicator(preparedTag,true,false,false);
+            }
+            preparedTag = null;
+        }
+
+        private function chooseScalarStyle() : String {
+             var ev : ScalarEvent = ScalarEvent(event);
+
+            if(null == analysis) {
+                analysis = Emitter.analyzeScalar(ev.getValue());
+            }
+
+            if(ev.getStyle() == '"' || this.canonical) {
+                return '"';
+            }
+            
+            if(ev.getStyle() == '0') {
+                if(!(simpleKeyContext && (analysis.empty || analysis.multiline)) && ((flowLevel != 0 && analysis.allowFlowPlain) || (flowLevel == 0 && analysis.allowBlockPlain))) {
+                    return '0';
+                }
+            }
+            if(ev.getStyle() == '0' && ev.getImplicit()[0] && (!(simpleKeyContext && (analysis.empty || analysis.multiline)) && (flowLevel!=0 && analysis.allowFlowPlain || (flowLevel == 0 && analysis.allowBlockPlain)))) {
+                return '0';
+            }
+            if((ev.getStyle() == '|') && flowLevel == 0 && analysis.allowBlock) {
+                return '|';
+            }            
+            if((ev.getStyle() == '>') && flowLevel == 0 && analysis.allowBlock) {
+                return '\'';
+            }
+            if((ev.getStyle() == '0' || ev.getStyle() == '\'') && (analysis.allowSingleQuoted && !(simpleKeyContext && analysis.multiline))) {
+                return '\'';
+            }
+
+                       var FIRST_SPACE : RegExp = new RegExp("(^|\n) ");
+            if(analysis.multiline && !FIRST_SPACE.exec(ev.getValue()).find() && !analysis.specialCharacters) {
+                return '|';
+            }
+            return '"';
+            
+        }
+
+        private function processScalar() : void{
+            var ev : ScalarEvent = ScalarEvent(event);
+
+            if(null == analysis) {
+                analysis = Emitter.analyzeScalar(ev.getValue());
+            }
+            if(0 == style) {
+                style = chooseScalarStyle();
+            }
+            var split : Boolean = !simpleKeyContext;
+            if(style == '"') {
+                emitter.writeDoubleQuoted(analysis.scalar,split);
+            } else if(style == '\'') {
+                emitter.writeSingleQuoted(analysis.scalar,split);
+            } else if(style == '>') {
+                emitter.writeFolded(analysis.scalar);
+            } else if(style == '|') {
+                emitter.writeLiteral(analysis.scalar);
+            } else {
+                emitter.writePlain(analysis.scalar,split);
+            }
+            analysis = null;
+            style = 0;
+        }
+    }
+ }
\ No newline at end of file
diff --git a/org/as3yaml/EmitterException.as b/org/as3yaml/EmitterException.as
new file mode 100755 (executable)
index 0000000..2f166e5
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2007 Derek Wischusen
+ * 
+ * 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.
+ */
+
+package org.as3yaml {
+
+public class EmitterException extends YAMLException {
+    public function EmitterException(msg : String) {
+        super(msg);
+    }
+
+}// EmitterException
+}
diff --git a/org/as3yaml/Parser.as b/org/as3yaml/Parser.as
new file mode 100755 (executable)
index 0000000..d9a7730
--- /dev/null
@@ -0,0 +1,718 @@
+/*
+ * Copyright (c) 2007 Derek Wischusen
+ * 
+ * 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.
+ */
+package org.as3yaml {
+
+import flash.utils.getQualifiedClassName;
+
+import org.as3yaml.events.*;
+import org.as3yaml.tokens.*;
+import org.idmedia.as3commons.util.*;
+import org.as3yaml.util.StringUtils;
+
+public class Parser {
+    // Memnonics for the production table
+    private const P_STREAM: int = 0;
+    private const P_STREAM_START: int = 1; // TERMINAL
+    private const P_STREAM_END: int = 2; // TERMINAL
+    private const P_IMPLICIT_DOCUMENT: int = 3;
+    private const P_EXPLICIT_DOCUMENT: int = 4;
+    private const P_DOCUMENT_START: int = 5;
+    private const P_DOCUMENT_START_IMPLICIT: int = 6;
+    private const P_DOCUMENT_END: int = 7;
+    private const P_BLOCK_NODE: int = 8;
+    private const P_BLOCK_CONTENT: int = 9;
+    private const P_PROPERTIES: int = 10;
+    private const P_PROPERTIES_END: int = 11;
+    private const P_FLOW_CONTENT: int = 12;
+    private const P_BLOCK_SEQUENCE: int = 13;
+    private const P_BLOCK_MAPPING: int = 14;
+    private const P_FLOW_SEQUENCE: int = 15;
+    private const P_FLOW_MAPPING: int = 16;
+    private const P_SCALAR: int = 17;
+    private const P_BLOCK_SEQUENCE_ENTRY: int = 18;
+    private const P_BLOCK_MAPPING_ENTRY: int = 19;
+    private const P_BLOCK_MAPPING_ENTRY_VALUE: int = 20;
+    private const P_BLOCK_NODE_OR_INDENTLESS_SEQUENCE: int = 21;
+    private const P_BLOCK_SEQUENCE_START: int = 22;
+    private const P_BLOCK_SEQUENCE_END: int = 23;
+    private const P_BLOCK_MAPPING_START: int = 24;
+    private const P_BLOCK_MAPPING_END: int = 25;
+    private const P_INDENTLESS_BLOCK_SEQUENCE: int = 26;
+    private const P_BLOCK_INDENTLESS_SEQUENCE_START: int = 27;
+    private const P_INDENTLESS_BLOCK_SEQUENCE_ENTRY: int = 28;
+    private const P_BLOCK_INDENTLESS_SEQUENCE_END: int = 29;
+    private const P_FLOW_SEQUENCE_START: int = 30;
+    private const P_FLOW_SEQUENCE_ENTRY: int = 31;
+    private const P_FLOW_SEQUENCE_END: int = 32;
+    private const P_FLOW_MAPPING_START: int = 33;
+    private const P_FLOW_MAPPING_ENTRY: int = 34;
+    private const P_FLOW_MAPPING_END: int = 35;
+    private const P_FLOW_INTERNAL_MAPPING_START: int = 36;
+    private const P_FLOW_INTERNAL_CONTENT: int = 37;
+    private const P_FLOW_INTERNAL_VALUE: int = 38;
+    private const P_FLOW_INTERNAL_MAPPING_END: int = 39;
+    private const P_FLOW_ENTRY_MARKER: int = 40;
+    private const P_FLOW_NODE: int = 41;
+    private const P_FLOW_MAPPING_INTERNAL_CONTENT: int = 42;
+    private const P_FLOW_MAPPING_INTERNAL_VALUE: int = 43;
+    private const P_ALIAS: int = 44;
+    private const P_EMPTY_SCALAR: int = 45;
+
+    private var DOCUMENT_END_TRUE: Event  = new DocumentEndEvent(true);
+    private var DOCUMENT_END_FALSE: Event  = new DocumentEndEvent(false);
+    private var MAPPING_END: Event  = new MappingEndEvent();
+    private var SEQUENCE_END: Event  = new SequenceEndEvent();
+    private var STREAM_END: Event  = new StreamEndEvent();
+    private var STREAM_START: Event  = new StreamStartEvent();
+
+    private const P_TABLE : Array = [];
+
+    private var DEFAULT_TAGS_1_0 : Map = new HashMap();
+    private var DEFAULT_TAGS_1_1 : Map = new HashMap();
+       
+       private var ONLY_WORD : RegExp = new RegExp("^\\w+$");
+
+    private var tags:Array;
+    private var anchors:Array;
+    private var tagHandles:Map;
+    private var yamlVersion:Array;
+    private var defaultYamlVersion:Array;
+
+       
+   public function produce(eventId: int) : Event {
+       
+               switch (eventId)
+               {
+               case P_STREAM:
+                   parseStack.unshift(P_STREAM_END);
+                   parseStack.unshift(P_EXPLICIT_DOCUMENT);
+                   parseStack.unshift(P_IMPLICIT_DOCUMENT);
+                   parseStack.unshift(P_STREAM_START);
+                   return null;
+               
+               case P_STREAM_START:
+                       scanner.getToken();
+                               return STREAM_START;
+                       
+                       case P_STREAM_END:
+                   scanner.getToken();
+                   return STREAM_END;
+                   
+               case P_IMPLICIT_DOCUMENT:
+                   var curr7 : Token = scanner.peekToken();
+                   if(!(curr7 is DirectiveToken || curr7 is DocumentStartToken || curr7 is StreamEndToken)) {
+                       parseStack.unshift(P_DOCUMENT_END);
+                       parseStack.unshift(P_BLOCK_NODE);
+                       parseStack.unshift(P_DOCUMENT_START_IMPLICIT);
+                   }
+                   return null;
+               
+               case P_EXPLICIT_DOCUMENT:
+                   if(!(scanner.peekToken() is StreamEndToken)) {
+                       parseStack.unshift(P_EXPLICIT_DOCUMENT);
+                       parseStack.unshift(P_DOCUMENT_END);
+                       parseStack.unshift(P_BLOCK_NODE);
+                       parseStack.unshift(P_DOCUMENT_START);
+                   }
+                   return null;
+              
+              case P_DOCUMENT_START:
+                   var tok1 : Token = scanner.peekToken();
+                   var directives1 : Array = processDirectives(scanner);
+                   if(!(scanner.peekToken() is DocumentStartToken)) {
+                       throw new ParserException(null,"expected '<document start>', but found " + getQualifiedClassName(tok1),null);
+                   }
+                   scanner.getToken();
+                   return new DocumentStartEvent(true, directives1[0], directives1[1]);
+              
+              case P_DOCUMENT_START_IMPLICIT:
+                var directives2 : Array = processDirectives(scanner);
+                return new DocumentStartEvent(false,directives2[0], directives2[1]);          
+              
+              case P_DOCUMENT_END:
+                   var tok2 : Token = scanner.peekToken();
+                   var explicit : Boolean = false;
+                   while(scanner.peekToken() is DocumentEndToken) {
+                       scanner.getToken();
+                       explicit = true;
+                   }
+                   return explicit ? DOCUMENT_END_TRUE : DOCUMENT_END_FALSE;
+              
+              case P_BLOCK_NODE:
+                var curr8 : Token = scanner.peekToken();
+                if(curr8 is DirectiveToken || curr8 is DocumentStartToken || curr8 is DocumentEndToken || curr8 is StreamEndToken) {
+                    parseStack.unshift(P_EMPTY_SCALAR);
+                } else {
+                    if(curr8 is AliasToken) {
+                        parseStack.unshift(P_ALIAS);
+                    } else {
+                        parseStack.unshift(P_PROPERTIES_END);
+                        parseStack.unshift(P_BLOCK_CONTENT);
+                        parseStack.unshift(P_PROPERTIES);
+                    }
+                }
+                return null;
+           
+           case P_BLOCK_CONTENT:
+                var tok : Token = scanner.peekToken();
+                if(tok is BlockSequenceStartToken) {
+                    parseStack.unshift(P_BLOCK_SEQUENCE);
+                } else if(tok is BlockMappingStartToken) {
+                    parseStack.unshift(P_BLOCK_MAPPING);
+                } else if(tok is FlowSequenceStartToken) {
+                    parseStack.unshift(P_FLOW_SEQUENCE);
+                } else if(tok is FlowMappingStartToken) {
+                    parseStack.unshift(P_FLOW_MAPPING);
+                } else if(tok is ScalarToken) {
+                    parseStack.unshift(P_SCALAR);
+                } else {
+                    return new ScalarEvent(anchors[0],tags[0],[false,false],null,'\'');
+                }
+                return null;
+           
+           case P_PROPERTIES:
+                var anchor : String = null;
+                var tokValue : Array  = null;
+                var tag: String = null;
+                if(scanner.peekToken() is AnchorToken) {
+                    anchor = AnchorToken(scanner.getToken()).getValue();
+                    if(scanner.peekToken() is TagToken) {
+                        scanner.getToken();
+                    }
+                } else if(scanner.peekToken() is TagToken) {
+                    tokValue = TagToken(scanner.getToken()).getValue();
+                    if(scanner.peekToken() is AnchorToken) {
+                        anchor = AnchorToken(scanner.getToken()).getValue();
+                    }
+                }
+                if(tokValue != null) {
+                    var handle : String = tokValue[0];
+                    var suffix : String = tokValue[1];
+                    var ix : int = -1;
+//                    if((ix = suffix.indexOf("^")) != -1) {
+//                        suffix = suffix.substring(0,ix) + suffix.substring(ix+1);
+//                    }
+//                    if(handle != null) {
+//                        if(!env.getTagHandles().containsKey(handle)) {
+//                            throw new ParserException("while parsing a node","found undefined tag handle " + handle,null);
+//                        }
+//                        if((ix = suffix.indexOf("/")) != -1) {
+//                            var before : String = suffix.substring(0,ix);
+//                            var after : String = suffix.substring(ix+1);
+//                            if(ONLY_WORD.exec(before)) {
+//                                tag = "tag:" + before + ".yaml.org,2002:" + after;
+//                            } else {
+//                                if(StringUtils.startsWith(before, "tag:")) {
+//                                    tag = before + ":" + after;
+//                                } else {
+//                                    tag = "tag:" + before + ":" + after;
+//                                }
+//                            }
+//                        } else {
+                            tag = (tagHandles.get(handle)) + suffix;
+//                        }
+                        
+                    } else {
+                        tag = suffix;
+                    }
+
+                anchors.unshift(anchor);
+                tags.unshift(tag);
+                return null;           
+           
+               case P_PROPERTIES_END:
+               anchors.shift();
+                tags.shift();
+                return null;
+                   
+               case P_FLOW_CONTENT:
+                var tok3 : Token = scanner.peekToken();
+                if(tok3 is FlowSequenceStartToken) {
+                    parseStack.unshift(P_FLOW_SEQUENCE);
+                } else if(tok3 is FlowMappingStartToken) {
+                    parseStack.unshift(P_FLOW_MAPPING);
+                } else if(tok3 is ScalarToken) {
+                    parseStack.unshift(P_SCALAR);
+                } else {
+                    throw new ParserException("while scanning a flow node","expected the node content, but found " + getQualifiedClassName(tok3),null);
+                }
+                return null;
+                   
+              case P_BLOCK_SEQUENCE:
+                parseStack.unshift(P_BLOCK_SEQUENCE_END);
+                parseStack.unshift(P_BLOCK_SEQUENCE_ENTRY);
+                parseStack.unshift(P_BLOCK_SEQUENCE_START);
+                return null;
+                   
+              case P_BLOCK_MAPPING:
+                parseStack.unshift(P_BLOCK_MAPPING_END);
+                parseStack.unshift(P_BLOCK_MAPPING_ENTRY);
+                parseStack.unshift(P_BLOCK_MAPPING_START);
+                return null;
+                   
+              case P_FLOW_SEQUENCE:
+                parseStack.unshift(P_FLOW_SEQUENCE_END);
+                parseStack.unshift(P_FLOW_SEQUENCE_ENTRY);
+                parseStack.unshift(P_FLOW_SEQUENCE_START);
+                return null;
+                   
+              case P_FLOW_MAPPING:
+                parseStack.unshift(P_FLOW_MAPPING_END);
+                parseStack.unshift(P_FLOW_MAPPING_ENTRY);
+                parseStack.unshift(P_FLOW_MAPPING_START);
+                return null;
+                   
+              case P_SCALAR:
+                var token : ScalarToken = scanner.getToken() as ScalarToken;
+                var implicit : Array = null;
+                if((token.getPlain() && tags[0] == null) || "!" == (tags[0])) {
+                    implicit = [true,false];
+                } else if(tags[0] == null) {
+                    implicit = [false,true];
+                } else {
+                    implicit = [false,false];
+                }
+                return new ScalarEvent(anchors[0],tags[0],implicit,token.getValue(),token.getStyle());
+                   
+              case P_BLOCK_SEQUENCE_ENTRY:
+                if(scanner.peekToken() is BlockEntryToken) {
+                    scanner.getToken();
+                    var curr1: Token = scanner.peekToken();
+                    if(!(curr1 is BlockEntryToken || curr1 is BlockEndToken)) {
+                        parseStack.unshift(P_BLOCK_SEQUENCE_ENTRY);
+                        parseStack.unshift(P_BLOCK_NODE);
+                    } else {
+                        parseStack.unshift(P_BLOCK_SEQUENCE_ENTRY);
+                        parseStack.unshift(P_EMPTY_SCALAR);
+                    }
+                }
+                return null;
+                   
+              case P_BLOCK_MAPPING_ENTRY:
+                var last : Token = scanner.peekToken();
+                if(last is KeyToken || last is ValueToken) {
+                    if(last is KeyToken) {
+                        scanner.getToken();
+                        var curr2 : Token = scanner.peekToken();
+                        if(!(curr2 is KeyToken || curr2 is ValueToken || curr2 is BlockEndToken)) {
+                            parseStack.unshift(P_BLOCK_MAPPING_ENTRY);
+                            parseStack.unshift(P_BLOCK_MAPPING_ENTRY_VALUE);
+                            parseStack.unshift(P_BLOCK_NODE_OR_INDENTLESS_SEQUENCE);
+                        } else {
+                            parseStack.unshift(P_BLOCK_MAPPING_ENTRY);
+                            parseStack.unshift(P_BLOCK_MAPPING_ENTRY_VALUE);
+                            parseStack.unshift(P_EMPTY_SCALAR);
+                        }
+                    } else {
+                        parseStack.unshift(P_BLOCK_MAPPING_ENTRY);
+                        parseStack.unshift(P_BLOCK_MAPPING_ENTRY_VALUE);
+                        parseStack.unshift(P_EMPTY_SCALAR);
+                    }
+                }
+                return null;
+                   
+              case P_BLOCK_MAPPING_ENTRY_VALUE:
+                var last2: Token = scanner.peekToken();
+                if (last2 is KeyToken || last2 is ValueToken) {
+                    if(last2 is ValueToken) {
+                        scanner.getToken();
+                        var curr3 : Token = scanner.peekToken();
+                        if(!(curr3 is KeyToken || curr3 is ValueToken || curr3 is BlockEndToken)) {
+                            parseStack.unshift(P_BLOCK_NODE_OR_INDENTLESS_SEQUENCE);
+                        } else {
+                            parseStack.unshift(P_EMPTY_SCALAR);
+                        }
+                    } else {
+                        parseStack.unshift(P_EMPTY_SCALAR);
+                    }
+                }
+
+                return null;
+                   
+              case P_BLOCK_NODE_OR_INDENTLESS_SEQUENCE:
+                var last3: Token = scanner.peekToken();
+                if(last3 is AliasToken) {
+                    parseStack.unshift(P_ALIAS);
+                } else {
+                    if(last3 is BlockEntryToken) {
+                        parseStack.unshift(P_INDENTLESS_BLOCK_SEQUENCE);
+                        parseStack.unshift(P_PROPERTIES);
+                    } else {
+                        parseStack.unshift(P_BLOCK_CONTENT);
+                        parseStack.unshift(P_PROPERTIES);
+                    }
+                }
+                return null;
+                   
+              case P_BLOCK_SEQUENCE_START:
+                var impl1 : Boolean = tags[0] == null || tags[0] == "!";
+                scanner.getToken();
+                return new SequenceStartEvent(anchors[0], tags[0], impl1,false);
+                   
+              case P_BLOCK_SEQUENCE_END:
+                var tok4 : Token = null;
+                if(!(scanner.peekToken() is BlockEndToken)) {
+                    tok4 = scanner.peekToken();
+                    throw new ParserException("while scanning a block collection","expected <block end>, but found " + getQualifiedClassName(tok4),null);
+                }
+                scanner.getToken();
+                return SEQUENCE_END;
+                   
+              case P_BLOCK_MAPPING_START:
+                var impl2 : Boolean = tags[0] == null || tags[0] == "!";
+                scanner.getToken();
+                return new MappingStartEvent(anchors[0], tags[0], impl2,false);
+                   
+              case P_BLOCK_MAPPING_END:
+                var tok5 : Token = scanner.peekToken();
+                if(!(tok5 is BlockEndToken)) {
+                    throw new ParserException("while scanning a block mapping","expected <block end>, but found " + getQualifiedClassName(tok5),null);
+                }
+                scanner.getToken();
+                return MAPPING_END;
+                   
+              case P_INDENTLESS_BLOCK_SEQUENCE:
+                parseStack.unshift(P_BLOCK_INDENTLESS_SEQUENCE_END);
+                parseStack.unshift(P_INDENTLESS_BLOCK_SEQUENCE_ENTRY);
+                parseStack.unshift(P_BLOCK_INDENTLESS_SEQUENCE_START);
+                return null;
+                   
+              case P_BLOCK_INDENTLESS_SEQUENCE_START:
+                var impl3 : Boolean = tags[0] == null || tags[0] == "!";
+                return new SequenceStartEvent(anchors[0], tags[0], impl3, false);
+                   
+              case P_INDENTLESS_BLOCK_SEQUENCE_ENTRY:
+                if(scanner.peekToken() is BlockEntryToken) {
+                    scanner.getToken();
+                    var curr4 : Token = scanner.peekToken();
+                    if(!(curr4 is BlockEntryToken || curr4 is KeyToken || curr4 is ValueToken || curr4 is BlockEndToken)) {
+                        parseStack.unshift(P_INDENTLESS_BLOCK_SEQUENCE_ENTRY);
+                        parseStack.unshift(P_BLOCK_NODE);
+                    } else {
+                        parseStack.unshift(P_INDENTLESS_BLOCK_SEQUENCE_ENTRY);
+                        parseStack.unshift(P_EMPTY_SCALAR);
+                    }
+                }
+                return null;
+                   
+              case P_BLOCK_INDENTLESS_SEQUENCE_END:
+                return SEQUENCE_END;
+                   
+              case P_FLOW_SEQUENCE_START:
+                var impl4 : Boolean = tags[0] == null || tags[0] == "!";
+                scanner.getToken();
+                return new SequenceStartEvent(anchors[0], tags[0], impl4,true);
+                   
+              case P_FLOW_SEQUENCE_ENTRY:
+                if(!(scanner.peekToken() is FlowSequenceEndToken)) {
+                    if(scanner.peekToken() is KeyToken) {
+                        parseStack.unshift(P_FLOW_SEQUENCE_ENTRY);
+                        parseStack.unshift(P_FLOW_ENTRY_MARKER);
+                        parseStack.unshift(P_FLOW_INTERNAL_MAPPING_END);
+                        parseStack.unshift(P_FLOW_INTERNAL_VALUE);
+                        parseStack.unshift(P_FLOW_INTERNAL_CONTENT);
+                        parseStack.unshift(P_FLOW_INTERNAL_MAPPING_START);
+                    } else {
+                        parseStack.unshift(P_FLOW_SEQUENCE_ENTRY);
+                        parseStack.unshift(P_FLOW_NODE);
+                        parseStack.unshift(P_FLOW_ENTRY_MARKER);
+                    }
+                }
+                return null;
+                   
+              case P_FLOW_SEQUENCE_END:
+                scanner.getToken();
+                return SEQUENCE_END;
+                   
+              case P_FLOW_MAPPING_START:
+                var impl5 : Boolean = tags[0] == null || tags[0] == "!";
+                scanner.getToken();
+                return new MappingStartEvent(anchors[0], tags[0], impl5,true);
+                   
+              case P_FLOW_MAPPING_ENTRY:
+                if(!(scanner.peekToken() is FlowMappingEndToken)) {
+                    if(scanner.peekToken() is KeyToken) {
+                        parseStack.unshift(P_FLOW_MAPPING_ENTRY);
+                        parseStack.unshift(P_FLOW_ENTRY_MARKER);
+                        parseStack.unshift(P_FLOW_MAPPING_INTERNAL_VALUE);
+                        parseStack.unshift(P_FLOW_MAPPING_INTERNAL_CONTENT);
+                    } else {
+                        parseStack.unshift(P_FLOW_MAPPING_ENTRY);
+                        parseStack.unshift(P_FLOW_NODE);
+                        parseStack.unshift(P_FLOW_ENTRY_MARKER);
+                    }
+                }
+                return null;
+                   
+              case P_FLOW_MAPPING_END:
+                scanner.getToken();
+                return MAPPING_END;
+                   
+              case P_FLOW_INTERNAL_MAPPING_START:
+                scanner.getToken();
+                return new MappingStartEvent(null,null,true,true);
+                   
+              case P_FLOW_INTERNAL_CONTENT:
+                var curr5 : Token = scanner.peekToken();
+                if(!(curr5 is ValueToken || curr5 is FlowEntryToken || curr5 is FlowSequenceEndToken)) {
+                    parseStack.unshift(P_FLOW_NODE);
+                } else {
+                    parseStack.unshift(P_EMPTY_SCALAR);
+                }
+                return null;
+                   
+              case P_FLOW_INTERNAL_VALUE:
+                if(scanner.peekToken() is ValueToken) {
+                    scanner.getToken();
+                    if(!((scanner.peekToken() is FlowEntryToken) || (scanner.peekToken() is FlowSequenceEndToken))) {
+                        parseStack.unshift(P_FLOW_NODE);
+                    } else {
+                        parseStack.unshift(P_EMPTY_SCALAR);
+                    }
+                } else {
+                    parseStack.unshift(P_EMPTY_SCALAR);
+                }
+                return null;
+                   
+              case P_FLOW_INTERNAL_MAPPING_END:
+                return MAPPING_END;
+                   
+              case P_FLOW_ENTRY_MARKER:
+                if(scanner.peekToken() is FlowEntryToken) {
+                    scanner.getToken();
+                }
+                return null;
+                   
+              case P_FLOW_NODE:
+                if(scanner.peekToken() is AliasToken) {
+                    parseStack.unshift(P_ALIAS);
+                } else {
+                    parseStack.unshift(P_PROPERTIES_END);
+                    parseStack.unshift(P_FLOW_CONTENT);
+                    parseStack.unshift(P_PROPERTIES);
+                }
+                return null;
+                   
+              case P_FLOW_MAPPING_INTERNAL_CONTENT:
+                var curr6 : Token = scanner.peekToken();
+                if(!(curr6 is ValueToken || curr6 is FlowEntryToken || curr6 is FlowMappingEndToken)) {
+                    scanner.getToken();
+                    parseStack.unshift(P_FLOW_NODE);
+                } else {
+                    parseStack.unshift(P_EMPTY_SCALAR);
+                }
+                return null;
+                   
+              case P_FLOW_MAPPING_INTERNAL_VALUE:
+                if(scanner.peekToken() is ValueToken) {
+                    scanner.getToken();
+                    if(!(scanner.peekToken() is FlowEntryToken || scanner.peekToken() is FlowMappingEndToken)) {
+                        parseStack.unshift(P_FLOW_NODE);
+                    } else {
+                        parseStack.unshift(P_EMPTY_SCALAR);
+                    }
+                } else {
+                    parseStack.unshift(P_EMPTY_SCALAR);
+                }
+                return null;
+                   
+              case P_ALIAS:
+                var aTok : AliasToken = scanner.getToken() as AliasToken;
+                return new AliasEvent(aTok.getValue());
+                   
+              case P_EMPTY_SCALAR:
+                   return processEmptyScalar();
+            
+                       }
+                       
+               return null;
+                                                                               
+       }
+
+
+    internal static function processEmptyScalar() : Event {
+        return new ScalarEvent(null,null,[true,false],"", '0');
+    }
+
+    private function processDirectives(scanner: Scanner) : Array {
+        while(scanner.peekToken() is DirectiveToken) {
+            var tok : DirectiveToken = DirectiveToken(scanner.getToken());
+            if(tok.getName() == ("YAML")) {
+                if(yamlVersion != null) {
+                    throw new ParserException(null,"found duplicate YAML directive",null);
+                }
+                var major : int = int(tok.getValue()[0]);
+                var minor : int = int(tok.getValue()[1]);
+                if(major != 1) {
+                    throw new ParserException(null,"found incompatible YAML document (version 1.* is required)",null);
+                }
+                yamlVersion = [major,minor];
+            } else if(tok.getName() == ("TAG")) {
+                var handle : String = tok.getValue()[0];
+                var prefix : String = tok.getValue()[1];
+                if(tagHandles.containsKey(handle)) {
+                    throw new ParserException(null,"duplicate tag handle " + handle,null);
+                }
+                tagHandles.put(handle,prefix);
+            }
+        }
+        var value : Array = new Array();
+        value[0] = getFinalYamlVersion();
+
+        if(!tagHandles.isEmpty()) {
+            value[1] = new HashMap().putAll(tagHandles);
+        }
+
+        var baseTags : Map = value[0][1] == 0 ? DEFAULT_TAGS_1_0 : DEFAULT_TAGS_1_1;
+        for(var iter : Iterator = baseTags.keySet().iterator(); iter.hasNext();) {
+            var key : Object = iter.next();
+            if(!tagHandles.containsKey(key)) {
+                tagHandles.put(key,baseTags.get(key));
+            }
+        }
+        return value;
+    }
+
+    private var scanner : Scanner = null;
+    private var cfg : YAMLConfig = null;
+
+    public function Parser(scanner : Scanner, cfg : YAMLConfig) {
+
+        DEFAULT_TAGS_1_0.put("!","tag:yaml.org,2002:");
+               DEFAULT_TAGS_1_0.put("!!","");
+
+        DEFAULT_TAGS_1_1.put("!","!");
+        DEFAULT_TAGS_1_1.put("!!","tag:yaml.org,2002:");        
+        
+        this.scanner = scanner;
+        this.tags = new Array();
+        this.anchors = new Array();
+        this.tagHandles = new HashMap();
+        this.yamlVersion = null;
+        this.defaultYamlVersion = [];
+        this.defaultYamlVersion[0] = int(cfg.getVersion().substring(0,cfg.getVersion().indexOf('.')));
+        this.defaultYamlVersion[1] = int(cfg.getVersion().substring(cfg.getVersion().indexOf('.')+1));
+    }
+
+    public function getFinalYamlVersion() : Array {
+        if(null == this.yamlVersion) {
+            return this.defaultYamlVersion;
+        }
+        return this.yamlVersion;
+    }
+
+    private var currentEvent : Event = null;
+
+    public function checkEvent(choices : Array) : Boolean {
+        parseStream();
+        if(this.currentEvent == null) {
+            this.currentEvent = parseStreamNext();
+        }
+        if(this.currentEvent != null) {
+            if(choices.length == 0) {
+                return true;
+            }
+            for(var i : int = 0; i < choices.length; i++) {
+                if(choices[i] == this.currentEvent) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public function peekEvent() : Event {
+        if (!parseStack) parseStream();
+        if(this.currentEvent == null) {
+            this.currentEvent = parseStreamNext();
+        }
+                       
+        return this.currentEvent;
+    }
+
+    public function getEvent() : Event {
+        parseStream();
+        if(this.currentEvent == null) {
+            this.currentEvent = parseStreamNext();
+        }
+        var value : Event = this.currentEvent;
+        this.currentEvent = null;
+        return value;
+    }
+
+    public function eachEvent(parser : Parser) : EventIterator {
+        return new EventIterator(parser);
+    }
+
+    public function iterator() : EventIterator {
+        return eachEvent(this);
+    }
+
+    private var parseStack : Array = null;
+
+    public function parseStream() : void {
+        if(null == parseStack) {
+            this.parseStack = new Array();
+            this.parseStack.push(P_STREAM);
+        }
+    }
+
+    public function parseStreamNext() : Event {
+        while(parseStack.length > 0) {
+               var eventId : int = parseStack.shift() as int;
+            var value : Event = this.produce(eventId) as Event;
+           
+            if(value) {
+                return value;
+            }
+        }
+
+        return null;
+    }
+
+}
+}
+       import org.as3yaml.Parser;
+       import org.as3yaml.events.Event;
+       
+
+internal class EventIterator {
+   
+   private var parser : Parser;
+   public function EventIterator (parser : Parser) : void{
+       this.parser = parser;
+   }
+   
+    public function hasNext() : Boolean {
+        return null != parser.peekEvent();
+    }
+
+    public function next() : Event {
+        return parser.getEvent();
+    }
+
+    public function remove() : void {
+    }
+}
diff --git a/org/as3yaml/ParserException.as b/org/as3yaml/ParserException.as
new file mode 100755 (executable)
index 0000000..e5d8a09
--- /dev/null
@@ -0,0 +1,52 @@
+/* Copyright (c) 2007 Derek Wischusen
+ *
+ * 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.
+ */
+
+package org.as3yaml {
+       
+public class ParserException extends YAMLException {
+    private var when : String;
+    private var what : String;
+    private var note : String;
+
+    public function ParserException(when : String, what : String, note : String) {
+        super("ParserException " + when + " we had this " + what);
+        this.when = when;
+        this.what = what;
+        this.note = note;
+    }
+    
+    override public function toString() : String {
+        var lines : String = new String();
+        if(this.when != null) {
+            lines += this.when + "\n";
+        }
+        if(this.what != null) {
+            lines+= this.what + "\n";
+        }
+        if(this.note != null) {
+            lines+= this.note + "\n";
+        }
+        //lines += super.toString();
+        
+        return lines;
+    }
+}// ParserException
+}
diff --git a/org/as3yaml/PrivateType.as b/org/as3yaml/PrivateType.as
new file mode 100755 (executable)
index 0000000..6e630bb
--- /dev/null
@@ -0,0 +1,37 @@
+/* Copyright (c) 2007 Derek Wischusen
+ *
+ * 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.
+ */
+
+package org.as3yaml {
+
+public class PrivateType {
+    private var tag : String;
+    public var value : Object;
+
+    public function PrivateType(tag : String, value : Object) : void {
+        this.tag = tag;
+        this.value = value;
+    }
+
+    public function toString() : String {
+        return "#<PrivateType tag: " + tag + " value: " + value + ">";
+    }
+}
+}
\ No newline at end of file
diff --git a/org/as3yaml/Representer.as b/org/as3yaml/Representer.as
new file mode 100755 (executable)
index 0000000..b142bfa
--- /dev/null
@@ -0,0 +1,355 @@
+/*
+ * Copyright (c) 2007 Derek Wischusen
+ * 
+ * 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.
+ */
+
+package org.as3yaml {
+       import flash.utils.ByteArray;
+       import flash.utils.Dictionary;
+       
+       import org.as3yaml.events.*;
+       import org.as3yaml.nodes.*;
+       import org.idmedia.as3commons.util.*;
+
+public class Representer {
+    private var serializer : Serializer;
+    private var defaultStyle : String;
+    private var representedObjects : Map;
+
+    public function Representer(serializer : Serializer, opts : YAMLConfig) : void {
+        this.serializer = serializer;
+        this.defaultStyle = opts.getUseDouble() ? '"' : (opts.getUseSingle() ? '\'' : '0');
+        this.representedObjects = new HashMap();
+    }
+
+    private function representData(data : Object) : Node {
+        var aliasKey : String = null;
+        var node : Node = null;
+
+        if(null != aliasKey) {
+            if(this.representedObjects.containsKey(aliasKey)) {
+                node = this.representedObjects.get(aliasKey) as Node;
+                if(null == node) {
+                    throw new RepresenterException("recursive objects are not allowed: " + data);
+                }
+                return node;
+            }
+            this.representedObjects.put(aliasKey,null);
+        }
+
+        node = getNodeCreatorFor(data).toYamlNode(this);
+
+        if(aliasKey != null) {
+            this.representedObjects.put(aliasKey,node);
+        }
+
+        return node;
+    }
+
+    public function scalar(tag : String, value : String, style : String): Node {
+        return representScalar(tag,value,style);
+    }
+
+    public function representScalar(tag : String, value : String, style : String): Node {
+        var realStyle : String = style == '0' ? this.defaultStyle : style;
+        return new ScalarNode(tag,value,style);
+    }
+
+    public function seq(tag : String, sequence : List, flowStyle : Boolean): Node {
+        return representSequence(tag,sequence,flowStyle);
+    }
+
+    public function representSequence(tag : String, sequence : List, flowStyle : Boolean): Node {
+        var value : Array = new Array();
+        for(var iter : Iterator = sequence.iterator();iter.hasNext();) {
+            value.push(representData(iter.next()));
+        }
+        return new SequenceNode(tag,value,flowStyle);
+    }
+
+    public function map(tag : String, mapping : Object, flowStyle : Boolean) : Node {
+        return representMapping(tag,mapping,flowStyle);
+    }
+
+    public function representMapping(tag : String, mapping : Object, flowStyle : Boolean): Node {
+        var value : HashMap = new HashMap();
+        for(var iter : Iterator = mapping.keySet().iterator();iter.hasNext();) {
+            var itemKey : Object = iter.next();
+            var itemValue : Object = mapping.get(itemKey);
+            value.put(representData(itemKey), representData(itemValue));
+        }
+        return new MappingNode(tag,value,flowStyle);
+    }
+
+    public function represent(data : Object) : void {
+        var node : Node = representData(data);
+        this.serializer.serialize(node);
+        this.representedObjects.clear();
+    }
+
+    protected function ignoreAliases(data : Object) : Boolean {
+        return false;
+    }
+
+    protected function getNodeCreatorFor(data : Object) : YAMLNodeCreator {
+        if(data is YAMLNodeCreator) {
+            return data as YAMLNodeCreator;
+        } else if(data is Map) {
+            return new MappingYAMLNodeCreator(data);
+        } else if(data is Array) {
+            return new ArrayYAMLNodeCreator(data as Array);
+        } else if(data is Date) {
+            return new DateYAMLNodeCreator(data as Date);
+        } else if(data is String) {
+            return new StringYAMLNodeCreator(data);
+        } else if(data is Number) {
+            return new NumberYAMLNodeCreator(data);
+        } else if(data is Boolean) {
+            return new ScalarYAMLNodeCreator("tag:yaml.org,2002:bool",data);
+        } else if(data == null) {
+            return new ScalarYAMLNodeCreator("tag:yaml.org,2002:null","");
+        } else if(data is ByteArray) {
+            return new BinaryYAMLNodeCreator(data);
+        } else { // if none of the above, serialize as an actionscript object
+            return new ActionScriptObjectNodeCreator(data);
+        }
+    }
+
+
+    }
+}
+
+
+import org.as3yaml.YAMLNodeCreator;
+import mx.formatters.DateFormatter;
+import org.idmedia.as3commons.util.Set;
+import org.idmedia.as3commons.util.Map;
+import org.idmedia.as3commons.util.Iterator;
+import org.idmedia.as3commons.util.ArrayList;
+import flash.utils.getQualifiedClassName;
+import org.idmedia.as3commons.util.List;
+import org.as3yaml.nodes.Node;
+import org.as3yaml.Representer;
+import org.idmedia.as3commons.util.HashMap;\r
+import mx.utils.ObjectUtil;\r
+import flash.utils.ByteArray;
+import mx.utils.Base64Encoder;\r
+import flash.utils.Dictionary;
+
+internal class DateYAMLNodeCreator implements YAMLNodeCreator {
+    private var data : Date;
+    public function DateYAMLNodeCreator(data : Date) {
+        this.data = data as Date;
+    }
+
+    public function taguri() : String {
+        return "tag:yaml.org,2002:timestamp";
+    }
+
+    private static var dateOutput : DateFormatter  = new DateFormatter();
+    dateOutput.formatString = "YYYY-MM-DD HH:NN:SS";
+    private static var dateOutputUsec : DateFormatter = new DateFormatter();
+    dateOutputUsec.formatString = "YYYY-MM-DD HH:NN:SS.SSS";
+    public function toYamlNode(representer : Representer) : Node {
+        var date : Date = new Date();
+        
+        var out : String = null;
+        if(data.milliseconds != 0) {
+            out = dateOutputUsec.format(data);
+        } else {
+            out = dateOutput.format(data);
+        }
+        var ts : String = date.toTimeString();
+        var timeZoneOffset : String = ts.substring(ts.indexOf("GMT") + 3);
+        timeZoneOffset = timeZoneOffset.substring(0, timeZoneOffset.length-2) + ":" + timeZoneOffset.substring(timeZoneOffset.length-2);  
+
+        out += " " + timeZoneOffset;
+        return representer.scalar(taguri(), out, "0");
+    }
+}
+
+
+internal class ArrayYAMLNodeCreator implements YAMLNodeCreator {
+    private var data : Array;
+    public function ArrayYAMLNodeCreator(data : Array) {
+        this.data = data;
+    }
+
+    public function taguri() : String {
+        return "tag:yaml.org,2002:seq";
+    }
+
+    public function toYamlNode(representer : Representer) : Node {
+        var l : int = data.length;
+        var lst : ArrayList = new ArrayList();
+        for(var i:int=0;i<l;i++) {
+            lst.add(data[i]);
+        }
+        return representer.seq(taguri(), lst, false);
+    }
+}
+
+internal class NumberYAMLNodeCreator implements YAMLNodeCreator {
+    private var data : Number;
+    public function NumberYAMLNodeCreator(data : Object) {
+        this.data = data as Number;
+    }
+
+    public function taguri() : String {
+        if(data is Number) {
+            return "tag:yaml.org,2002:float";
+        } else {
+            return "tag:yaml.org,2002:int";
+        }
+    }
+
+     public function toYamlNode(representer : Representer) : Node {
+        var str : String = String(data);
+        if(str == ("Infinity")) {
+            str = ".inf";
+        } else if(str == ("-Infinity")) {
+            str = "-.inf";
+        } else if(str == ("NaN")) {
+            str = ".nan";
+        }
+        return representer.scalar(taguri(), str, '0');
+    }
+}
+
+internal class ScalarYAMLNodeCreator implements YAMLNodeCreator {
+    private var tag : String;
+    private var data : Object;
+    public function ScalarYAMLNodeCreator(tag : String, data : Object) {
+        this.tag = tag;
+        this.data = data;
+    }
+
+    public function taguri() : String {
+        return this.tag;
+    }
+
+     public function toYamlNode(representer : Representer) : Node {
+        return representer.scalar(taguri(), data.toString(), '0');
+    }
+}
+
+internal class StringYAMLNodeCreator implements YAMLNodeCreator {
+    private var data : Object;
+    public function StringYAMLNodeCreator(data : Object) {
+        this.data = data;
+    }
+
+    public function taguri() : String {
+        if(data is String) {
+            return "tag:yaml.org,2002:str";
+        } else {
+            return "tag:yaml.org,2002:str:" + getQualifiedClassName(data);
+        }
+    }
+
+     public function toYamlNode(representer : Representer) : Node {
+        return representer.scalar(taguri(), data.toString(), '0');
+    }
+}
+
+internal class SequenceYAMLNodeCreator implements YAMLNodeCreator {
+    private var data : List;
+    public function SequenceYAMLNodeCreator(data : Object) {
+        this.data = data as List;
+    }
+
+    public function taguri() : String {
+        if(data is ArrayList) {
+            return "tag:yaml.org,2002:seq";
+        } else {
+            return "tag:yaml.org,2002:seq:" + getQualifiedClassName(data);
+        }
+    }
+
+     public function toYamlNode(representer : Representer) : Node {
+        return representer.seq(taguri(), data, false);
+    }
+}
+
+internal class MappingYAMLNodeCreator implements YAMLNodeCreator {
+    private var data : Object;
+    public function MappingYAMLNodeCreator(data : Object) {
+        this.data = data as Map;
+    }
+
+    public function taguri() : String {
+        if(data is HashMap) {
+            return "tag:yaml.org,2002:map";
+        } else {
+            return "tag:yaml.org,2002:map:"+getQualifiedClassName(data);
+        }
+    }
+
+     public function toYamlNode(representer : Representer) : Node {
+        return representer.map(taguri(), data, false);
+    }
+}
+
+internal class BinaryYAMLNodeCreator implements YAMLNodeCreator {
+    private var data : ByteArray;
+    public function BinaryYAMLNodeCreator(data : Object) {
+        this.data = data as ByteArray;
+    }
+
+    public function taguri() : String {
+       return "tag:yaml.org,2002:binary";
+    }
+
+     public function toYamlNode(representer : Representer) : Node {
+       var encoder : Base64Encoder = new Base64Encoder();
+       encoder.encodeBytes(data);
+       var base64Data : String = encoder.flush() + '\n';
+        return representer.scalar(taguri(), base64Data, '|');
+    }
+}
+
+internal class ActionScriptObjectNodeCreator implements YAMLNodeCreator {
+    private var data : Object;
+    public function ActionScriptObjectNodeCreator(data : Object) : void {
+        this.data = data;
+    }
+
+    public function taguri() : String {
+        var className : String = getQualifiedClassName(data);
+        className = className.replace("::", ".");
+        return "!actionscript/object:" + className;
+    }
+
+     public function toYamlNode(representer : Representer) : Node {
+        var values : Map = new HashMap();
+        var props : Array = ObjectUtil.getClassInfo(data).properties;
+        for each(var prop : String in props) {
+
+            try {
+                values.put(prop, data[prop]);
+            } catch(exe : Error) {
+                values.put(prop, null);
+            }
+
+            
+        }
+        return representer.map(taguri(),values,false);
+    }
+}
diff --git a/org/as3yaml/RepresenterException.as b/org/as3yaml/RepresenterException.as
new file mode 100755 (executable)
index 0000000..f88d0b6
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2007 Derek Wischusen
+ * 
+ * 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.
+ */
+
+package org.as3yaml {
+
+public class RepresenterException extends YAMLException {
+    public function RepresenterException(msg : String) {
+        super(msg);
+    }
+
+}// RepresenterException
+}
\ No newline at end of file
diff --git a/org/as3yaml/Resolver.as b/org/as3yaml/Resolver.as
new file mode 100755 (executable)
index 0000000..1f58f2a
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2007 Derek Wischusen
+ * 
+ * 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.
+ */
+package org.as3yaml {
+
+import flash.utils.Dictionary;
+
+import org.as3yaml.nodes.*;
+import org.rxr.actionscript.io.StringReader;
+
+public class Resolver {
+    private static var yamlImplicitResolvers : Dictionary = new Dictionary();
+    private static var yamlPathResolvers : Dictionary = new Dictionary();
+
+    private var resolverExactPaths : Array = new Array();
+    private var resolverPrefixPaths : Array = new Array();
+
+    public static function addImplicitResolver(tag : String, regexp : RegExp, first : String) : void {
+        var firstVal : String = (null == first)?"":first;
+        for(var i:int=0,j:int=firstVal.length;i<j;i++) {
+            var theC : String = firstVal.charAt(i);
+            var curr : Array = yamlImplicitResolvers[theC] as Array;
+            if(curr == null) {
+                curr = new Array();
+                yamlImplicitResolvers[theC] = curr;
+            }
+            curr.push([tag,regexp]);
+        }
+    }
+
+//    public static function addPathResolver(tag : String, path : List, kind : Class) : void {
+//        var newPath : Array = new Array();
+//        var nodeCheck : Object = null;
+//        var indexCheck : Object = null;
+//        for(var iter : Iterator = path.iterator();iter.hasNext();) {
+//            var element : Object = iter.next();
+//            if(element is List) {
+//                var eList : List = element as List;
+//                if(eList.size() == 2) {
+//                    nodeCheck = eList.get(0);
+//                    indexCheck = eList.get(1);
+//                } else if(eList.size() == 1) {
+//                    nodeCheck = eList.get(0);
+//                    indexCheck = true;
+//                } else {
+//                    throw new ResolverException("Invalid path element: " + element);
+//                }
+//            } else {
+//                nodeCheck = null;
+//                indexCheck = element;
+//            }
+//
+//            if(nodeCheck is String) {
+//                nodeCheck = ScalarNode;
+//            } else if(nodeCheck is List) {
+//                nodeCheck = SequenceNode;
+//            } else if(nodeCheck is Map) {
+//                nodeCheck = MappingNode;
+//            } else if(null != nodeCheck && !ScalarNode == (nodeCheck) && !SequenceNode == (nodeCheck) && !MappingNode == (nodeCheck)) {
+//                throw new ResolverException("Invalid node checker: " + nodeCheck);
+//            }
+//            if(!(indexCheck is String || indexCheck is int) && null != indexCheck) {
+//                throw new ResolverException("Invalid index checker: " + indexCheck);
+//            }
+//            newPath.push([nodeCheck,indexCheck]);
+//        }
+//        var newKind : Class = null;
+//        if(String == kind) {
+//            newKind = ScalarNode;
+//        } else if(List == kind) {
+//            newKind = SequenceNode;
+//        } else if(Map == kind) {
+//            newKind = MappingNode;
+//        } else if(kind != null && !ScalarNode == kind && !SequenceNode == kind && !MappingNode == kind) {
+//            throw new ResolverException("Invalid node kind: " + kind);
+//        } else {
+//            newKind = kind;
+//        }
+//        var x : Array = new Array();
+//        x.push(newPath);
+//        var y : Array = new Array();
+//        y.push(x);
+//        y.push(kind);
+//        yamlPathResolvers[y] = tag;
+//    }
+
+    public function descendResolver(currentNode : Node, currentIndex : Object) : void {
+        var exactPaths : Dictionary = new Dictionary();
+        var prefixPaths : Array = new Array();
+               var path : Array;
+        if(null != currentNode) {
+            var depth : int = resolverPrefixPaths.length;
+            for(var xi:int=0; xi < resolverPrefixPaths[0].length; xi++) {
+                var obj : Array = resolverPrefixPaths[0][xi] as Array;
+                path = obj[0] as Array;
+                if(checkResolverPrefix(depth,path, obj[1],currentNode,currentIndex)) {
+                    if(path.size() > depth) {
+                        prefixPaths.push([path,obj[1]]);
+                    } else {
+                        var resPath : Array = new Array();
+                        resPath.push(path);
+                        resPath.push(obj[1]);
+                        exactPaths[obj[1]] = yamlPathResolvers[resPath];
+                    }
+                }
+            }
+        } else {
+            for(var keyObj : Object in yamlPathResolvers) {
+                var key : Array = keyObj as Array;
+                path = key[0] as Array;
+                var kind : Class = key[1] as Class;
+                if(null == path) {
+                    exactPaths[kind] = yamlPathResolvers[key];
+                } else {
+                    prefixPaths.push(key);
+                }
+            }
+        }
+        resolverExactPaths.unshift(exactPaths);
+        resolverPrefixPaths.unshift(prefixPaths);
+    }
+
+    public function ascendResolver() : void {
+        resolverExactPaths.shift();
+        resolverPrefixPaths.shift();
+    }
+
+    public function checkResolverPrefix(depth : int, path : Array, kind : Class, currentNode : Node, currentIndex : Object) : Boolean {
+        var check : Array = path[depth-1];
+        var nodeCheck : Object = check[0];
+        var indexCheck : Object = check[1];
+        if(nodeCheck is String) {
+            if(!currentNode.getTag() == (nodeCheck)) {
+                return false;
+            }
+        } else if(null != nodeCheck) {
+            if(!(nodeCheck).isInstance(currentNode)) {
+                return false;
+            }
+        }
+        if(indexCheck == true && currentIndex != null) {
+            return false;
+        }
+        if(indexCheck == true && currentIndex == null) {
+            return false;
+        }
+        if(indexCheck is String) {
+            if(!(currentIndex is ScalarNode && indexCheck == ((ScalarNode(currentIndex)).getValue()))) {
+                return false;
+            }
+        } else if(indexCheck is int) {
+            if(!currentIndex == (indexCheck)) {
+                return false;
+            }
+        }
+        return true;
+    }
+    
+    public function resolve(kind : Class, value : String, implicit : Array) : String {
+        var resolvers : Array = null;
+        if(kind == ScalarNode && implicit[0]) {
+            if("" == (value)) {
+                resolvers = yamlImplicitResolvers[""] as Array;
+            } else {
+                resolvers = yamlImplicitResolvers[value.charAt(0)] as Array;
+            }
+            if(resolvers == null) {
+                resolvers = new Array();
+            }
+            if(yamlImplicitResolvers[null]) {
+                resolvers.concat(yamlImplicitResolvers[null]);
+            }
+            for(var xi:int=0; xi < resolvers.length; xi++) {
+                var val : Array = resolvers[xi];
+                if((RegExp(val[1])).exec(value)) {
+                    return val[0] as String;
+                }
+            }
+        }
+        var exactPaths : Dictionary = resolverExactPaths[0] as Dictionary;
+        if(exactPaths[kind]) {
+            return exactPaths[kind] as String;
+        }
+        if(exactPaths[null]) {
+            return exactPaths[null] as String;
+        }
+        if(kind == ScalarNode) {
+            return YAML.DEFAULT_SCALAR_TAG;
+        } else if(kind == SequenceNode) {
+            return YAML.DEFAULT_SEQUENCE_TAG;
+        } else if(kind == MappingNode) {
+            return YAML.DEFAULT_MAPPING_TAG;
+        }
+        return null;
+    } 
+
+    static: {
+        addImplicitResolver("tag:yaml.org,2002:bool",new RegExp("^(?:yes|Yes|YES|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF)$"),"yYnNtTfFoO");
+        addImplicitResolver("tag:yaml.org,2002:float",new RegExp("^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?|[-+]?(?:[0-9][0-9_]*)?\\.[0-9_]+(?:[eE][-+][0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"),"-+0123456789.");
+        addImplicitResolver("tag:yaml.org,2002:int",new RegExp("^(?:[-+]?0b[0-1_]+|[-+]?0[0-7_]+|[-+]?(?:0|[1-9][0-9_]*)|[-+]?0x[0-9a-fA-F_]+|[-+]?[1-9][0-9_]*(?::[0-5]?[0-9])+)$"),"-+0123456789");
+        addImplicitResolver("tag:yaml.org,2002:merge",new RegExp("^(?:<<)$"),"<");
+        addImplicitResolver("tag:yaml.org,2002:null",new RegExp("^(?:~|null|Null|NULL| )$"),"~nN\x00");
+        addImplicitResolver("tag:yaml.org,2002:timestamp",new RegExp("^(?:[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]|[0-9][0-9][0-9][0-9]-[0-9][0-9]?-[0-9][0-9]?(?:[Tt]|[ \t]+)[0-9][0-9]?:[0-9][0-9]:[0-9][0-9](?:\\.[0-9]*)?(?:[ \t]*(?:Z|[-+][0-9][0-9]?(?::[0-9][0-9])?))?)$"),"0123456789");
+        addImplicitResolver("tag:yaml.org,2002:value",new RegExp("^(?:=)$"),"=");
+      // The following implicit resolver is only for documentation purposes. It cannot work
+      // because plain scalars cannot start with '!', '&', or '*'.
+        addImplicitResolver("tag:yaml.org,2002:yaml",new RegExp("^(?:!|&|\\*)$"),"!&*");
+    }
+}
+}
\ No newline at end of file
diff --git a/org/as3yaml/ResolverException.as b/org/as3yaml/ResolverException.as
new file mode 100755 (executable)
index 0000000..f54aa62
--- /dev/null
@@ -0,0 +1,29 @@
+/* Copyright (c) 2007 Derek Wischusen
+ *
+ * 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.
+ */
+
+package org.as3yaml {
+       
+public class ResolverException extends YAMLException {
+    public function ResolverException(msg : String) {
+        super(msg);
+    }
+}// ResolverException
+}
\ No newline at end of file
diff --git a/org/as3yaml/SafeConstructor.as b/org/as3yaml/SafeConstructor.as
new file mode 100755 (executable)
index 0000000..6074875
--- /dev/null
@@ -0,0 +1,420 @@
+/* Copyright (c) 2007 Derek Wischusen
+ *
+ * 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.
+ */
+
+package org.as3yaml {
+
+import flash.utils.Dictionary;
+import flash.utils.getDefinitionByName;
+import flash.utils.getQualifiedClassName;
+
+import mx.utils.Base64Decoder;
+import mx.utils.ObjectUtil;
+
+import org.as3yaml.nodes.Node;
+import org.idmedia.as3commons.util.ArrayList;
+import org.idmedia.as3commons.util.Collection;
+import org.idmedia.as3commons.util.HashMap;
+import org.idmedia.as3commons.util.Map;
+import org.as3yaml.util.StringUtils;
+
+public class SafeConstructor extends BaseConstructor {
+    private static var yamlConstructors : Dictionary = new Dictionary();
+    private static var yamlMultiConstructors : Dictionary = new Dictionary();
+    private static var yamlMultiRegexps : Map = new HashMap();
+   
+    override public function getYamlConstructor(key:Object) : Function {
+       
+        var ctor : Function = yamlConstructors[key];
+        
+        if(ctor == null) {
+          ctor = super.getYamlConstructor(key);
+        }   
+        return ctor;
+    }
+
+    override public function getYamlMultiConstructor(key : Object) : Function {
+        
+        var ctor : Function = yamlMultiConstructors[key];
+        
+        if(ctor == null) {
+         ctor = super.getYamlMultiConstructor(key);
+        } 
+           
+        return ctor;
+    }
+
+    override public function getYamlMultiRegexp(key : Object) : RegExp {
+        var mine : RegExp = yamlMultiRegexps.get(key);
+        if(mine == null) {
+            mine = super.getYamlMultiRegexp(key);
+        }
+        return mine;
+    }
+
+    override public function getYamlMultiRegexps() : Map {
+        var all : Map = new HashMap();
+        all.putAll(super.getYamlMultiRegexps());
+        all.putAll(yamlMultiRegexps);
+        return all;
+    }
+
+    public static function addConstructor(tag : String, ctor : Function) : void {
+        yamlConstructors[tag] = ctor;
+    }
+
+    public static function addMultiConstructor(tagPrefix : String, ctor : Function) : void {
+        yamlMultiConstructors[tagPrefix] = ctor;
+        yamlMultiRegexps.put(tagPrefix, new RegExp("^"+tagPrefix));
+    }
+
+    public function SafeConstructor(composer : Composer) {
+        super(composer);
+    }
+
+    private static var BOOL_VALUES : Object = {
+                                                                                       yes     : true,
+                                                                                       no      : false,
+                                                                                       "true"  : true,
+                                                                                       "false" : false,
+                                                                                       on      : true,
+                                                                                       off     : false
+                                                                                 };
+
+    public static function constructYamlNull(ctor : Constructor, node : Node) : Object {
+        return null;
+    }
+    
+    public static function constructYamlBool(ctor : Constructor, node : Node) : Object {
+        var val : String = ctor.constructScalar(node) as String;
+        return BOOL_VALUES[val.toLowerCase()];
+    }
+
+    public static function constructYamlOmap(ctor : Constructor, node : Node) : Object {
+        return ctor.constructOmap(node);
+    }
+
+    public static function constructYamlPairs(ctor : Constructor, node : Node) : Object {
+        return ctor.constructPairs(node); 
+    }
+
+    public static function constructYamlSet(ctor : Constructor, node : Node) : Object {
+        return Map(ctor.constructMapping(node)).keySet();
+    }
+
+    public static function constructYamlStr(ctor : Constructor, node : Node) : Object {
+        var value : String = ctor.constructScalar(node) as String;
+        return value.length == 0 ? null : value;
+    }
+
+    public static function constructYamlSeq(ctor : Constructor, node : Node) : Object {
+        return ctor.constructSequence(node);
+    }
+
+    public static function constructYamlMap(ctor : Constructor, node : Node) : Object {
+        return ctor.constructMapping(node);
+    }
+
+    public static function constructUndefined(ctor : Constructor, node : Node) : Object {
+        throw new ConstructorException(null,"could not determine a constructor for the tag " + node.getTag(),null);
+    }
+
+    private static var TIMESTAMP_REGEXP : RegExp = new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:(?:[Tt]|[ \t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \t]*(?:Z|([-+][0-9][0-9]?)(?::([0-9][0-9])?)?))?)?$");
+    private static var YMD_REGEXP : RegExp = new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)$");
+    public static function constructYamlTimestamp(ctor : Constructor, node : Node) : Object {
+        var match : Object = YMD_REGEXP.exec(String(node.getValue()));
+
+        var year_s : String;
+        var month_s : String;
+        var day_s : String;
+        var time : Date = null;
+       
+        if(match) {
+            year_s = match[1];
+            month_s = match[2];
+            day_s = match[3];
+            
+            if(year_s == null || month_s == null || day_s == null) {
+               throw new ConstructorException(null, "bad date value: " + node.getValue(), null);
+            }
+
+            return new Date(year_s,int(month_s)-1,day_s);
+        }
+        match = TIMESTAMP_REGEXP.exec(String(node.getValue()));
+        if(!match) {
+            return ctor.constructPrivateType(node);
+        }
+        
+        year_s = match[1];
+        month_s = match[2];
+        day_s = match[3];
+        
+        var hour_s: String = match[4];
+        var min_s: String = match[5];
+        var sec_s: String = match[6];
+        var fract_s: String = match[7];
+        var timezoneh_s: String = match[8];
+        var timezonem_s: String = match[9];
+        
+        var usec : int = 0;
+        if(fract_s != null) {
+            usec = int(fract_s);
+            if(usec != 0) {
+                while(10*usec < 1000) {
+                    usec *= 10;
+                }
+            }
+        }
+        
+        time = new Date();
+        
+        if(month_s != null && day_s != null) {
+            time.setMonth(int(month_s)-1, day_s);
+        }      
+        if(year_s != null) {
+            time.setFullYear(year_s);
+        }
+        if(hour_s != null) {
+            time.setHours(hour_s);
+        }
+        if(min_s != null) {
+            time.setMinutes(min_s);
+        }
+        if(sec_s != null) {
+            time.setSeconds(sec_s);
+        }
+        time.setMilliseconds(usec);
+        if(timezoneh_s != null || timezonem_s != null) {
+            var zone : int = 0;
+            var sign : int = 1;
+            if(timezoneh_s != null) {
+                if(timezoneh_s.charAt(0) == ("-")) {
+                    sign = -1;
+                }
+                zone += int(timezoneh_s.substring(1))*3600000;
+            }
+            if(timezonem_s != null) {
+                zone += int(timezonem_s)*60000;
+            }
+        }
+        return time;
+    }
+
+    public static function constructYamlInt(ctor : Constructor, node : Node) : Object {
+        var value : String = String(ctor.constructScalar(node)).replace(/_/g,"");
+        var sign : int = +1;
+        var first : String = value.charAt(0);
+        if(first == '-') {
+            sign = -1;
+            value = value.substring(1);
+        } else if(first == '+') {
+            value = value.substring(1);
+        }
+        var base : int = 10;
+        if(value == ("0")) {
+            return 0;
+        } else if(StringUtils.startsWith(value, "0b")) {
+            value = value.substring(2);
+            base = 2;
+        } else if(StringUtils.startsWith(value, "0x")) {
+            value = value.substring(2);
+            base = 16;
+        } else if(value.charAt(0) == ("0")) {
+            value = value.substring(1);
+            base = 8;
+        } else if(value.indexOf(':') != -1) {
+            var digits : Array = value.split(":");
+            var bes : int = 1;
+            var val : int = 0;
+            for(var i:int=0,j:int=digits.length;i<j;i++) {
+                val += (Number(digits[(j-i)-1])*bes);
+                bes *= 60;
+            }
+            return new int(sign*val);
+        } else {
+            return sign * parseInt(value, base);//new Number(sign * int(value));
+        }
+        return (sign * parseInt(value, base));
+    }
+
+    private static var INF_VALUE_POS : Number  = new Number(Number.POSITIVE_INFINITY);
+    private static var INF_VALUE_NEG : Number = new Number(Number.NEGATIVE_INFINITY);
+    private static var NAN_VALUE : Number = new Number(Number.NaN);
+
+    public static function constructYamlFloat(ctor : Constructor, node : Node) : Object {
+        var value : String = String(ctor.constructScalar(node).toString()).replace(/'_'/g,"");
+        var sign : int = +1;
+        var first : String = value.charAt(0);
+        if(first == '-') {
+            sign = -1;
+            value = value.substring(1);
+        } else if(first == '+') {
+            value = value.substring(1);
+        }
+        var valLower : String = value.toLowerCase();
+        if(valLower == (".inf")) {
+            return sign == -1 ? INF_VALUE_NEG : INF_VALUE_POS;
+        } else if(valLower == (".nan")) {
+            return NAN_VALUE;
+        } else if(value.indexOf(':') != -1) {
+            var digits : Array = value.split(":");
+            var bes : int = 1;
+            var val : Number = 0.0;
+            for(var i:int=0,j:int=digits.length;i<j;i++) {
+                val += (Number(digits[(j-i)-1])*bes);
+                bes *= 60;
+            }
+            return new Number(sign*val);
+        } else {
+            return Number(value) * sign;
+        }
+    }    
+
+    public static function constructYamlBinary(ctor : Constructor, node : Node) : Object {
+        var values : Array = ctor.constructScalar(node).toString().split("[\n\u0085]|(?:\r[^\n])");
+        var vals : String = new String();
+        for(var i:int=0,j:int=values.length;i<j;i++) {
+            vals += (values[i]);
+        }
+        var decoder : Base64Decoder = new Base64Decoder();
+        decoder.decode(vals);
+        return decoder.flush();
+    }
+
+    public static function constructSpecializedSequence(ctor : Constructor, pref : String, node : Node) : Object {
+        var outp : ArrayList = null;
+        try {
+            var seqClass : Object = getDefinitionByName(pref) as Class;
+            outp = new seqClass() as ArrayList;
+        } catch(e : Error) {
+            throw new YAMLException("Can't construct a sequence from class " + pref + ": " + e.toString());
+        }
+        var coll : Collection = ctor.constructSequence(node) as Collection;
+        outp.addAll(coll);
+        return outp;
+    }
+
+    public static function constructSpecializedMap(ctor : Constructor, pref : String, node : Node) : Object {
+        var outp : Map = null;
+        try {
+            var mapClass : Class = getDefinitionByName(pref) as Class;
+            outp = new mapClass();
+        } catch(e : Error) {
+            throw new YAMLException("Can't construct a mapping from class " + pref + ": " + e.toString());
+        }
+        var coll : Map = ctor.constructMapping(node) as Map;
+        outp.putAll(coll);
+        return outp;
+    }
+
+    private static function fixValue(inp : Object, outp : Class) : Object {
+        if(inp == null) {
+            return null;
+        }
+        var inClass : Class = getDefinitionByName(getQualifiedClassName(inp)) as Class;
+        if(outp is inClass) {
+            return inp;
+        }
+        if(inClass == Number && (outp == int)) {
+            return new int(inp);
+        }
+
+        if(inClass == Number && (outp == String)) {
+            return new String(inp);
+        }
+
+        return inp;
+    }
+
+    public static function constructActionscript(ctor : Constructor, pref : String, node : Node) : Object {
+        var outp : Object = null;
+        try {
+            var cl : Class = getDefinitionByName(pref) as Class;
+            outp = new cl();
+            var values : Dictionary = Dictionary(ctor.constructMapping(node));
+            var props : Array = ObjectUtil.getClassInfo(outp).properties;
+            for(var key : Object in values) {
+                var value : Object = values[key];
+                               outp[key] = value;
+            } 
+        } catch(e : Error) {
+            throw new YAMLException("Can't construct actionscript object from class " + pref + ": " + e.toString());
+        }
+        return outp;
+    }
+
+    static: {
+        BaseConstructor.addConstructor("tag:yaml.org,2002:null", function call(self : Constructor, node : Node) : Object {
+                    return constructYamlNull(self,node);
+            });
+        addConstructor("tag:yaml.org,2002:bool", function call(self : Constructor, node : Node) : Object {
+                    return constructYamlBool(self,node);
+            });
+        addConstructor("tag:yaml.org,2002:omap", function call(self : Constructor, node : Node) : Object {
+                    return constructYamlOmap(self,node);
+            });
+        addConstructor("tag:yaml.org,2002:pairs", function call(self : Constructor, node : Node) : Object {
+                    return constructYamlPairs(self,node);
+            });
+        addConstructor("tag:yaml.org,2002:set", function call(self : Constructor, node : Node) : Object {
+                    return constructYamlSet(self,node);
+            });
+        addConstructor("tag:yaml.org,2002:int", function call(self : Constructor, node : Node) : Object {
+                    return constructYamlInt(self,node);
+            });
+        addConstructor("tag:yaml.org,2002:float", function call(self : Constructor, node : Node) : Object {
+                    return constructYamlFloat(self,node); 
+            });
+        addConstructor("tag:yaml.org,2002:timestamp", function call(self : Constructor, node : Node) : Object {
+                    return constructYamlTimestamp(self,node);
+            });
+        addConstructor("tag:yaml.org,2002:timestamp#ymd", function call(self : Constructor, node : Node) : Object {
+                    return constructYamlTimestamp(self,node);
+            });
+        addConstructor("tag:yaml.org,2002:str", function call(self : Constructor, node : Node) : Object {
+                    return constructYamlStr(self,node);
+            });
+        addConstructor("tag:yaml.org,2002:binary", function call(self : Constructor, node : Node) : Object {
+                    return constructYamlBinary(self,node);
+            });
+        addConstructor("tag:yaml.org,2002:seq", function call(self : Constructor, node : Node) : Object {
+                    return constructYamlSeq(self,node);
+            });
+        addConstructor("tag:yaml.org,2002:map", function call(self : Constructor, node : Node) : Object {
+                    return constructYamlMap(self,node);
+            });
+        addConstructor(null, function call(self : Constructor, node : Node) : Object {
+                    return self.constructPrivateType(node);
+            });
+
+        addMultiConstructor("tag:yaml.org,2002:seq:", function call(self : Constructor, pref : String, node : Node) : Object {
+                    return constructSpecializedSequence(self,pref,node);
+            });
+        addMultiConstructor("tag:yaml.org,2002:map:", function call(self : Constructor, pref : String, node : Node) : Object {
+                    return constructSpecializedMap(self,pref,node);
+            });
+        addMultiConstructor("!actionscript/object:", function call(self : Constructor, pref : String, node : Node) : Object {
+                    return constructActionscript(self,pref,node);
+           });
+    }
+
+}
+}
\ No newline at end of file
diff --git a/org/as3yaml/ScalarAnalysis.as b/org/as3yaml/ScalarAnalysis.as
new file mode 100755 (executable)
index 0000000..76f4f45
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2007 Derek Wischusen
+ * 
+ * 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.
+ */
+
+package org.as3yaml
+{
+   internal class ScalarAnalysis {
+        public var scalar : String;
+        public var empty : Boolean;
+        public var multiline : Boolean;
+        public var allowFlowPlain : Boolean;
+        public var allowBlockPlain : Boolean;
+        public var allowSingleQuoted : Boolean;
+        public var allowDoubleQuoted : Boolean;
+        public var allowBlock : Boolean;
+        public var specialCharacters : Boolean;
+        public function ScalarAnalysis(scalar : String, empty : Boolean, multiline : Boolean, allowFlowPlain : Boolean, allowBlockPlain : Boolean, allowSingleQuoted : Boolean, allowDoubleQuoted : Boolean, allowBlock : Boolean, specialCharacters : Boolean) {
+            this.scalar = scalar;
+            this.empty = empty;
+            this.multiline = multiline;
+            this.allowFlowPlain = allowFlowPlain;
+            this.allowBlockPlain = allowBlockPlain;
+            this.allowSingleQuoted = allowSingleQuoted;
+            this.allowDoubleQuoted = allowDoubleQuoted;
+            this.allowBlock = allowBlock;
+            this.specialCharacters = specialCharacters;
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/org/as3yaml/Scanner.as b/org/as3yaml/Scanner.as
new file mode 100755 (executable)
index 0000000..08bfb8b
--- /dev/null
@@ -0,0 +1,1176 @@
+/*
+ * Copyright (c) 2007 Derek Wischusen
+ * 
+ * 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.
+ */
+
+
+package org.as3yaml {
+       import org.as3yaml.tokens.*;
+       import org.as3yaml.util.StringUtils;
+       import org.idmedia.as3commons.util.Iterator;
+       import org.rxr.actionscript.io.StringReader;
+
+       
+
+
+public class Scanner {
+    private const LINEBR : String = "\n\u0085\u2028\u2029";
+    private const NULL_BL_LINEBR : String = "\x00 \r\n\u0085";
+    private const NULL_BL_T_LINEBR : String = "\x00 \t\r\n\u0085";
+    private const NULL_OR_OTHER : String = NULL_BL_T_LINEBR;
+    private const NULL_OR_LINEBR : String = "\x00\r\n\u0085";
+    private const FULL_LINEBR : String = "\r\n\u0085";
+    private const BLANK_OR_LINEBR : String = " \r\n\u0085";
+    private const S4 : String = "\0 \t\r\n\u0028[]{}";    
+    private const ALPHA : String = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
+    private const STRANGE_CHAR : String = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789][-';/?:@&=+$,.!~*()%";
+    private const RN : String = "\r\n";
+    private const BLANK_T : String = " \t";
+    private const SPACES_AND_STUFF : String = "'\"\\\x00 \t\r\n\u0085";
+    private const DOUBLE_ESC : String = "\"\\";
+    private const NON_ALPHA_OR_NUM : String = "\x00 \t\r\n\u0085?:,]}%@`";
+    private const NON_PRINTABLE : RegExp = new RegExp("[^\x09\x0A\x0D\x20-\x7E\x85\xA0-\uD7FF\uE000-\uFFFD]");
+    private const NOT_HEXA : RegExp = new RegExp("[^0-9A-Fa-f]");
+    private const NON_ALPHA : RegExp = new RegExp("[^-0-9A-Za-z_]");
+    private const R_FLOWZERO : RegExp = new RegExp(/[\x00 \t\r\n\u0085]|(:[\x00 \t\r\n\u0028])/);
+    private const R_FLOWNONZERO : RegExp = new RegExp(/[\x00 \t\r\n\u0085\\\[\\\]{},:?]/);
+    private const LINE_BR_REG : RegExp = new RegExp("[\n\u0085]|(?:\r[^\n])");
+    private const END_OR_START : RegExp = new RegExp("^(---|\\.\\.\\.)[\0 \t\r\n\u0085]$");
+    private const ENDING : RegExp = new RegExp("^---[\0 \t\r\n\u0085]$");
+    private const START : RegExp = new RegExp("^\\.\\.\\.[\x00 \t\r\n\u0085]$");
+    private const BEG : RegExp = new RegExp(/^([^\x00 \t\r\n\u0085\\\-?:,\\[\\\]{}#&*!|>'\"%@]|([\\\-?:][^\x00 \t\r\n\u0085]))/);
+
+    private var ESCAPE_REPLACEMENTS : Object = new Object();
+    private var ESCAPE_CODES : Object = new Object();
+
+       private function initEscapes(): void { 
+        ESCAPE_REPLACEMENTS['0'] = "\x00";
+        ESCAPE_REPLACEMENTS['a'] = "\u0007";
+        ESCAPE_REPLACEMENTS['b'] = "\u0008";
+        ESCAPE_REPLACEMENTS['t'] = "\u0009";
+        ESCAPE_REPLACEMENTS['\t'] = "\u0009";
+        ESCAPE_REPLACEMENTS['n'] = "\n";
+        ESCAPE_REPLACEMENTS['v'] = "\u000B";
+        ESCAPE_REPLACEMENTS['f'] = "\u000C";
+        ESCAPE_REPLACEMENTS['r'] = "\r";
+        ESCAPE_REPLACEMENTS['e'] = "\u001B";
+        ESCAPE_REPLACEMENTS[' '] = "\u0020";
+        ESCAPE_REPLACEMENTS['"'] = "\"";
+        ESCAPE_REPLACEMENTS['\\'] = "\\";
+        ESCAPE_REPLACEMENTS['N'] = "\u0085";
+        ESCAPE_REPLACEMENTS['_'] = "\u00A0";
+        ESCAPE_REPLACEMENTS['L'] = "\u2028";
+        ESCAPE_REPLACEMENTS['P'] = "\u2029";
+
+        ESCAPE_CODES['x'] = 2;
+        ESCAPE_CODES['u'] = 4;
+        ESCAPE_CODES['U'] = 8;
+    }
+
+    private var done : Boolean = false;
+    private var flowLevel : int = 0;
+    private var tokensTaken : int = 0;
+    private var indent : int = -1;
+    private var allowSimpleKey : Boolean = true;
+    private var eof : Boolean = true;
+    private var column : int = 0;
+    private var buffer : StringReader;
+    private var tokens : Array;
+    private var indents : Array;
+    private var possibleSimpleKeys : Object;
+
+    private var docStart : Boolean = false;
+
+    public function Scanner(stream : String) {
+       initEscapes();
+        this.buffer = new StringReader(stream);
+        this.tokens = new Array();
+        this.indents = new Array();
+        this.possibleSimpleKeys = new Object();
+        checkPrintable(stream);
+        buffer.writeChar('\x00');
+        fetchStreamStart();
+    }
+
+    public function checkToken(choices : Array) : Boolean {
+//        while(needMoreTokens()) {
+//            fetchMoreTokens();
+//        }
+        if(this.tokens.length > 0) {
+            if(choices.length == 0) {
+                return true;
+            }
+           var first : Class = this.tokens.get(0) as Class;
+           var len: int = choices.length;
+            for (var i : int = 0; i < len; i++) {
+                if(choices[i] is first) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public function peekToken() : Token {
+        while(needMoreTokens()) {
+            fetchMoreTokens();
+        }
+        return Token(this.tokens.length == 0 ? null : this.tokens[0]);
+    }
+
+    public function getToken() : Token {
+
+        if(this.tokens.length > 0) {
+            this.tokensTaken++;
+            return this.tokens.shift() as Token;
+            
+        }
+        return null;
+    }
+
+    public function eachToken(scanner : Scanner) : Iterator  {
+        return new TokenIterator(scanner);
+    }
+
+    public function iterator(scanner : Scanner) : Iterator{
+        return eachToken(scanner);
+    }
+
+    private function peek(offset : int = 0) : String {
+        return buffer.peek(offset);
+    }
+
+    private function prefix(length : int, offset: int = 0) : String {
+        if(length > buffer.charsAvailable) {
+            return buffer.peekRemaining()
+        } else {
+            return buffer.peekFor(length, offset);
+        }
+    }
+
+    private function prefixForward(length : int) : String {
+        var buff : String = null;
+        if(length > buffer.charsAvailable) {
+            buff = buffer.readRemaining()();
+        } else {
+            buff = buffer.readFor(length);
+        }
+        var ch : String;
+        var j:int = buff.length;
+        for(var i:int=0; i<j; i++) {
+            ch = buff.charAt(i);
+            if(LINEBR.indexOf(ch) != -1 || (ch == '\r' && buff.charAt(i+1) != '\n')) {
+                this.column = 0;
+            } else if(ch != '\uFEFF') {
+                this.column++;
+            }
+        }
+        return buff;
+    }
+
+    private function forward(char: String=null) : void {
+        const ch1 : String =  char ? char : buffer.peek();
+        buffer.forward();
+        if(ch1 == '\n' || ch1 == '\u0085' || (ch1 == '\r' && buffer.peek() != '\n')) {
+            this.column = 0;
+        } else {
+            this.column++;
+        }
+    }
+    
+    private function forwardBy(length : int) : void {
+        var ch : String;
+        for(var i:int=0;i<length;i++) {
+            ch = buffer.read();
+            if(LINEBR.indexOf(ch) != -1 || (ch == '\r' && buffer.peek() != '\n')) {
+                this.possibleSimpleKeys = new Object();
+                this.column = 0;
+            } else if(ch != '\uFEFF') {
+                this.column++;
+            }
+        }
+    }
+
+    private function checkPrintable(data : String) : void {
+        var match : Object = NON_PRINTABLE.exec(data);
+        if(match) {
+            throw new YAMLException("At " + match.index + " we found: " + match + ". Special characters are not allowed");
+        }
+    }
+
+    private function needMoreTokens() : Boolean {
+        
+        if(this.tokens.length == 0)
+               return true;
+        else if(nextPossibleSimpleKey() == this.tokensTaken)
+                       return true;
+               
+               return false;
+    }
+       
+    private function fetchMoreTokens() : Token {
+        scanToNextToken();
+        unwindIndent(this.column);
+        var ch : String =  buffer.peek();
+        var colz :Boolean = this.column == 0;
+        switch(ch) {
+        case ':': if(this.flowLevel != 0 || NULL_OR_OTHER.indexOf(buffer.peek(1)) != -1) { return fetchValue(); } break;       
+        case '\'': return fetchSingle();
+        case '"': return fetchDouble();
+        case '?': if(this.flowLevel != 0 || NULL_OR_OTHER.indexOf(buffer.peek(1)) != -1) { return fetchKey(); } break;
+        case '%': if(colz) {return fetchDirective(); } break;
+        case '-': 
+            if((colz || docStart) && (ENDING.exec(prefix(4)))) {
+                return fetchDocumentStart(); 
+            } else if(NULL_OR_OTHER.indexOf(buffer.peek(1)) != -1) {
+                return fetchBlockEntry(); 
+            }
+            break;
+        case '.': 
+            if(colz && START.exec(prefix(4))) {
+                return fetchDocumentEnd(); 
+            }
+            break;
+        case '[': return fetchFlowSequenceStart();
+        case '{': return fetchFlowMappingStart();
+        case ']': return fetchFlowSequenceEnd();
+        case '}': return fetchFlowMappingEnd();
+        case ',': return fetchFlowEntry();
+        case '*': return fetchAlias();
+        case '&': return fetchAnchor();
+        case '!': return fetchTag();
+        case '|': if(this.flowLevel == 0) { return fetchLiteral(); } break;
+        case '>': if(this.flowLevel == 0) { return fetchFolded(); } break;
+        case '\x00': return fetchStreamEnd();
+        }
+        if(BEG.exec(prefix(2))) {
+            return fetchPlain();
+        }
+        throw new ScannerException("while scanning for the next token","found character " + ch + "(" + (ch) + " that cannot start any token",null);
+    }
+
+    private function nextPossibleSimpleKey() : int {
+        for(var keyObj : Object in this.possibleSimpleKeys) {
+            var sk : SimpleKey = this.possibleSimpleKeys[keyObj] as SimpleKey;
+            var tokNum : int = sk.tokenNumber;         
+            if(tokNum > 0) {
+                return tokNum;
+            }
+        }
+        return -1;
+    }
+
+    private function removePossibleSimpleKey() : void {
+        var key : SimpleKey = SimpleKey(this.possibleSimpleKeys[this.flowLevel]);
+        if(key != null) {
+               delete this.possibleSimpleKeys[this.flowLevel];
+            if(key.isRequired()) {
+                throw new ScannerException("while scanning a simple key","could not find expected ':'",null);
+            }
+        }
+    }
+    
+    private function savePossibleSimpleKey() : void {
+        if(this.allowSimpleKey) {
+               this.removePossibleSimpleKey();
+            this.possibleSimpleKeys[this.flowLevel] = new SimpleKey(this.tokensTaken+this.tokens.length,(this.flowLevel == 0) && this.indent == this.column,-1,-1,this.column);
+        }
+    }
+    
+    private function unwindIndent(col : int) : void {
+        if(this.flowLevel != 0) {
+            return;
+        }
+
+        while(this.indent > col) {
+            this.indent = this.indents.shift();
+            this.tokens.push(Tokens.BLOCK_END);
+        }
+    }
+    
+    private function addIndent(col : int) : Boolean {
+        if(this.indent < col) {
+            this.indents.unshift(this.indent);
+            this.indent = col;
+            return true;
+        }
+        return false;
+    }
+
+    private function fetchStreamStart() : Token {
+        this.docStart = true;
+        this.tokens.push(Tokens.STREAM_START);
+        return Tokens.STREAM_START;
+    }
+
+    private function fetchStreamEnd() : Token {
+        unwindIndent(-1);
+        this.allowSimpleKey = false;
+        this.possibleSimpleKeys = new Object();
+        this.tokens.push(Tokens.STREAM_END);
+        this.done = true;
+        return Tokens.STREAM_END;
+    }
+
+    private function fetchDirective() : Token {
+        unwindIndent(-1);
+        this.allowSimpleKey = false;
+        var tok : Token = scanDirective();
+        this.tokens.push(tok);
+        return tok;
+    }
+    
+    private function fetchDocumentStart() : Token {
+        this.docStart = false;
+        return fetchDocumentIndicator(Tokens.DOCUMENT_START);
+    }
+
+    private function fetchDocumentEnd() : Token {
+        return fetchDocumentIndicator(Tokens.DOCUMENT_END);
+    }
+
+    private function fetchDocumentIndicator(tok : Token) : Token {
+        unwindIndent(-1);
+        removePossibleSimpleKey();
+        this.allowSimpleKey = false;
+        forwardBy(3);
+        this.tokens.push(tok);
+        return tok;
+    }
+    
+    private function fetchFlowSequenceStart() : Token {
+        return fetchFlowCollectionStart(Tokens.FLOW_SEQUENCE_START);
+    }
+
+    private function fetchFlowMappingStart() : Token {
+        return fetchFlowCollectionStart(Tokens.FLOW_MAPPING_START);
+    }
+
+    private function fetchFlowCollectionStart(tok : Token) : Token {
+        savePossibleSimpleKey();
+        this.flowLevel++;
+        this.allowSimpleKey = true;
+        forwardBy(1);
+        this.tokens.push(tok);
+        return tok;
+    }
+
+    private function fetchFlowSequenceEnd() : Token {
+        return fetchFlowCollectionEnd(Tokens.FLOW_SEQUENCE_END);
+    }
+    
+    private function fetchFlowMappingEnd() : Token {
+        return fetchFlowCollectionEnd(Tokens.FLOW_MAPPING_END);
+    }
+    
+    private function fetchFlowCollectionEnd(tok : Token) : Token {
+        removePossibleSimpleKey();
+        this.flowLevel--;
+        this.allowSimpleKey = false;
+        forwardBy(1);
+        this.tokens.push(tok);
+        return tok;
+    }
+    
+    private function fetchFlowEntry() : Token {
+        this.allowSimpleKey = true;
+        removePossibleSimpleKey();
+        forwardBy(1);
+        this.tokens.push(Tokens.FLOW_ENTRY);
+        return Tokens.FLOW_ENTRY;
+    }
+
+    private function fetchBlockEntry() : Token {
+
+        if(this.flowLevel == 0) {
+            if(!this.allowSimpleKey) {
+                throw new ScannerException(null,"sequence entries are not allowed here",null);
+            }
+            if(addIndent(this.column)) {
+                this.tokens.push(Tokens.BLOCK_SEQUENCE_START);
+            }
+        }
+        this.allowSimpleKey = true;
+        removePossibleSimpleKey();
+        forward();
+        this.tokens.push(Tokens.BLOCK_ENTRY);
+
+        return Tokens.BLOCK_ENTRY;
+    }        
+
+    private function fetchKey() : Token {
+        if(this.flowLevel == 0) {
+            if(!this.allowSimpleKey) {
+                throw new ScannerException(null,"mapping keys are not allowed here",null);
+            }
+            if(addIndent(this.column)) {
+                this.tokens.push(Tokens.BLOCK_MAPPING_START);
+            }
+        }
+        this.allowSimpleKey = this.flowLevel == 0;
+        removePossibleSimpleKey();
+        forward();
+        this.tokens.push(Tokens.KEY);
+        return Tokens.KEY;
+    }
+
+    private function fetchValue() : Token {
+       this.docStart = false;
+        var key : SimpleKey = this.possibleSimpleKeys[this.flowLevel];
+        if(null == key) {
+            if(this.flowLevel == 0 && !this.allowSimpleKey) {
+                throw new ScannerException(null,"mapping values are not allowed here",null);
+            }
+            this.allowSimpleKey = (this.flowLevel == 0);
+            removePossibleSimpleKey();
+        } else {
+            delete this.possibleSimpleKeys[this.flowLevel];
+            var sIndex: int = key.tokenNumber-this.tokensTaken;
+                   var s:Array = tokens.slice(0, sIndex);
+                   var e:Array = tokens.slice(sIndex);
+                   tokens = s.concat(Tokens.KEY).concat(e);
+            if(this.flowLevel == 0 && addIndent(key.getColumn())) {
+                   var sIndex2: int = key.tokenNumber-this.tokensTaken;
+                           var s2:Array = tokens.slice(0, sIndex2);
+                           var e2:Array = tokens.slice(sIndex2);
+                           tokens = s2.concat(Tokens.BLOCK_MAPPING_START).concat(e2);
+            }
+            this.allowSimpleKey = false;
+        }
+        forward();
+        this.tokens.push(Tokens.VALUE);
+        return Tokens.VALUE;
+    }
+
+    private function fetchAlias() : Token {
+        savePossibleSimpleKey();
+        this.allowSimpleKey = false;
+        var tok : Token = scanAnchor(new AliasToken());
+        this.tokens.push(tok);
+        return tok;
+    }
+
+    private function fetchAnchor() : Token {
+        savePossibleSimpleKey();
+        this.allowSimpleKey = false;
+        var tok : Token = scanAnchor(new AnchorToken());
+        this.tokens.push(tok);
+        return tok;
+    }
+
+    private function fetchTag() : Token {
+       this.docStart = false;
+        savePossibleSimpleKey();
+        this.allowSimpleKey = false;
+        var tok : Token = scanTag();
+        this.tokens.push(tok);
+        return tok;
+    }
+    
+    private function fetchLiteral() : Token {
+        return fetchBlockScalar('|');
+    }
+    
+    private function fetchFolded() : Token {
+        return fetchBlockScalar('>');
+    }
+    
+    private function fetchBlockScalar(style : String) : Token {
+        this.allowSimpleKey = true;
+        this.removePossibleSimpleKey();
+        var tok : Token = scanBlockScalar(style);
+        this.tokens.push(tok);
+        return tok;
+    }
+    
+    private function fetchSingle() : Token {
+        return fetchFlowScalar('\'');
+    }
+    
+    private function fetchDouble() : Token {
+        return fetchFlowScalar('"');
+    }
+    
+    private function fetchFlowScalar(style : String) : Token {
+        savePossibleSimpleKey();
+        this.allowSimpleKey = false;
+        var tok : Token = scanFlowScalar(style);
+        this.tokens.push(tok);
+        return tok;
+    }
+    
+    private function fetchPlain() : Token {
+        savePossibleSimpleKey();
+        this.allowSimpleKey = false;
+        var tok : Token = scanPlain();
+        this.tokens.push(tok);
+        return tok;
+    }
+    
+    private function scanToNextToken() : void {
+        while(1) {
+               
+                       var pk : String = buffer.peek();
+            while(pk == ' ') {
+                forward(pk);
+                pk = buffer.peek();
+            }                  
+            if(pk == '#') {
+                while(NULL_OR_LINEBR.indexOf(buffer.peek()) == -1) {
+                    forward();
+                }
+            }
+            if(scanLineBreak().length != 0 ) {
+                if(this.flowLevel == 0) {
+                    this.allowSimpleKey = true;
+                }
+            } else {
+                break;
+            }
+        }
+    }
+    
+    private function scanDirective() : Token {
+        forward();
+        var name : String = scanDirectiveName();
+        var value : Array = null;
+        if(name == ("YAML")) {
+            value = scanYamlDirectiveValue();
+        } else if(name == ("TAG")) {
+            value = scanTagDirectiveValue();
+        } else {
+            while(NULL_OR_LINEBR.indexOf(buffer.peek()) == -1) {
+                forward();
+            }
+        }
+        scanDirectiveIgnoredLine();
+        return new DirectiveToken(name,value);
+    }
+    
+    private function scanDirectiveName() : String {
+        var length : int = 0;
+        var ch : String = buffer.peek(length);
+        var zlen : Boolean = true;
+        while(ALPHA.indexOf(ch) != -1) {
+            zlen = false;
+            length++;
+            ch = buffer.peek(length);
+        }
+        if(zlen) {
+            throw new ScannerException("while scanning a directive","expected alphabetic or numeric character, but found " + ch + "(" + (ch) + ")",null);
+        }
+        var value : String = prefixForward(length);
+        //        forward(length);
+        if(NULL_BL_LINEBR.indexOf(buffer.peek()) == -1) {
+            throw new ScannerException("while scanning a directive","expected alphabetic or numeric character, but found " + ch + "(" + (ch) + ")",null);
+        }
+        return value;
+    }
+
+    private function scanYamlDirectiveValue() : Array {
+        while(buffer.peek() == ' ') {
+            forward();
+        }
+        var major : String = scanYamlDirectiveNumber();
+        if(buffer.peek() != '.') {
+            throw new ScannerException("while scanning a directive","expected a digit or '.', but found " + buffer.peek() + "(" + (buffer.peek()) + ")",null);
+        }
+        forward();
+        var minor : String = scanYamlDirectiveNumber();
+        if(NULL_BL_LINEBR.indexOf(buffer.peek()) == -1) {
+            throw new ScannerException("while scanning a directive","expected a digit or ' ', but found " + buffer.peek() + "(" + (buffer.peek()) + ")",null);
+        }
+        return [major,minor];
+    }
+
+    private function scanYamlDirectiveNumber() : String {
+        var ch : String = buffer.peek();
+        if(!StringUtils.isDigit(ch)) {
+            throw new ScannerException("while scanning a directive","expected a digit, but found " + ch + "(" + (ch) + ")",null);
+        }
+        var length : int = 0;
+        while(StringUtils.isDigit(buffer.peek(length))) {
+            length++;
+        }
+        var value : String = prefixForward(length);
+        //        forward(length);
+        return value;
+    }
+
+    private function scanTagDirectiveValue() : Array  {
+        while(buffer.peek() == ' ') {
+            forward();
+        }
+        var handle : String = scanTagDirectiveHandle();
+        while(buffer.peek() == ' ') {
+            forward();
+        }
+        var prefix : String = scanTagDirectivePrefix();
+        return [handle,prefix];
+    }
+
+    private function scanTagDirectiveHandle() : String {
+        var value : String = scanTagHandle("directive");
+        if(buffer.peek() != ' ') {
+            throw new ScannerException("while scanning a directive","expected ' ', but found " + buffer.peek() + "(" + (buffer.peek()) + ")",null);
+        }
+        return value;
+    }
+    
+    private function scanTagDirectivePrefix() : String {
+        var value : String = scanTagUri("directive");
+        if(NULL_BL_LINEBR.indexOf(buffer.peek()) == -1) {
+            throw new ScannerException("while scanning a directive","expected ' ', but found " + buffer.peek() + "(" + (buffer.peek()) + ")",null);
+        }
+        return value;
+    }
+
+    private function scanDirectiveIgnoredLine() : String {
+        while(buffer.peek() == ' ') {
+            forward();
+        }
+        if(buffer.peek() == '"') {
+            while(NULL_OR_LINEBR.indexOf(buffer.peek()) == -1) {
+                forward();
+            }
+        }
+        var ch : String = buffer.peek();
+        if(NULL_OR_LINEBR.indexOf(ch) == -1) {
+            throw new ScannerException("while scanning a directive","expected a comment or a line break, but found " + buffer.peek() + "(" + (buffer.peek()) + ")",null);
+        }
+        return scanLineBreak();
+    }
+
+    private function scanAnchor(tok : Token) : Token {
+        var indicator : String = buffer.peek();
+        var name : String = indicator == '*' ? "alias" : "anchor";
+        forward();
+        var length : int = 0;
+        var chunk_size : int = 16;
+        var match : Object;
+        for(;;) {
+            var chunk : String = prefix(chunk_size);
+            if((match = NON_ALPHA.exec(chunk))) {
+                break;
+            }
+            chunk_size+=16;
+        }
+        length = match.index;
+        if(length == 0) {
+            throw new ScannerException("while scanning an " + name,"expected alphabetic or numeric character, but found something else...",null);
+        }
+        var value : String = prefixForward(length);
+        //        forward(length);
+        if(NON_ALPHA_OR_NUM.indexOf(buffer.peek()) == -1) {
+            throw new ScannerException("while scanning an " + name,"expected alphabetic or numeric character, but found "+ buffer.peek() + "(" + (buffer.peek()) + ")",null);
+
+        }
+        tok.setValue(value);
+        return tok;
+    }
+
+    private function scanTag() : Token {
+        var ch : String = buffer.peek(1);
+        var handle : String = null;
+        var suffix : String = null;
+        if(ch == '<') {
+            forwardBy(2);
+            suffix = scanTagUri("tag");
+            if(buffer.peek() != '>') {
+                throw new ScannerException("while scanning a tag","expected '>', but found "+ buffer.peek() + "(" + (buffer.peek()) + ")",null);
+            }
+            forward();
+        } else if(NULL_BL_T_LINEBR.indexOf(ch) != -1) {
+            suffix = "!";
+            forward();
+        } else {
+            var length : int = 1;
+            var useHandle : Boolean = false;
+            while(NULL_BL_T_LINEBR.indexOf(ch) == -1) {
+                if(ch == '!') {
+                    useHandle = true;
+                    break;
+                }
+                length++;
+                ch = buffer.peek(length);
+            }
+            handle = "!";
+            if(useHandle) {
+                handle = scanTagHandle("tag");
+            } else {
+                handle = "!";
+                forward();
+            }
+            suffix = scanTagUri("tag");
+        }
+        if(NULL_BL_LINEBR.indexOf(buffer.peek()) == -1) {
+            throw new ScannerException("while scanning a tag","expected ' ', but found " + buffer.peek() + "(" + (buffer.peek()) + ")",null);
+        }
+        return new TagToken([handle,suffix]);
+    }
+
+    private function scanBlockScalar(style : String) : ScalarToken {
+        var folded : Boolean = style == '>';
+        var chunks : String = new String();
+        forward();
+        var chompi : Array = scanBlockScalarIndicators();
+        var chomping : Boolean = Boolean(chompi[0])
+        var increment : int = (int(chompi[1]));
+        scanBlockScalarIgnoredLine();
+        var minIndent : int = this.indent+1;
+        if(minIndent < 1) {
+            minIndent = 1;
+        }
+        var breaks : String = null;
+        var maxIndent : int = 0;
+        var ind : int = 0;
+        if(increment == -1) {
+            var brme : Array = scanBlockScalarIndentation();
+            breaks = String(brme[0]);
+            maxIndent = (int(brme[1]))
+            if(minIndent > maxIndent) {
+                ind = minIndent;
+            } else {
+                ind = maxIndent;
+            }
+        } else {
+            ind = minIndent + increment - 1;
+            breaks = scanBlockScalarBreaks(ind);
+        }
+               var pk :String = buffer.peek();
+        var lineBreak : String = "";
+        while(this.column == ind && pk != '\x00') {
+            chunks += breaks;
+            var leadingNonSpace : Boolean = BLANK_T.indexOf(pk) == -1;
+            var length : int = 0;
+            while(NULL_OR_LINEBR.indexOf(buffer.peek(length))==-1) {
+                length++;
+            }
+            chunks += prefixForward(length);
+            //            forward(length);
+            lineBreak = scanLineBreak();
+            breaks = scanBlockScalarBreaks(ind);
+            pk = buffer.peek();
+            if(this.column == ind && pk != '\x00') {
+                if(folded && lineBreak == ("\n") && leadingNonSpace && BLANK_T.indexOf(pk) == -1) {
+                    if(breaks.length == 0) {
+                        chunks += " ";
+                    }
+                } else {
+                    chunks += lineBreak;
+                }
+            } else {
+                break;
+            }
+        }
+
+        if(chomping) {
+            chunks += lineBreak;
+            chunks += breaks;
+        }
+
+        return new ScalarToken(chunks,false,style);
+    }
+
+    private function scanBlockScalarIndicators() : Array {
+        var chomping : Boolean = false;
+        var increment : int = -1;
+        var ch : String = buffer.peek();
+        if(ch == '-' || ch == '+') {
+            chomping = ch == '+';
+            forward(ch);
+            ch = buffer.peek();
+            if(StringUtils.isDigit(ch)) {
+                increment = int(ch);
+                if(increment == 0) {
+                    throw new ScannerException("while scanning a block scalar","expected indentation indicator in the range 1-9, but found 0",null);
+                }
+                forward(ch);
+            }
+        } else if(StringUtils.isDigit(ch)) {
+            increment = int(ch);
+            if(increment == 0) {
+                throw new ScannerException("while scanning a block scalar","expected indentation indicator in the range 1-9, but found 0",null);
+            }
+            forward();
+            ch = buffer.peek();
+            if(ch == '-' || ch == '+') {
+                chomping = ch == '+';
+                forward();
+            }
+        }
+        if(NULL_BL_LINEBR.indexOf(buffer.peek()) == -1) {
+            throw new ScannerException("while scanning a block scalar","expected chomping or indentation indicators, but found " + buffer.peek() + "(" + (buffer.peek()) + ")",null);
+        }
+        return [chomping, increment];
+}
+
+    private function scanBlockScalarIgnoredLine() : String {
+        while(buffer.peek() == ' ') {
+            forward();
+        }
+        if(buffer.peek() == '#') {
+            while(NULL_OR_LINEBR.indexOf(buffer.peek()) == -1) {
+                forward();
+            }
+        }
+        if(NULL_OR_LINEBR.indexOf(buffer.peek()) == -1) {
+            throw new ScannerException("while scanning a block scalar","expected a comment or a line break, but found " + buffer.peek() + "(" + (buffer.peek()) + ")",null);
+        }
+        return scanLineBreak();
+    }
+
+    private function scanBlockScalarIndentation() : Array {
+        var chunks : String = new String();
+        var maxIndent : int = 0;
+        while(BLANK_OR_LINEBR.indexOf(buffer.peek()) != -1) {
+            if(buffer.peek() != ' ') {
+                chunks += scanLineBreak();
+            } else {
+                forward();
+                if(this.column > maxIndent) {
+                    maxIndent = column;
+                }
+            }
+        }
+        return [chunks, maxIndent];
+    }
+
+    private function scanBlockScalarBreaks(indent : int) : String {
+        var chunks : String = new String();
+        while(this.column < indent && buffer.peek() == ' ') {
+            forward();
+        }
+        while(FULL_LINEBR.indexOf(buffer.peek()) != -1) {
+            chunks += scanLineBreak();
+            while(this.column < indent && buffer.peek() == ' ') {
+                forward();
+            }
+        }
+        return chunks;
+    }
+
+    private function scanFlowScalar(style : String) : Token {
+        var dbl : Boolean = style == '"';
+        var chunks : String = new String();
+        var quote : String = buffer.peek();
+        forward();
+        chunks += scanFlowScalarNonSpaces(dbl);
+        while(buffer.peek() != quote) {
+            chunks += scanFlowScalarSpaces();
+            chunks += scanFlowScalarNonSpaces(dbl);
+        }
+        forward();
+               
+        return new ScalarToken(chunks,false,style);
+    }
+
+    private function scanFlowScalarNonSpaces(dbl : Boolean) : String {
+        var chunks : String = new String();
+        while(1) {
+            var length : int = 0;
+            while(SPACES_AND_STUFF.indexOf(buffer.peek(length)) == -1) {
+                length++;
+            }
+            if(length != 0) {
+                chunks += (prefixForward(length));
+                //                forward(length);
+            }
+            var ch : String = buffer.peek();
+            if(!dbl && ch == '\'' && buffer.peek(1) == '\'') {
+                chunks += ("'");
+                forwardBy(2);
+            } else if((dbl && ch == '\'') || (!dbl && DOUBLE_ESC.indexOf(ch) != -1)) {
+                chunks += ch;
+                forward();
+            } else if(dbl && ch == '\\') {
+                forward();
+                ch = buffer.peek();
+                if(ESCAPE_REPLACEMENTS[ch]) {
+                    chunks += ESCAPE_REPLACEMENTS[ch];
+                    forward(); 
+                } else if(ESCAPE_CODES[ch]) {
+                    length = (ESCAPE_CODES[ch]);
+                    forward();
+                    var val : String = prefix(length);
+                    if(NOT_HEXA.exec(val)) {
+                        throw new ScannerException("while scanning a double-quoted scalar","expected escape sequence of " + length + " hexadecimal numbers, but found something else: " + val,null);
+                    }
+                    var charCode : int = parseInt(val, 16);
+                    var char : String = String.fromCharCode(charCode);
+                    chunks += char;
+                    forwardBy(length);
+                } else if(FULL_LINEBR.indexOf(ch) != -1) {
+                    scanLineBreak();
+                    chunks += scanFlowScalarBreaks();
+                } else {
+                    throw new ScannerException("while scanning a double-quoted scalar","found unknown escape character " + ch + "(" + (ch) + ")",null);
+                }
+            } else {
+                return chunks;
+            }
+        }
+        return "";
+    }
+
+    private function scanFlowScalarSpaces() : String {
+        var chunks : String = new String();
+        var length : int = 1;
+        while(BLANK_T.indexOf(buffer.peek(length)) != -1) {
+            length++;
+        }
+        var whitespaces : String = prefixForward(length);
+        //        forward(length);
+        var ch : String = buffer.peek();
+        if(ch == '\x00') {
+            throw new ScannerException("while scanning a quoted scalar","found unexpected end of stream",null);
+        } else if(FULL_LINEBR.indexOf(ch) != -1) {
+            var lineBreak : String = scanLineBreak();
+            var breaks : String = scanFlowScalarBreaks();
+            if(!lineBreak == ("\n")) {
+                chunks += lineBreak;
+            } else if(breaks.length == 0) {
+                chunks += " ";
+            }
+            chunks += breaks;
+        } else {
+            chunks += whitespaces;
+        }
+        return chunks;
+    }
+
+    private function scanFlowScalarBreaks() : String {
+        var chunks : String = "";
+        var pre : String = null;
+        while(1) {
+            pre = prefix(3);
+            if((pre == ("---") || pre == ("...")) && NULL_BL_T_LINEBR.indexOf(buffer.peek(3)) != -1) {
+                throw new ScannerException("while scanning a quoted scalar","found unexpected document separator",null);
+            }
+            while(BLANK_T.indexOf(buffer.peek()) != -1) {
+                forward();
+            }
+            if(FULL_LINEBR.indexOf(buffer.peek()) != -1) {
+                chunks += scanLineBreak();
+            } else {
+                return chunks;
+            }            
+        }
+        return "";
+    }
+
+
+    private function scanPlain() : Token {
+        /*
+       See the specification for details.
+       We add an additional restriction for the flow context:
+         plain scalars in the flow context cannot contain ',', ':' and '?'.
+       We also keep track of the `allow_simple_key` flag here.
+       Indentation rules are loosed for the flow context.
+         */
+        
+        
+        var chunks : String = new String();
+        var ind : int = this.indent+1;
+        var spaces : String = "";
+        var f_nzero : Boolean = true;
+        var r_check : RegExp = R_FLOWNONZERO;
+        if(this.flowLevel == 0) {
+            f_nzero = false;
+            r_check = R_FLOWZERO;
+        }
+        while(buffer.peek() != '#') {
+               
+            var chunkSize : int = 256;
+            var startAt: int = 0;
+            var match: Object;
+            while(!(match = r_check.exec(prefix(chunkSize, startAt)))) {
+                startAt += chunkSize;
+            }
+            
+            const length: int = startAt + int(match.index);
+            var ch : String = buffer.peek(length);
+            if(f_nzero && ch == ':' && S4.indexOf(buffer.peek(length+1)) == -1) {
+                forwardBy(length);
+                throw new ScannerException("while scanning a plain scalar","found unexpected ':'","Please check http://pyyaml.org/wiki/YAMLColonInFlowContext for details.");
+            }
+                       
+            if(length == 0) {
+                break;
+            }
+            this.allowSimpleKey = false;
+            chunks += spaces;
+            chunks += prefixForward(length);
+
+            spaces = scanPlainSpaces(ind);
+            if(spaces == null || (this.flowLevel == 0 && this.column < ind)) {
+                break;
+            }
+        }
+                      
+        return new ScalarToken(chunks,true);
+    }
+
+    private function scanPlainSpaces(indent : int) : String {
+        var chunks : String = new String();
+        var length : int = 0;
+        while(buffer.peek(length) == ' ') {
+            length++;
+        }
+        var whitespaces : String = prefixForward(length);
+        //        forward(length);
+        var ch : String  = buffer.peek();
+        if(FULL_LINEBR.indexOf(ch) != -1) {
+            var lineBreak : String = scanLineBreak();
+            this.allowSimpleKey = true;
+            if(END_OR_START.exec(prefix(4))) {
+                return "";
+            }
+            var breaks : String = new String();
+            while(BLANK_OR_LINEBR.indexOf(buffer.peek()) != -1) {
+                if(' ' == buffer.peek()) {
+                    forward();
+                } else {
+                    breaks += scanLineBreak();
+                    if(END_OR_START.exec(prefix(4))) {
+                        return "";
+                    }
+                }
+            }            
+            if(!lineBreak == ("\n")) {
+                chunks += lineBreak;
+            } else if(breaks == null || breaks.toString() == ("")) {
+                chunks += " ";
+            }
+            chunks += breaks;
+        } else {
+            chunks += whitespaces;
+        }
+        return chunks;
+    }
+
+    private function scanTagHandle(name : String) : String {
+        var ch : String =  buffer.peek();
+        if(ch != '!') {
+            throw new ScannerException("while scanning a " + name,"expected '!', but found " + ch + "(" + (ch) + ")",null);
+        }
+        var length : int = 1;
+        ch = buffer.peek(length);
+        if(ch != ' ') {
+            while(ALPHA.indexOf(ch) != -1) {
+                length++;
+                ch = buffer.peek(length);
+            }
+            if('!' != ch) {
+                forwardBy(length);
+                throw new ScannerException("while scanning a " + name,"expected '!', but found " + ch + "(" + (ch) + ")",null);
+            }
+            length++;
+        }
+        var value :String = prefixForward(length);
+
+        return value;
+    }
+
+    private function scanTagUri(name : String) : String {
+        var chunks : String = new String();
+        var length : int = 0;
+        var ch : String = buffer.peek(length);
+        while(STRANGE_CHAR.indexOf(ch) != -1) {
+            if('%' == ch) {
+                chunks += prefixForward(length);
+                length = 0;
+                chunks += scanUriEscapes(name);
+            } else {
+                length++;
+            }
+            ch = buffer.peek(length);
+        }
+        if(length != 0) {
+            chunks += (prefixForward(length));
+        }
+
+        if(chunks.length == 0) {
+            throw new ScannerException("while scanning a " + name,"expected URI, but found " + ch + "(" + (ch) + ")",null);
+        }
+        return chunks;
+    }
+
+    private function scanUriEscapes(name : String) : String {
+        var bytes : String = new String();
+        while(buffer.peek() == '%') {
+            forward();
+            try {
+                bytes += int(prefix(2)).toString(16);
+            } catch(nfe : Error) {
+                throw new ScannerException("while scanning a " + name,"expected URI escape sequence of 2 hexadecimal numbers, but found " + buffer.peek(1) + "(" + (buffer.peek(1)) + ") and "+ buffer.peek(2) + "(" + (buffer.peek(2)) + ")",null);
+            }
+            forwardBy(2);
+        }
+        return bytes
+    }
+
+    private function scanLineBreak() : String {
+        // Transforms:
+   &nb