split casing and fill onto separate levels
[potlatch2.git] / org / as3yaml / Emitter.as
1 /*
2  * Copyright (c) 2007 Derek Wischusen
3  * 
4  * Permission is hereby granted, free of charge, to any person obtaining a copy of 
5  * this software and associated documentation files (the "Software"), to deal in 
6  * the Software without restriction, including without limitation the rights to 
7  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 
8  * of the Software, and to permit persons to whom the Software is furnished to do
9  * so, subject to the following conditions:
10  * 
11  * The above copyright notice and this permission notice shall be included in all
12  * copies or substantial portions of the Software.
13  * 
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
20  * SOFTWARE.
21  */
22
23 package org.as3yaml {
24
25 import org.as3yaml.events.*;
26 import org.idmedia.as3commons.util.Iterator;
27 import org.idmedia.as3commons.util.Map;
28 import org.idmedia.as3commons.util.HashMap;
29 import org.rxr.actionscript.io.StringWriter;
30
31
32
33 public class Emitter {
34
35     internal static const STREAM_START : int = 0;
36     internal static const FIRST_DOCUMENT_START : int = 1;
37     internal static const DOCUMENT_ROOT : int = 2;
38     internal static const NOTHING : int = 3;
39     internal static const DOCUMENT_START : int = 4;
40     internal static const DOCUMENT_END : int = 5;
41     internal static const FIRST_FLOW_SEQUENCE_ITEM : int = 6;
42     internal static const FLOW_SEQUENCE_ITEM : int = 7;
43     internal static const FIRST_FLOW_MAPPING_KEY : int = 8;
44     internal static const FLOW_MAPPING_SIMPLE_VALUE : int = 9;
45     internal static const FLOW_MAPPING_VALUE : int = 10;
46     internal static const FLOW_MAPPING_KEY : int = 11;
47     internal static const BLOCK_SEQUENCE_ITEM : int = 12;
48     internal static const FIRST_BLOCK_MAPPING_KEY : int = 13;
49     internal static const BLOCK_MAPPING_SIMPLE_VALUE : int = 14;
50     internal static const BLOCK_MAPPING_VALUE : int = 15;
51     internal static const BLOCK_MAPPING_KEY : int = 16;
52     internal static const FIRST_BLOCK_SEQUENCE_ITEM : int = 17;
53     
54     private static var STATES : Array = new Array();
55     
56     static: {
57         STATES[STREAM_START] = function expect(env : EmitterEnvironment) : void {
58                     env.expectStreamStart();
59                 };
60
61         STATES[FIRST_DOCUMENT_START] = function expect(env : EmitterEnvironment) : void {
62                     env.expectDocumentStart(true);
63                 };
64             
65         STATES[DOCUMENT_ROOT] = function expect(env : EmitterEnvironment) : void {
66                     env.expectDocumentRoot();
67                 };
68             
69         STATES[NOTHING] =  function expect(env : EmitterEnvironment) : void {
70                     env.expectNothing();
71                 };
72             
73         STATES[DOCUMENT_START] = function expect(env : EmitterEnvironment) : void {
74                     env.expectDocumentStart(false);
75                 };
76             
77         STATES[DOCUMENT_END] = function expect(env : EmitterEnvironment ) : void {
78                     env.expectDocumentEnd();
79                 };
80             
81         STATES[FIRST_FLOW_SEQUENCE_ITEM] = function expect(env : EmitterEnvironment) : void {
82                     env.expectFirstFlowSequenceItem();
83                 };
84             
85         STATES[FLOW_SEQUENCE_ITEM] = function expect(env : EmitterEnvironment) : void {
86                     env.expectFlowSequenceItem();
87                 };
88             
89         STATES[FIRST_FLOW_MAPPING_KEY] = function expect(env : EmitterEnvironment) : void {
90                     env.expectFirstFlowMappingKey();
91                 };
92             
93         STATES[FLOW_MAPPING_SIMPLE_VALUE] = function expect(env : EmitterEnvironment) : void {
94                     env.expectFlowMappingSimpleValue();
95                 };
96             
97         STATES[FLOW_MAPPING_VALUE] = function expect(env : EmitterEnvironment) : void {
98                     env.expectFlowMappingValue();
99                 };
100             
101         STATES[FLOW_MAPPING_KEY] = function expect(env : EmitterEnvironment) : void {
102                     env.expectFlowMappingKey();
103                 };
104             
105         STATES[BLOCK_SEQUENCE_ITEM] = function expect(env : EmitterEnvironment) : void {
106                     env.expectBlockSequenceItem(false);
107                 };
108             
109         STATES[FIRST_BLOCK_MAPPING_KEY] = function expect(env : EmitterEnvironment) : void {
110                     env.expectFirstBlockMappingKey();
111                 };
112             
113         STATES[BLOCK_MAPPING_SIMPLE_VALUE] = function expect(env : EmitterEnvironment) : void {
114                     env.expectBlockMappingSimpleValue();
115                 };
116             
117         STATES[BLOCK_MAPPING_VALUE] = function expect(env : EmitterEnvironment) : void {
118                     env.expectBlockMappingValue();
119                 };
120             
121         STATES[BLOCK_MAPPING_KEY] = function expect(env : EmitterEnvironment) : void {
122                     env.expectBlockMappingKey(false);
123                 };
124             
125         STATES[FIRST_BLOCK_SEQUENCE_ITEM] = function expect(env : EmitterEnvironment) : void  {
126                     env.expectBlockSequenceItem(true);
127                 };
128             
129     }
130
131     public static var DEFAULT_TAG_PREFIXES_1_0 : Map;
132     public static var DEFAULT_TAG_PREFIXES_1_1 : Map;
133     static: {
134         private static var defInit0 : Map = new HashMap();
135         defInit0.put("tag:yaml.org,2002:","!");
136         DEFAULT_TAG_PREFIXES_1_0 = defInit0;
137         private static var defInit : Map = new HashMap();
138         defInit.put("!","!");
139         defInit.put("tag:yaml.org,2002:","!!");
140         DEFAULT_TAG_PREFIXES_1_1 = defInit;
141     }
142
143     private var stream : StringWriter;
144     private var options : YAMLConfig;
145     private var env : EmitterEnvironment;
146
147     public function Emitter(stream : StringWriter, opts : YAMLConfig) {
148         this.stream = stream;
149         this.options = opts;
150         this.env = new EmitterEnvironment();
151         this.env.emitter = this;
152         this.env.canonical = this.options.getCanonical();
153         var propIndent : int = this.options.getIndent();
154         if(propIndent>=2 && propIndent<10) {
155             this.env.bestIndent = propIndent;
156         }
157         var propWidth : int = this.options.getBestWidth();
158         if(propWidth != 0 && propWidth > (this.env.bestIndent*2)) {
159             this.env.bestWidth = propWidth;
160         }
161     }
162
163     public function getOptions() : YAMLConfig {
164         return options;
165     }
166
167     public function emit(event : Event) : void {
168         this.env.events.add(event);
169         while(!this.env.needMoreEvents()) {
170             this.env.event = this.env.events.removeAtAndReturn(0);
171             STATES[this.env.state](env);
172             this.env.event = null;
173         }
174     }
175
176     internal function writeStreamStart() : void {
177     }
178
179     internal function writeStreamEnd() : void {
180         flushStream();
181     }
182     
183     internal function writeIndicator(indicator : String, needWhitespace : Boolean, whitespace : Boolean, indentation : Boolean) : void {
184         var data : String = null;
185         if(!(env.whitespace || !needWhitespace)) {
186              data = " " + indicator;
187         } else {
188                 data = indicator;
189         }
190         env.whitespace = whitespace;
191         env.indentation = env.indentation && indentation;
192         env.column += data.length;
193         stream.write(data);
194     }
195
196     internal function writeIndent() : void {
197         var indent : int = 0;
198         if(env.indent != -1) {
199             indent = env.indent;
200         }
201
202         if(!env.indentation || env.column > indent || (env.column == indent && !env.whitespace)) {
203             writeLineBreak(null);
204         }
205
206         if(env.column < indent) {
207             env.whitespace = true;
208             var data : String = new String();
209             for(var i:int=0;i<(indent-env.column);i++) {
210                 data += " ";
211             }
212             env.column = indent;
213             stream.write(data);
214         }
215     }
216
217     internal function writeVersionDirective(version_text : String) : void {
218         stream.write("%YAML " + version_text);
219         writeLineBreak(null);
220     }
221     
222     internal function writeTagDirective(handle : String, prefix : String) : void {
223         stream.write("%TAG " + handle + " " + prefix);
224         writeLineBreak(null);
225     }
226
227     internal function writeDoubleQuoted(text : String, split : Boolean) : void {
228         writeIndicator("\"",true,false,false);
229         var start : int = 0;
230         var ending : int = 0;
231         var data : String = null;
232         var textLen: uint = text.length;
233         while(ending <= textLen) {
234             var ch : * = 0;
235             if(ending < textLen) {
236                 ch = text.charAt(ending);
237             }
238             if(ch==0 || "\"\\\u0085".indexOf(ch) != -1 || !('\u0020' <= ch && ch <= '\u007E')) {
239                 if(start < ending) {
240                     data = text.substring(start,ending);
241                     env.column+=data.length;
242                     stream.write(data);
243                     start = ending;
244                 }
245                 if(ch != 0) {
246                     if(YAML.ESCAPE_REPLACEMENTS[ch]) {
247                         data = "\\" + YAML.ESCAPE_REPLACEMENTS[ch];
248                     } else if(ch <= '\u00FF') {
249                         var str : String = new int(ch).toString(16);
250                         if(str.length == 1) {
251                             str = "0" + str;
252                         }
253                         data = "\\x" + str;
254                     }
255                     env.column += data.length;
256                     stream.write(data);
257                     start = ending+1;
258                 }
259             }
260             if((0 < ending && ending < (textLen-1)) && (ch == ' ' || start >= ending) && (env.column+(ending-start)) > env.bestWidth && split) {
261                 data = text.substring(start,ending) + "\\";
262                 if(start < ending) {
263                     start = ending;
264                 }
265                 env.column += data.length;
266                 stream.write(data);
267                 writeIndent();
268                 env.whitespace = false;
269                 env.indentation = false;
270                 if(text.charAt(start) == ' ') {
271                     data = "\\";
272                     env.column += data.length;
273                     stream.write(data);
274                 }
275             }
276             ending += 1;
277         }
278
279         writeIndicator("\"",false,false,false);
280     }
281
282     internal function writeSingleQuoted(text : String, split : Boolean) : void {
283         writeIndicator("'",true,false,false);
284         var spaces : Boolean = false;
285         var breaks : Boolean = false;
286         var start : int = 0; 
287         var ending : int = 0;
288         var ceh : String = null;
289         var data : String = null;
290         while(ending <= text.length) {
291             ceh = null;
292             if(ending < text.length) {
293                 ceh = text.charAt(ending);
294             }
295             if(spaces) {
296                 if(ceh == null || int(ceh) != 32) {
297                     if(start+1 == ending && env.column > env.bestWidth && split && start != 0 && ending != text.length) {
298                         writeIndent();
299                     } else {
300                         data = text.substring(start,ending);
301                         env.column += data.length;
302                         stream.write(data);
303                     }
304                     start = ending;
305                 }
306             } else if(breaks) {
307                 if(ceh == null || !('\n' == ceh)) {
308                     data = text.substring(start,ending);
309                     for(var i:int=0,j:int=data.length;i<j;i++) {
310                         var cha : String = data.charAt(i);
311                         if('\n' == cha) {
312                             writeLineBreak(null);
313                         } else {
314                             writeLineBreak(""+cha);
315                         }
316                     }
317                     writeIndent();
318                     start = ending;
319                 }
320             } else {
321                 if(ceh == null || !('\n' == ceh)) {
322                     if(start < ending) {
323                         data = text.substring(start,ending);
324                         env.column += data.length;
325                         stream.write(data);
326                         start = ending;
327                     }
328                     if(ceh == '\'') {
329                         data = "''";
330                         env.column += 2;
331                         stream.write(data);
332                         start = ending + 1;
333                     }
334                 }
335             }
336             if(ceh != null) {
337                 spaces = (ceh == ' ');
338                 breaks = (ceh == '\n');
339             }
340             ending++;
341         }
342         writeIndicator("'",false,false,false);
343     }
344
345     internal function writeFolded(text : String) : void  {
346         var chomp : String = determineChomp(text);
347         writeIndicator(">" + chomp, true, false, false);
348         writeIndent();
349         var leadingSpace : Boolean = false;
350         var spaces : Boolean = false;
351         var breaks : Boolean = false;
352         var start:int=0,ending:int=0;
353         var data : String = null;
354         while(ending <= text.length) {
355             var ceh : String = null;
356             if(ending < text.length) {
357                 ceh = text.charAt(ending);
358             }
359             if(breaks) {
360                 if(ceh == null || !('\n' == ceh || '\u0085' == ceh)) {
361                     if(!leadingSpace && ceh != null && ceh != ' ' && text.charAt(start) == '\n') {
362                         writeLineBreak(null);
363                     }
364                     leadingSpace = ceh == ' ';
365                     data = text.substring(start,ending);
366                     for(var i:int=0,j:int=data.length;i<j;i++) {
367                         var cha : String = data.charAt(i);
368                         if('\n' == cha) {
369                             writeLineBreak(null);
370                         } else {
371                             writeLineBreak(""+cha);
372                         }
373                     }
374                     if(ceh != null) {
375                         writeIndent();
376                     }
377                     start = ending;
378                 }
379             } else if(spaces) {
380                 if(ceh != ' ') {
381                     if(start+1 == ending && env.column > env.bestWidth) {
382                         writeIndent();
383                     } else {
384                         data = text.substring(start,ending);
385                         env.column += data.length;
386                         stream.write(data);
387                     }
388                     start = ending;
389                 }
390             } else {
391                 if(ceh == null || ' ' == ceh || '\n' == ceh || '\u0085' == ceh) {
392                     data = text.substring(start,ending);
393                     stream.write(data);
394                     if(ceh == null) {
395                         writeLineBreak(null);
396                     } 
397                     start = ending;
398                 }
399             }
400             if(ceh != null) {
401                 breaks = '\n' == ceh || '\u0085' == ceh;
402                 spaces = ceh == ' ';
403             }
404             ending++;
405         }
406     }
407
408     internal function writeLiteral(text : String):void {
409         var chomp:String= determineChomp(text);
410         writeIndicator("|" + chomp, true, false, false);
411         writeIndent();
412         var breaks:Boolean= false;
413         var start:int=0,ending:int=0;
414         var data:String= null;
415         while(ending <= text.length) {
416             var ceh : String = null;
417             if(ending < text.length) {
418                 ceh = text.charAt(ending);
419             }
420             if(breaks) {
421                 if(ceh == null || !('\n' == ceh || '\u0085' == ceh)) {
422                     data = text.substring(start,ending);
423                     for(var i:int=0,j:int=data.length;i<j;i++) {
424                         var cha : String = data.charAt(i);
425                         if('\n' == cha) {
426                             writeLineBreak(null);
427                         } else {
428                             writeLineBreak(""+cha);
429                         }
430                     }
431                     if(ceh != null) {
432                         writeIndent();
433                     }
434                     start = ending;
435                 }
436             } else {
437                 if(ceh == null || '\n' == ceh || '\u0085' == ceh) {
438                     data = text.substring(start,ending);
439                     stream.write(data);
440                     if(ceh == null) {
441                         writeLineBreak(null);
442                     }
443                     start = ending;
444                 }
445             }
446             if(ceh != null) {
447                 breaks = '\n' == ceh || '\u0085' == ceh;
448             }
449             ending++;
450         }
451     }
452
453     internal function writePlain(text : String, split : Boolean):void {
454         if(text == null || "" == text) {
455             return;
456         }
457         var data : String = null;
458         if(!env.whitespace) {
459             data = " ";
460             env.column += data.length;
461             stream.write(data);
462         }
463         env.whitespace = false;
464         env.indentation = false;
465         var spaces:Boolean=false, breaks : Boolean = false;
466         var start:int=0,ending : int=0;
467         while(ending <= text.length) {
468             var ceh : String = null;
469             if(ending < text.length) {
470                 ceh = text.charAt(ending);
471             }
472             if(spaces) {
473                 if(ceh != ' ') {
474                     if(start+1 == ending && env.column > env.bestWidth && split) {
475                         writeIndent();
476                         env.whitespace = false;
477                         env.indentation = false;
478                     } else {
479                         data = text.substring(start,ending);
480                         env.column += data.length;
481                        stream.write(data);
482                     }
483                     start = ending;
484                 }
485             } else if(breaks) {
486                 if(ceh != '\n' && ceh != '\u0085') {
487                     if(text.charAt(start) == '\n') {
488                         writeLineBreak(null);
489                     }
490                     data = text.substring(start,ending);
491                     for(var i:int=0,j:int=data.length;i<j;i++) {
492                         var cha : String = data.charAt(i);
493                         if('\n' == cha) {
494                             writeLineBreak(null);
495                         } else {
496                             writeLineBreak(""+cha);
497                         }
498                     }
499                     writeIndent();
500                     env.whitespace = false;
501                     env.indentation = false;
502                     start = ending;
503                 }
504             } else {
505                 if(ceh == null || ' ' == String(ceh) || '\n' == String(ceh) || '\u0085' == String(ceh)) {
506                     data = text.substring(start,ending);
507                     env.column += data.length;
508                     stream.write(data);
509                     start = ending;
510                 }
511             }
512             if(ceh != null) {
513                 spaces = String(ceh) == ' ';
514                 breaks = String(ceh) == '\n' || String(ceh) == '\u0085';
515             }
516             ending++;
517         }
518     }
519
520     internal function writeLineBreak(data:String):void {
521         var xdata:String= data;
522         if(xdata == null) {
523             xdata = env.bestLineBreak;
524         }
525         env.whitespace = true;
526         env.indentation = true;
527         env.line++;
528         env.column = 0;
529         stream.write(xdata);
530     }
531
532     internal function flushStream() : void {
533         stream.flush();
534     }
535
536     internal function prepareVersion(version : Array) : String {
537         if(version[0] != 1) {
538             throw new EmitterException("unsupported YAML version: " + version[0] + "." + version[1]);
539         }
540         return ""+version[0] + "." + version[1];
541     }
542     
543     private static var HANDLE_FORMAT : RegExp = new RegExp("^![-\\w]*!$");
544     
545     internal static function prepareTagHandle(handle : String):String{
546         if(handle == null || "" == handle) {
547             throw new EmitterException("tag handle must not be empty");
548         } else if(handle.charAt(0) != '!' || handle.charAt(handle.length-1) != '!') {
549             throw new EmitterException("tag handle must start and end with '!': " + handle);
550         } else if(!"!" == handle && !HANDLE_FORMAT.exec(handle)) {
551             throw new EmitterException("invalid syntax for tag handle: " + handle);
552         }
553         return handle;
554     }
555
556     internal static function prepareTagPrefix(prefix : String) : String {
557         if(prefix == null || "" == prefix) {
558             throw new EmitterException("tag prefix must not be empty");
559         }
560         var chunks : String = new String();
561         var start:int=0,ending:int=0;
562         if(prefix.charAt(0) == '!') {
563             ending = 1;
564         }
565         while(ending < prefix.length) {
566             ending++;
567         }
568         if(start < ending) {
569             chunks += prefix.substring(start,ending);
570         }
571         return chunks;
572     }
573
574     private static var ANCHOR_FORMAT : RegExp = new RegExp("^[-\\w]*$");
575     internal static function prepareAnchor(anchor : String) : String {
576         if(anchor == null || "" == anchor) {
577             throw new EmitterException("anchor must not be empty");
578         }
579         if(!ANCHOR_FORMAT.exec(anchor)) {
580             throw new EmitterException("invalid syntax for anchor: " + anchor);
581         }
582         return anchor;
583     }
584
585     internal function prepareTag(tag : String) : String {
586         if(tag == null || "" == tag) {
587             throw new EmitterException("tag must not be empty");
588         }
589         if(tag == "!") {
590             return tag;
591         }
592         var handle : String = null;
593         var suffix : String = tag;
594         for(var iter : Iterator = env.tagPrefixes.keySet().iterator();iter.hasNext();) {
595             var prefix : String = iter.next() as String;
596             if(new RegExp("^" + prefix + ".+$").exec(tag) && (prefix == "!" || prefix.length < tag.length)) {
597                 handle = env.tagPrefixes.get(prefix) as String;
598                 suffix = tag.substring(prefix.length);
599             }
600         }
601         var chunks : String = new String();
602         var start:int=0,ending:int=0;
603         while(ending < suffix.length) {
604             ending++;
605         }
606         if(start < ending) {
607             chunks += suffix.substring(start,ending);
608         }
609         var suffixText : String = chunks;
610         if(handle != null) {
611             return handle + suffixText;
612         } else {
613             return "!<" + suffixText + ">";
614         }
615     }
616
617     private static var DOC_INDIC : RegExp = new RegExp("^(---|\\.\\.\\.)");
618     private static var NULL_BL_T_LINEBR : String = "\x00 \t\r\n\u0085";
619     private static var SPECIAL_INDIC : String = "#,[]{}#&*!|>'\"%@`";
620     private static var FLOW_INDIC : String = ",?[]{}";
621     internal static function analyzeScalar(scalar : String) : ScalarAnalysis {
622         if(scalar == null || "" == scalar) {
623             return new ScalarAnalysis(scalar,true,false,false,true,true,true,false,false);
624         }
625                 var blockIndicators:Boolean= false;
626         var flowIndicators:Boolean= false;
627         var lineBreaks:Boolean= false;
628         var specialCharacters:Boolean= false;
629
630         // Whitespaces.
631         var inlineSpaces: Boolean = false;          // non-space space+ non-space
632         var inlineBreaks: Boolean = false;          // non-space break+ non-space
633         var leadingSpaces: Boolean = false;         // ^ space+ (non-space | $)
634         var leadingBreaks: Boolean = false;         // ^ break+ (non-space | $)
635         var trailingSpaces: Boolean = false;        // (^ | non-space) space+ $
636         var trailingBreaks: Boolean = false;        // (^ | non-space) break+ $
637         var inlineBreaksSpaces: Boolean = false;   // non-space break+ space+ non-space
638         var mixedBreaksSpaces: Boolean = false;    // anything else
639         
640         if(DOC_INDIC.exec(scalar)) {
641             blockIndicators = true;
642             flowIndicators = true;
643         }
644
645                 var preceededBySpace:Boolean= true;
646         var followedBySpace:Boolean= scalar.length == 1|| NULL_BL_T_LINEBR.indexOf(scalar.charAt(1)) != -1;
647
648         var spaces:Boolean= false;
649         var breaks:Boolean= false;
650         var mixed:Boolean= false;
651         var leading:Boolean= false;
652         
653         var index:int= 0;
654
655         while(index < scalar.length) {
656             var ceh : String = scalar.charAt(index);
657             if(index == 0) {
658                 if(SPECIAL_INDIC.indexOf(ceh) != -1) {
659                     flowIndicators = true;
660                     blockIndicators = true;
661                 }
662                 if(ceh == '?' || ceh == ':') {
663                     flowIndicators = true;
664                     if(followedBySpace) {
665                         blockIndicators = true;
666                     }
667                 }
668                 if(ceh == '-' && followedBySpace) {
669                     flowIndicators = true;
670                     blockIndicators = true;
671                 }
672             } else {
673                 if(FLOW_INDIC.indexOf(ceh) != -1) {
674                     flowIndicators = true;
675                 }
676                 if(ceh == ':') {
677                     flowIndicators = true;
678                     if(followedBySpace) {
679                         blockIndicators = true;
680                     }
681                 }
682                 if(ceh == '#' && preceededBySpace) {
683                     flowIndicators = true;
684                     blockIndicators = true;
685                 }
686             }
687             if(ceh == '\n' || '\u0085' == ceh) {
688                 lineBreaks = true;
689             }
690             if(!(ceh == '\n' || ('\u0020' <= ceh && ceh <= '\u007E'))) {
691                 specialCharacters = true;
692
693             }
694             if(' ' == ceh || '\n' == ceh || '\u0085' == ceh) {
695                 if(spaces && breaks) {
696                     if(ceh != ' ') {
697                         mixed = true;
698                     }
699                 } else if(spaces) {
700                     if(ceh != ' ') {
701                         breaks = true;
702                         mixed = true;
703                     }
704                 } else if(breaks) {
705                     if(ceh == ' ') {
706                         spaces = true;
707                     }
708                 } else {
709                     leading = (index == 0);
710                     if(ceh == ' ') {
711                         spaces = true;
712                     } else {
713                         breaks = true;
714                     }
715                 }
716             } else if(spaces || breaks) {
717                 if(leading) {
718                     if(spaces && breaks) {
719                         mixedBreaksSpaces = true;
720                     } else if(spaces) {
721                         leadingSpaces = true;
722                     } else if(breaks) {
723                         leadingBreaks = true;
724                     }
725                 } else {
726                     if(mixed) {
727                         mixedBreaksSpaces = true;
728                     } else if(spaces && breaks) {
729                         inlineBreaksSpaces = true;
730                     } else if(spaces) {
731                         inlineSpaces = true;
732                     } else if(breaks) {
733                         inlineBreaks = true;
734                     }
735                 }
736                 spaces = breaks = mixed = leading = false;
737             }
738
739             if((spaces || breaks) && (index == scalar.length-1)) {
740                 if(spaces && breaks) {
741                     mixedBreaksSpaces = true;
742                 } else if(spaces) {
743                     trailingSpaces = true;
744                     if(leading) {
745                         leadingSpaces = true;
746                     }
747                 } else if(breaks) {
748                     trailingBreaks = true;
749                     if(leading) {
750                         leadingBreaks = true;
751                     }
752                 }
753                 spaces = breaks = mixed = leading = false;
754             }
755             index++;
756             preceededBySpace = NULL_BL_T_LINEBR.indexOf(ceh) != -1;
757             followedBySpace = index+1 >= scalar.length || NULL_BL_T_LINEBR.indexOf(scalar.charAt(index+1)) != -1;
758         }
759                 var allowFlowPlain:Boolean= true;
760         var allowBlockPlain:Boolean= true;
761         var allowSingleQuoted:Boolean= true;
762         var allowDoubleQuoted:Boolean= true;
763         var allowBlock:Boolean= true;
764         
765         if(leadingSpaces || leadingBreaks || trailingSpaces) {
766             allowFlowPlain = allowBlockPlain = allowBlock = false;
767         }
768
769         if(trailingBreaks) {
770             allowFlowPlain = allowBlockPlain = false;
771         }
772
773         if(inlineBreaksSpaces) {
774             allowFlowPlain = allowBlockPlain = allowSingleQuoted = false;
775         }
776
777         if(mixedBreaksSpaces || specialCharacters) {
778             allowFlowPlain = allowBlockPlain = allowSingleQuoted = allowBlock = false;
779         }
780
781         if(inlineBreaks) {
782             allowFlowPlain = allowBlockPlain = allowSingleQuoted = false;
783         }
784         
785         if(trailingBreaks) {
786             allowSingleQuoted = false;
787         }
788
789         if(lineBreaks) {
790             allowFlowPlain = allowBlockPlain = false;
791         }
792
793         if(flowIndicators) {
794             allowFlowPlain = false;
795         }
796         
797         if(blockIndicators) {
798             allowBlockPlain = false;
799         }
800
801         return new ScalarAnalysis(scalar,false,lineBreaks,allowFlowPlain,allowBlockPlain,allowSingleQuoted,allowDoubleQuoted,allowBlock, specialCharacters);
802     }
803
804     internal static function determineChomp(text : String) : String {
805         var ceh : String = ' ';
806         var ceh2 : String =  ' ';
807         
808         if(text.length > 0) {
809             ceh = text.charAt(text.length-1);
810             if(text.length > 1) {
811                 ceh2 = text.charAt(text.length-2);
812             }
813         }
814                 
815         return (ceh == '\n' || ceh == '\u0085') ? ((ceh2 == '\n' || ceh2 == '\u0085') ? "+" : "") : "-";
816     }
817
818 }
819 }
820    
821