d9a77302e5cb6a6b1aff56e114b3e1b75e3c7e40
[potlatch2.git] / org / as3yaml / Parser.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  
24 package org.as3yaml {
25
26 import flash.utils.getQualifiedClassName;
27
28 import org.as3yaml.events.*;
29 import org.as3yaml.tokens.*;
30 import org.idmedia.as3commons.util.*;
31 import org.as3yaml.util.StringUtils;
32
33 public class Parser {
34     // Memnonics for the production table
35     private const P_STREAM: int = 0;
36     private const P_STREAM_START: int = 1; // TERMINAL
37     private const P_STREAM_END: int = 2; // TERMINAL
38     private const P_IMPLICIT_DOCUMENT: int = 3;
39     private const P_EXPLICIT_DOCUMENT: int = 4;
40     private const P_DOCUMENT_START: int = 5;
41     private const P_DOCUMENT_START_IMPLICIT: int = 6;
42     private const P_DOCUMENT_END: int = 7;
43     private const P_BLOCK_NODE: int = 8;
44     private const P_BLOCK_CONTENT: int = 9;
45     private const P_PROPERTIES: int = 10;
46     private const P_PROPERTIES_END: int = 11;
47     private const P_FLOW_CONTENT: int = 12;
48     private const P_BLOCK_SEQUENCE: int = 13;
49     private const P_BLOCK_MAPPING: int = 14;
50     private const P_FLOW_SEQUENCE: int = 15;
51     private const P_FLOW_MAPPING: int = 16;
52     private const P_SCALAR: int = 17;
53     private const P_BLOCK_SEQUENCE_ENTRY: int = 18;
54     private const P_BLOCK_MAPPING_ENTRY: int = 19;
55     private const P_BLOCK_MAPPING_ENTRY_VALUE: int = 20;
56     private const P_BLOCK_NODE_OR_INDENTLESS_SEQUENCE: int = 21;
57     private const P_BLOCK_SEQUENCE_START: int = 22;
58     private const P_BLOCK_SEQUENCE_END: int = 23;
59     private const P_BLOCK_MAPPING_START: int = 24;
60     private const P_BLOCK_MAPPING_END: int = 25;
61     private const P_INDENTLESS_BLOCK_SEQUENCE: int = 26;
62     private const P_BLOCK_INDENTLESS_SEQUENCE_START: int = 27;
63     private const P_INDENTLESS_BLOCK_SEQUENCE_ENTRY: int = 28;
64     private const P_BLOCK_INDENTLESS_SEQUENCE_END: int = 29;
65     private const P_FLOW_SEQUENCE_START: int = 30;
66     private const P_FLOW_SEQUENCE_ENTRY: int = 31;
67     private const P_FLOW_SEQUENCE_END: int = 32;
68     private const P_FLOW_MAPPING_START: int = 33;
69     private const P_FLOW_MAPPING_ENTRY: int = 34;
70     private const P_FLOW_MAPPING_END: int = 35;
71     private const P_FLOW_INTERNAL_MAPPING_START: int = 36;
72     private const P_FLOW_INTERNAL_CONTENT: int = 37;
73     private const P_FLOW_INTERNAL_VALUE: int = 38;
74     private const P_FLOW_INTERNAL_MAPPING_END: int = 39;
75     private const P_FLOW_ENTRY_MARKER: int = 40;
76     private const P_FLOW_NODE: int = 41;
77     private const P_FLOW_MAPPING_INTERNAL_CONTENT: int = 42;
78     private const P_FLOW_MAPPING_INTERNAL_VALUE: int = 43;
79     private const P_ALIAS: int = 44;
80     private const P_EMPTY_SCALAR: int = 45;
81
82     private var DOCUMENT_END_TRUE: Event  = new DocumentEndEvent(true);
83     private var DOCUMENT_END_FALSE: Event  = new DocumentEndEvent(false);
84     private var MAPPING_END: Event  = new MappingEndEvent();
85     private var SEQUENCE_END: Event  = new SequenceEndEvent();
86     private var STREAM_END: Event  = new StreamEndEvent();
87     private var STREAM_START: Event  = new StreamStartEvent();
88
89     private const P_TABLE : Array = [];
90
91     private var DEFAULT_TAGS_1_0 : Map = new HashMap();
92     private var DEFAULT_TAGS_1_1 : Map = new HashMap();
93         
94         private var ONLY_WORD : RegExp = new RegExp("^\\w+$");
95
96     private var tags:Array;
97     private var anchors:Array;
98     private var tagHandles:Map;
99     private var yamlVersion:Array;
100     private var defaultYamlVersion:Array;
101
102         
103    public function produce(eventId: int) : Event {
104         
105                 switch (eventId)
106                 {
107                 case P_STREAM:
108                     parseStack.unshift(P_STREAM_END);
109                     parseStack.unshift(P_EXPLICIT_DOCUMENT);
110                     parseStack.unshift(P_IMPLICIT_DOCUMENT);
111                     parseStack.unshift(P_STREAM_START);
112                     return null;
113                 
114                 case P_STREAM_START:
115                         scanner.getToken();
116                                 return STREAM_START;
117                         
118                         case P_STREAM_END:
119                     scanner.getToken();
120                     return STREAM_END;
121                     
122                 case P_IMPLICIT_DOCUMENT:
123                     var curr7 : Token = scanner.peekToken();
124                     if(!(curr7 is DirectiveToken || curr7 is DocumentStartToken || curr7 is StreamEndToken)) {
125                         parseStack.unshift(P_DOCUMENT_END);
126                         parseStack.unshift(P_BLOCK_NODE);
127                         parseStack.unshift(P_DOCUMENT_START_IMPLICIT);
128                     }
129                     return null;
130                 
131                 case P_EXPLICIT_DOCUMENT:
132                     if(!(scanner.peekToken() is StreamEndToken)) {
133                         parseStack.unshift(P_EXPLICIT_DOCUMENT);
134                         parseStack.unshift(P_DOCUMENT_END);
135                         parseStack.unshift(P_BLOCK_NODE);
136                         parseStack.unshift(P_DOCUMENT_START);
137                     }
138                     return null;
139                
140                case P_DOCUMENT_START:
141                     var tok1 : Token = scanner.peekToken();
142                     var directives1 : Array = processDirectives(scanner);
143                     if(!(scanner.peekToken() is DocumentStartToken)) {
144                         throw new ParserException(null,"expected '<document start>', but found " + getQualifiedClassName(tok1),null);
145                     }
146                     scanner.getToken();
147                     return new DocumentStartEvent(true, directives1[0], directives1[1]);
148                
149                case P_DOCUMENT_START_IMPLICIT:
150                 var directives2 : Array = processDirectives(scanner);
151                 return new DocumentStartEvent(false,directives2[0], directives2[1]);           
152                
153                case P_DOCUMENT_END:
154                     var tok2 : Token = scanner.peekToken();
155                     var explicit : Boolean = false;
156                     while(scanner.peekToken() is DocumentEndToken) {
157                         scanner.getToken();
158                         explicit = true;
159                     }
160                     return explicit ? DOCUMENT_END_TRUE : DOCUMENT_END_FALSE;
161                
162                case P_BLOCK_NODE:
163                 var curr8 : Token = scanner.peekToken();
164                 if(curr8 is DirectiveToken || curr8 is DocumentStartToken || curr8 is DocumentEndToken || curr8 is StreamEndToken) {
165                     parseStack.unshift(P_EMPTY_SCALAR);
166                 } else {
167                     if(curr8 is AliasToken) {
168                         parseStack.unshift(P_ALIAS);
169                     } else {
170                         parseStack.unshift(P_PROPERTIES_END);
171                         parseStack.unshift(P_BLOCK_CONTENT);
172                         parseStack.unshift(P_PROPERTIES);
173                     }
174                 }
175                 return null;
176            
177            case P_BLOCK_CONTENT:
178                 var tok : Token = scanner.peekToken();
179                 if(tok is BlockSequenceStartToken) {
180                     parseStack.unshift(P_BLOCK_SEQUENCE);
181                 } else if(tok is BlockMappingStartToken) {
182                     parseStack.unshift(P_BLOCK_MAPPING);
183                 } else if(tok is FlowSequenceStartToken) {
184                     parseStack.unshift(P_FLOW_SEQUENCE);
185                 } else if(tok is FlowMappingStartToken) {
186                     parseStack.unshift(P_FLOW_MAPPING);
187                 } else if(tok is ScalarToken) {
188                     parseStack.unshift(P_SCALAR);
189                 } else {
190                     return new ScalarEvent(anchors[0],tags[0],[false,false],null,'\'');
191                 }
192                 return null;
193            
194            case P_PROPERTIES:
195                 var anchor : String = null;
196                 var tokValue : Array  = null;
197                 var tag: String = null;
198                 if(scanner.peekToken() is AnchorToken) {
199                     anchor = AnchorToken(scanner.getToken()).getValue();
200                     if(scanner.peekToken() is TagToken) {
201                         scanner.getToken();
202                     }
203                 } else if(scanner.peekToken() is TagToken) {
204                     tokValue = TagToken(scanner.getToken()).getValue();
205                     if(scanner.peekToken() is AnchorToken) {
206                         anchor = AnchorToken(scanner.getToken()).getValue();
207                     }
208                 }
209                 if(tokValue != null) {
210                     var handle : String = tokValue[0];
211                     var suffix : String = tokValue[1];
212                     var ix : int = -1;
213 //                    if((ix = suffix.indexOf("^")) != -1) {
214 //                        suffix = suffix.substring(0,ix) + suffix.substring(ix+1);
215 //                    }
216 //                    if(handle != null) {
217 //                        if(!env.getTagHandles().containsKey(handle)) {
218 //                            throw new ParserException("while parsing a node","found undefined tag handle " + handle,null);
219 //                        }
220 //                        if((ix = suffix.indexOf("/")) != -1) {
221 //                            var before : String = suffix.substring(0,ix);
222 //                            var after : String = suffix.substring(ix+1);
223 //                            if(ONLY_WORD.exec(before)) {
224 //                                tag = "tag:" + before + ".yaml.org,2002:" + after;
225 //                            } else {
226 //                                if(StringUtils.startsWith(before, "tag:")) {
227 //                                    tag = before + ":" + after;
228 //                                } else {
229 //                                    tag = "tag:" + before + ":" + after;
230 //                                }
231 //                            }
232 //                        } else {
233                             tag = (tagHandles.get(handle)) + suffix;
234 //                        }
235                         
236                     } else {
237                         tag = suffix;
238                     }
239
240                 anchors.unshift(anchor);
241                 tags.unshift(tag);
242                 return null;           
243            
244                 case P_PROPERTIES_END:
245                 anchors.shift();
246                 tags.shift();
247                 return null;
248                     
249                 case P_FLOW_CONTENT:
250                 var tok3 : Token = scanner.peekToken();
251                 if(tok3 is FlowSequenceStartToken) {
252                     parseStack.unshift(P_FLOW_SEQUENCE);
253                 } else if(tok3 is FlowMappingStartToken) {
254                     parseStack.unshift(P_FLOW_MAPPING);
255                 } else if(tok3 is ScalarToken) {
256                     parseStack.unshift(P_SCALAR);
257                 } else {
258                     throw new ParserException("while scanning a flow node","expected the node content, but found " + getQualifiedClassName(tok3),null);
259                 }
260                 return null;
261                     
262                case P_BLOCK_SEQUENCE:
263                 parseStack.unshift(P_BLOCK_SEQUENCE_END);
264                 parseStack.unshift(P_BLOCK_SEQUENCE_ENTRY);
265                 parseStack.unshift(P_BLOCK_SEQUENCE_START);
266                 return null;
267                     
268                case P_BLOCK_MAPPING:
269                 parseStack.unshift(P_BLOCK_MAPPING_END);
270                 parseStack.unshift(P_BLOCK_MAPPING_ENTRY);
271                 parseStack.unshift(P_BLOCK_MAPPING_START);
272                 return null;
273                     
274                case P_FLOW_SEQUENCE:
275                 parseStack.unshift(P_FLOW_SEQUENCE_END);
276                 parseStack.unshift(P_FLOW_SEQUENCE_ENTRY);
277                 parseStack.unshift(P_FLOW_SEQUENCE_START);
278                 return null;
279                     
280                case P_FLOW_MAPPING:
281                 parseStack.unshift(P_FLOW_MAPPING_END);
282                 parseStack.unshift(P_FLOW_MAPPING_ENTRY);
283                 parseStack.unshift(P_FLOW_MAPPING_START);
284                 return null;
285                     
286                case P_SCALAR:
287                 var token : ScalarToken = scanner.getToken() as ScalarToken;
288                 var implicit : Array = null;
289                 if((token.getPlain() && tags[0] == null) || "!" == (tags[0])) {
290                     implicit = [true,false];
291                 } else if(tags[0] == null) {
292                     implicit = [false,true];
293                 } else {
294                     implicit = [false,false];
295                 }
296                 return new ScalarEvent(anchors[0],tags[0],implicit,token.getValue(),token.getStyle());
297                     
298                case P_BLOCK_SEQUENCE_ENTRY:
299                 if(scanner.peekToken() is BlockEntryToken) {
300                     scanner.getToken();
301                     var curr1: Token = scanner.peekToken();
302                     if(!(curr1 is BlockEntryToken || curr1 is BlockEndToken)) {
303                         parseStack.unshift(P_BLOCK_SEQUENCE_ENTRY);
304                         parseStack.unshift(P_BLOCK_NODE);
305                     } else {
306                         parseStack.unshift(P_BLOCK_SEQUENCE_ENTRY);
307                         parseStack.unshift(P_EMPTY_SCALAR);
308                     }
309                 }
310                 return null;
311                     
312                case P_BLOCK_MAPPING_ENTRY:
313                 var last : Token = scanner.peekToken();
314                 if(last is KeyToken || last is ValueToken) {
315                     if(last is KeyToken) {
316                         scanner.getToken();
317                         var curr2 : Token = scanner.peekToken();
318                         if(!(curr2 is KeyToken || curr2 is ValueToken || curr2 is BlockEndToken)) {
319                             parseStack.unshift(P_BLOCK_MAPPING_ENTRY);
320                             parseStack.unshift(P_BLOCK_MAPPING_ENTRY_VALUE);
321                             parseStack.unshift(P_BLOCK_NODE_OR_INDENTLESS_SEQUENCE);
322                         } else {
323                             parseStack.unshift(P_BLOCK_MAPPING_ENTRY);
324                             parseStack.unshift(P_BLOCK_MAPPING_ENTRY_VALUE);
325                             parseStack.unshift(P_EMPTY_SCALAR);
326                         }
327                     } else {
328                         parseStack.unshift(P_BLOCK_MAPPING_ENTRY);
329                         parseStack.unshift(P_BLOCK_MAPPING_ENTRY_VALUE);
330                         parseStack.unshift(P_EMPTY_SCALAR);
331                     }
332                 }
333                 return null;
334                     
335                case P_BLOCK_MAPPING_ENTRY_VALUE:
336                 var last2: Token = scanner.peekToken();
337                 if (last2 is KeyToken || last2 is ValueToken) {
338                     if(last2 is ValueToken) {
339                         scanner.getToken();
340                         var curr3 : Token = scanner.peekToken();
341                         if(!(curr3 is KeyToken || curr3 is ValueToken || curr3 is BlockEndToken)) {
342                             parseStack.unshift(P_BLOCK_NODE_OR_INDENTLESS_SEQUENCE);
343                         } else {
344                             parseStack.unshift(P_EMPTY_SCALAR);
345                         }
346                     } else {
347                         parseStack.unshift(P_EMPTY_SCALAR);
348                     }
349                 }
350
351                 return null;
352                     
353                case P_BLOCK_NODE_OR_INDENTLESS_SEQUENCE:
354                 var last3: Token = scanner.peekToken();
355                 if(last3 is AliasToken) {
356                     parseStack.unshift(P_ALIAS);
357                 } else {
358                     if(last3 is BlockEntryToken) {
359                         parseStack.unshift(P_INDENTLESS_BLOCK_SEQUENCE);
360                         parseStack.unshift(P_PROPERTIES);
361                     } else {
362                         parseStack.unshift(P_BLOCK_CONTENT);
363                         parseStack.unshift(P_PROPERTIES);
364                     }
365                 }
366                 return null;
367                     
368                case P_BLOCK_SEQUENCE_START:
369                 var impl1 : Boolean = tags[0] == null || tags[0] == "!";
370                 scanner.getToken();
371                 return new SequenceStartEvent(anchors[0], tags[0], impl1,false);
372                     
373                case P_BLOCK_SEQUENCE_END:
374                 var tok4 : Token = null;
375                 if(!(scanner.peekToken() is BlockEndToken)) {
376                     tok4 = scanner.peekToken();
377                     throw new ParserException("while scanning a block collection","expected <block end>, but found " + getQualifiedClassName(tok4),null);
378                 }
379                 scanner.getToken();
380                 return SEQUENCE_END;
381                     
382                case P_BLOCK_MAPPING_START:
383                 var impl2 : Boolean = tags[0] == null || tags[0] == "!";
384                 scanner.getToken();
385                 return new MappingStartEvent(anchors[0], tags[0], impl2,false);
386                     
387                case P_BLOCK_MAPPING_END:
388                 var tok5 : Token = scanner.peekToken();
389                 if(!(tok5 is BlockEndToken)) {
390                     throw new ParserException("while scanning a block mapping","expected <block end>, but found " + getQualifiedClassName(tok5),null);
391                 }
392                 scanner.getToken();
393                 return MAPPING_END;
394                     
395                case P_INDENTLESS_BLOCK_SEQUENCE:
396                 parseStack.unshift(P_BLOCK_INDENTLESS_SEQUENCE_END);
397                 parseStack.unshift(P_INDENTLESS_BLOCK_SEQUENCE_ENTRY);
398                 parseStack.unshift(P_BLOCK_INDENTLESS_SEQUENCE_START);
399                 return null;
400                     
401                case P_BLOCK_INDENTLESS_SEQUENCE_START:
402                 var impl3 : Boolean = tags[0] == null || tags[0] == "!";
403                 return new SequenceStartEvent(anchors[0], tags[0], impl3, false);
404                     
405                case P_INDENTLESS_BLOCK_SEQUENCE_ENTRY:
406                 if(scanner.peekToken() is BlockEntryToken) {
407                     scanner.getToken();
408                     var curr4 : Token = scanner.peekToken();
409                     if(!(curr4 is BlockEntryToken || curr4 is KeyToken || curr4 is ValueToken || curr4 is BlockEndToken)) {
410                         parseStack.unshift(P_INDENTLESS_BLOCK_SEQUENCE_ENTRY);
411                         parseStack.unshift(P_BLOCK_NODE);
412                     } else {
413                         parseStack.unshift(P_INDENTLESS_BLOCK_SEQUENCE_ENTRY);
414                         parseStack.unshift(P_EMPTY_SCALAR);
415                     }
416                 }
417                 return null;
418                     
419                case P_BLOCK_INDENTLESS_SEQUENCE_END:
420                 return SEQUENCE_END;
421                     
422                case P_FLOW_SEQUENCE_START:
423                 var impl4 : Boolean = tags[0] == null || tags[0] == "!";
424                 scanner.getToken();
425                 return new SequenceStartEvent(anchors[0], tags[0], impl4,true);
426                     
427                case P_FLOW_SEQUENCE_ENTRY:
428                 if(!(scanner.peekToken() is FlowSequenceEndToken)) {
429                     if(scanner.peekToken() is KeyToken) {
430                         parseStack.unshift(P_FLOW_SEQUENCE_ENTRY);
431                         parseStack.unshift(P_FLOW_ENTRY_MARKER);
432                         parseStack.unshift(P_FLOW_INTERNAL_MAPPING_END);
433                         parseStack.unshift(P_FLOW_INTERNAL_VALUE);
434                         parseStack.unshift(P_FLOW_INTERNAL_CONTENT);
435                         parseStack.unshift(P_FLOW_INTERNAL_MAPPING_START);
436                     } else {
437                         parseStack.unshift(P_FLOW_SEQUENCE_ENTRY);
438                         parseStack.unshift(P_FLOW_NODE);
439                         parseStack.unshift(P_FLOW_ENTRY_MARKER);
440                     }
441                 }
442                 return null;
443                     
444                case P_FLOW_SEQUENCE_END:
445                 scanner.getToken();
446                 return SEQUENCE_END;
447                     
448                case P_FLOW_MAPPING_START:
449                 var impl5 : Boolean = tags[0] == null || tags[0] == "!";
450                 scanner.getToken();
451                 return new MappingStartEvent(anchors[0], tags[0], impl5,true);
452                     
453                case P_FLOW_MAPPING_ENTRY:
454                 if(!(scanner.peekToken() is FlowMappingEndToken)) {
455                     if(scanner.peekToken() is KeyToken) {
456                         parseStack.unshift(P_FLOW_MAPPING_ENTRY);
457                         parseStack.unshift(P_FLOW_ENTRY_MARKER);
458                         parseStack.unshift(P_FLOW_MAPPING_INTERNAL_VALUE);
459                         parseStack.unshift(P_FLOW_MAPPING_INTERNAL_CONTENT);
460                     } else {
461                         parseStack.unshift(P_FLOW_MAPPING_ENTRY);
462                         parseStack.unshift(P_FLOW_NODE);
463                         parseStack.unshift(P_FLOW_ENTRY_MARKER);
464                     }
465                 }
466                 return null;
467                     
468                case P_FLOW_MAPPING_END:
469                 scanner.getToken();
470                 return MAPPING_END;
471                     
472                case P_FLOW_INTERNAL_MAPPING_START:
473                 scanner.getToken();
474                 return new MappingStartEvent(null,null,true,true);
475                     
476                case P_FLOW_INTERNAL_CONTENT:
477                 var curr5 : Token = scanner.peekToken();
478                 if(!(curr5 is ValueToken || curr5 is FlowEntryToken || curr5 is FlowSequenceEndToken)) {
479                     parseStack.unshift(P_FLOW_NODE);
480                 } else {
481                     parseStack.unshift(P_EMPTY_SCALAR);
482                 }
483                 return null;
484                     
485                case P_FLOW_INTERNAL_VALUE:
486                 if(scanner.peekToken() is ValueToken) {
487                     scanner.getToken();
488                     if(!((scanner.peekToken() is FlowEntryToken) || (scanner.peekToken() is FlowSequenceEndToken))) {
489                         parseStack.unshift(P_FLOW_NODE);
490                     } else {
491                         parseStack.unshift(P_EMPTY_SCALAR);
492                     }
493                 } else {
494                     parseStack.unshift(P_EMPTY_SCALAR);
495                 }
496                 return null;
497                     
498                case P_FLOW_INTERNAL_MAPPING_END:
499                 return MAPPING_END;
500                     
501                case P_FLOW_ENTRY_MARKER:
502                 if(scanner.peekToken() is FlowEntryToken) {
503                     scanner.getToken();
504                 }
505                 return null;
506                     
507                case P_FLOW_NODE:
508                 if(scanner.peekToken() is AliasToken) {
509                     parseStack.unshift(P_ALIAS);
510                 } else {
511                     parseStack.unshift(P_PROPERTIES_END);
512                     parseStack.unshift(P_FLOW_CONTENT);
513                     parseStack.unshift(P_PROPERTIES);
514                 }
515                 return null;
516                     
517                case P_FLOW_MAPPING_INTERNAL_CONTENT:
518                 var curr6 : Token = scanner.peekToken();
519                 if(!(curr6 is ValueToken || curr6 is FlowEntryToken || curr6 is FlowMappingEndToken)) {
520                     scanner.getToken();
521                     parseStack.unshift(P_FLOW_NODE);
522                 } else {
523                     parseStack.unshift(P_EMPTY_SCALAR);
524                 }
525                 return null;
526                     
527                case P_FLOW_MAPPING_INTERNAL_VALUE:
528                 if(scanner.peekToken() is ValueToken) {
529                     scanner.getToken();
530                     if(!(scanner.peekToken() is FlowEntryToken || scanner.peekToken() is FlowMappingEndToken)) {
531                         parseStack.unshift(P_FLOW_NODE);
532                     } else {
533                         parseStack.unshift(P_EMPTY_SCALAR);
534                     }
535                 } else {
536                     parseStack.unshift(P_EMPTY_SCALAR);
537                 }
538                 return null;
539                     
540                case P_ALIAS:
541                 var aTok : AliasToken = scanner.getToken() as AliasToken;
542                 return new AliasEvent(aTok.getValue());
543                     
544                case P_EMPTY_SCALAR:
545                     return processEmptyScalar();
546             
547                         }
548                         
549                 return null;
550                                                                                 
551         }
552
553  
554
555     internal static function processEmptyScalar() : Event {
556         return new ScalarEvent(null,null,[true,false],"", '0');
557     }
558
559     private function processDirectives(scanner: Scanner) : Array {
560         while(scanner.peekToken() is DirectiveToken) {
561             var tok : DirectiveToken = DirectiveToken(scanner.getToken());
562             if(tok.getName() == ("YAML")) {
563                 if(yamlVersion != null) {
564                     throw new ParserException(null,"found duplicate YAML directive",null);
565                 }
566                 var major : int = int(tok.getValue()[0]);
567                 var minor : int = int(tok.getValue()[1]);
568                 if(major != 1) {
569                     throw new ParserException(null,"found incompatible YAML document (version 1.* is required)",null);
570                 }
571                 yamlVersion = [major,minor];
572             } else if(tok.getName() == ("TAG")) {
573                 var handle : String = tok.getValue()[0];
574                 var prefix : String = tok.getValue()[1];
575                 if(tagHandles.containsKey(handle)) {
576                     throw new ParserException(null,"duplicate tag handle " + handle,null);
577                 }
578                 tagHandles.put(handle,prefix);
579             }
580         }
581         var value : Array = new Array();
582         value[0] = getFinalYamlVersion();
583
584         if(!tagHandles.isEmpty()) {
585             value[1] = new HashMap().putAll(tagHandles);
586         }
587
588         var baseTags : Map = value[0][1] == 0 ? DEFAULT_TAGS_1_0 : DEFAULT_TAGS_1_1;
589         for(var iter : Iterator = baseTags.keySet().iterator(); iter.hasNext();) {
590             var key : Object = iter.next();
591             if(!tagHandles.containsKey(key)) {
592                 tagHandles.put(key,baseTags.get(key));
593             }
594         }
595         return value;
596     }
597
598     private var scanner : Scanner = null;
599     private var cfg : YAMLConfig = null;
600
601     public function Parser(scanner : Scanner, cfg : YAMLConfig) {
602
603         DEFAULT_TAGS_1_0.put("!","tag:yaml.org,2002:");
604                 DEFAULT_TAGS_1_0.put("!!","");
605
606         DEFAULT_TAGS_1_1.put("!","!");
607         DEFAULT_TAGS_1_1.put("!!","tag:yaml.org,2002:");        
608         
609         this.scanner = scanner;
610         this.tags = new Array();
611         this.anchors = new Array();
612         this.tagHandles = new HashMap();
613         this.yamlVersion = null;
614         this.defaultYamlVersion = [];
615         this.defaultYamlVersion[0] = int(cfg.getVersion().substring(0,cfg.getVersion().indexOf('.')));
616         this.defaultYamlVersion[1] = int(cfg.getVersion().substring(cfg.getVersion().indexOf('.')+1));
617     }
618
619     public function getFinalYamlVersion() : Array {
620         if(null == this.yamlVersion) {
621             return this.defaultYamlVersion;
622         }
623         return this.yamlVersion;
624     }
625
626     private var currentEvent : Event = null;
627
628     public function checkEvent(choices : Array) : Boolean {
629         parseStream();
630         if(this.currentEvent == null) {
631             this.currentEvent = parseStreamNext();
632         }
633         if(this.currentEvent != null) {
634             if(choices.length == 0) {
635                 return true;
636             }
637             for(var i : int = 0; i < choices.length; i++) {
638                 if(choices[i] == this.currentEvent) {
639                     return true;
640                 }
641             }
642         }
643         return false;
644     }
645
646     public function peekEvent() : Event {
647         if (!parseStack) parseStream();
648         if(this.currentEvent == null) {
649             this.currentEvent = parseStreamNext();
650         }
651                         
652         return this.currentEvent;
653     }
654
655     public function getEvent() : Event {
656         parseStream();
657         if(this.currentEvent == null) {
658             this.currentEvent = parseStreamNext();
659         }
660         var value : Event = this.currentEvent;
661         this.currentEvent = null;
662         return value;
663     }
664
665     public function eachEvent(parser : Parser) : EventIterator {
666         return new EventIterator(parser);
667     }
668
669     public function iterator() : EventIterator {
670         return eachEvent(this);
671     }
672
673     private var parseStack : Array = null;
674
675     public function parseStream() : void {
676         if(null == parseStack) {
677             this.parseStack = new Array();
678             this.parseStack.push(P_STREAM);
679         }
680     }
681
682     public function parseStreamNext() : Event {
683         while(parseStack.length > 0) {
684                 var eventId : int = parseStack.shift() as int;
685             var value : Event = this.produce(eventId) as Event;
686            
687             if(value) {
688                 return value;
689             }
690         }
691
692         return null;
693     }
694
695 }
696 }
697         import org.as3yaml.Parser;
698         import org.as3yaml.events.Event;
699         
700
701 internal class EventIterator {
702    
703    private var parser : Parser;
704    public function EventIterator (parser : Parser) : void{
705         this.parser = parser;
706    }
707    
708     public function hasNext() : Boolean {
709         return null != parser.peekEvent();
710     }
711
712     public function next() : Event {
713         return parser.getEvent();
714     }
715
716     public function remove() : void {
717     }
718 }