2005-08-23 Iain McCoy <iain@mccoy.id.au>
[mono.git] / mcs / class / PresentationFramework / Mono.Windows.Serialization / XamlParser.cs
1 //
2 // XamlParser.cs
3 //
4 // Author:
5 //   Iain McCoy (iain@mccoy.id.au)
6 //
7 // (C) 2005 Iain McCoy
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29
30 using System;
31 using System.Collections;
32 using System.Diagnostics;
33 using System.IO;
34 using System.Xml;
35 using System.Reflection;
36 using System.Windows;
37 using System.Windows.Serialization;
38
39 namespace Mono.Windows.Serialization {
40         public class XamlParser {
41                 public const string XAML_NAMESPACE = "http://schemas.microsoft.com/winfx/xaml/2005";
42                 private Mapper mapper = new Mapper(new string[] { });
43                 private XmlTextReader reader;
44                 private ArrayList nodeQueue = new ArrayList();
45
46                 private enum CurrentType { Object, 
47                         Property, 
48                         PropertyObject,
49                         DependencyProperty,
50                         Code }
51
52                 private class ParserState {
53                         public object obj;
54                         public CurrentType type;
55                 }
56         
57                 private bool begun = false;
58
59                 private ParserState currentState() {
60                         if (oldStates.Count == 0) return null;
61                         return (ParserState)oldStates[oldStates.Count - 1];
62                 }
63                 private ArrayList oldStates = new ArrayList();
64
65                 int tempStateCount = 0;
66                 private int getDepth() {
67                         return oldStates.Count - tempStateCount;
68                 }
69         
70                 public XamlParser(string filename) : this(
71                                 new XmlTextReader(filename))
72                 {
73                 }
74                 
75                 public XamlParser(TextReader reader) : this(
76                                 new XmlTextReader(reader))
77                 {
78                 }
79                 
80                 public XamlParser(XmlTextReader reader)
81                 {
82                         this.reader = reader;
83                 }
84
85                 private XamlNode topNode()
86                 {
87                         return (XamlNode)nodeQueue[nodeQueue.Count - 1];
88                 }
89                 
90                 public XamlNode GetNextNode()
91                 {
92                         if (nodeQueue.Count != 0) {
93                                 XamlNode x = (XamlNode)nodeQueue[0];
94                                 nodeQueue.RemoveAt(0);
95                                 return x;
96                         }
97                         while (reader.Read()) {
98                                 Debug.WriteLine("XamlParser: NOW PARSING: " + reader.NodeType + "; " + reader.Name + "; " + reader.Value);
99                                 if (goneTooFar())
100                                         throw new Exception("Too far: " + reader.NodeType + ", " + reader.Name);
101                                 if (currentState() != null && currentState().type == CurrentType.Code)
102                                 {
103                                         processElementInCodeState();
104                                         continue;
105                                 }
106                                 switch (reader.NodeType) {
107                                 case XmlNodeType.ProcessingInstruction:
108                                         parsePI();
109                                         break;
110                                 case XmlNodeType.Element:
111                                         parseElement();
112                                         break;
113                                 case XmlNodeType.EndElement:
114                                         parseEndElement();
115                                         break;
116                                 case XmlNodeType.Text:
117                                         parseText();
118                                         break;
119                                 case XmlNodeType.Whitespace:
120                                 case XmlNodeType.Comment:
121                                         // skip whitespace and comments
122                                         break;
123                                 default:
124                                         throw new Exception("Unknown element type " + reader.NodeType);
125                                 }
126                                 if (nodeQueue.Count != 0) {
127                                         XamlNode x = (XamlNode)nodeQueue[0];
128                                         nodeQueue.RemoveAt(0);
129                                         return x;
130                                 }
131                         }
132                         return null;
133                 }
134                 void processElementInCodeState()
135                 {
136                         if (reader.NodeType == XmlNodeType.EndElement &&
137                                         reader.LocalName == "Code" && 
138                                         reader.NamespaceURI == XAML_NAMESPACE) {
139                                 parseEndElement();
140                         } else if (reader.NodeType != XmlNodeType.CDATA && reader.NodeType != XmlNodeType.Text) {
141                                 throw new Exception("Code element children must be either text or CDATA nodes.");
142                         } else {
143                                 currentState().obj = (string)currentState().obj + reader.Value;
144                         }
145                 }
146                 bool goneTooFar()
147                 {
148
149                         if (begun && 
150                                         currentState() == null && 
151                                         reader.NodeType != XmlNodeType.Whitespace && 
152                                         reader.NodeType != XmlNodeType.Comment)
153                                 return true;
154                         else
155                                 return false;
156                 }
157
158                 void parsePI()
159                 {
160                         if (reader.Name != "Mapping")
161                                 throw new Exception("Unknown processing instruction.");
162                         mapper.AddMappingProcessingInstruction(reader.Value);
163                 }
164
165                 void parseElement()
166                 {
167                         if (reader.NamespaceURI == "")
168                                 throw new Exception("No xml namespace specified.");
169                         if (reader.LocalName == "Code" && reader.NamespaceURI == XAML_NAMESPACE) {
170                                 parseCodeElement();
171                                 return;
172                         }
173                         // This element must be an object if:
174                         //  - It's a direct child of a property element
175                         //  - It's a direct child of an IAddChild element
176                         //    and does not have a dot in its name
177                         //    
178                         //  We just check that it doesn't have a dot in it here
179                         //  since parseObjectElement will confirm that it is
180                         //  a direct child of an IAddChild.
181                         //
182                         //  If it's a dotted name, then it is a property.
183                         //  What it is a property of depends on the bit of the
184                         //  name before the dot.
185                         int dotPosition = reader.LocalName.IndexOf('.');
186                         if (dotPosition < 0 ||
187                                         currentState().type == CurrentType.Property) {
188                                 parseObjectElement();
189                                 return;
190                         }
191                         string beforeDot = reader.LocalName.Substring(0, dotPosition);
192                         string afterDot = reader.LocalName.Substring(dotPosition + 1);
193                         // If we've got this far, then currentState().Type == Object
194                         if (isNameOfAncestorClass(beforeDot, (Type)currentState().obj))
195                                 parseNormalPropertyElement(afterDot);
196                         else
197                                 parseDependencyPropertyElement(beforeDot, afterDot);
198                 }
199
200                 // check if the given name is the name of an ancestor of 
201                 // the given type
202                 bool isNameOfAncestorClass(string name, Type t)
203                 {
204                         if (name == "object")
205                                 return true;
206                         while (t.BaseType != null) {
207                                 if (t.Name == name)
208                                         return true;
209                                 t = t.BaseType;
210                         }
211                         return false;
212                 }
213
214                 // handle an x:Code element. Most of the handling for this is
215                 // at the start of the main parsing loop, in the 
216                 // processElementInCodeState() function
217                 void parseCodeElement()
218                 {
219                         push(CurrentType.Code, "");
220                 }
221
222                 void parseText()
223                 {
224                         nodeQueue.Add(new XamlTextNode(reader.LineNumber, reader.LinePosition, getDepth(), reader.Value));
225                         switch (currentState().type) {
226                         case CurrentType.Object:
227                         case CurrentType.PropertyObject:
228                                 abortIfNotAddChild("text");
229                                 ((XamlTextNode)topNode()).setmode(XamlParseMode.Object);
230 //                              writer.CreateObjectText(reader.Value);
231                                 break;
232                         case CurrentType.DependencyProperty:
233                                 DependencyProperty dp = (DependencyProperty)currentState().obj;
234 //                              writer.CreateDependencyPropertyText(reader.Value, dp.PropertyType);
235                                 ((XamlTextNode)topNode()).setmode(XamlParseMode.DependencyProperty);
236                                 ((XamlTextNode)topNode()).setfinalType(dp.PropertyType);
237                                 break;
238                         case CurrentType.Property:
239                                 PropertyInfo prop = (PropertyInfo)currentState().obj;
240 //                              writer.CreatePropertyText(reader.Value, prop.PropertyType);
241                                 ((XamlTextNode)topNode()).setmode(XamlParseMode.Property);
242                                 ((XamlTextNode)topNode()).setfinalType(prop.PropertyType);
243                                 break;
244                         default:
245                                 throw new NotImplementedException();
246                         }
247                 }
248
249                 void abortIfNotAddChild(string thing)
250                 {
251                         if (!isAddChild((Type)currentState().obj))
252                                 throw new Exception("Cannot add " + thing +
253                                                 " to instance of '" + 
254                                                 ((Type)currentState().obj) + 
255                                                 "'.");
256                 }
257                 
258                 void parseNormalPropertyElement(string propertyName)
259                 {
260                         // preconditions: currentState().Type == Object
261                         Type currentType = (Type)currentState().obj;
262                         PropertyInfo prop = currentType.GetProperty(propertyName);
263
264                         if (prop == null) {
265                                 throw new Exception("Property '" + propertyName + "' not found on '" + currentType.Name + "'.");
266                         }
267
268
269 //                      writer.CreateProperty(prop);
270                         nodeQueue.Add(new XamlPropertyNode(
271                                         reader.LineNumber,
272                                         reader.LinePosition,
273                                         getDepth(),
274                                         null,
275                                         currentType.Assembly.FullName,
276                                         currentType.AssemblyQualifiedName,
277                                         propertyName,
278                                         reader.Value,
279                                         reader.NamespaceURI,
280                                         BamlAttributeUsage.Default,
281                                         false));
282                         ((XamlPropertyNode)topNode()).setPropInfo(prop);
283                         push(CurrentType.Property, prop);
284
285                         if (reader.HasAttributes) {
286                                 throw new Exception("Property node should not have attributes.");
287                         }
288                 }
289
290
291                 void parseDependencyPropertyElement(string attachedTo, string propertyName)
292                 {
293                         Type currentType = (Type)currentState().obj;
294                         ensureDependencyObject(currentType);
295                         Type typeAttachedTo = findTypeToAttachTo(attachedTo, propertyName);
296                         DependencyProperty dp = getDependencyProperty(typeAttachedTo, propertyName);
297                         
298
299 //                      writer.CreateDependencyProperty(typeAttachedTo, propertyName, dp.PropertyType);
300                         nodeQueue.Add(new XamlPropertyNode(
301                                         reader.LineNumber,
302                                         reader.LinePosition,
303                                         getDepth(),
304                                         null,
305                                         currentType.Assembly.FullName,
306                                         currentType.AssemblyQualifiedName,
307                                         propertyName,
308                                         reader.Value,
309                                         reader.NamespaceURI,
310                                         BamlAttributeUsage.Default,
311                                         false));
312                         ((XamlPropertyNode)topNode()).setDP(dp);
313
314                         push(CurrentType.DependencyProperty, dp);
315         
316                 }
317                 bool isAddChild(Type t)
318                 {
319                         return (t.GetInterface("System.Windows.Serialization.IAddChild") != null);
320                 }
321                 void parseObjectElement()
322                 {
323                         Type parent;
324                         bool isEmpty = reader.IsEmptyElement;
325                         
326                         parent = mapper.GetType(reader.NamespaceURI, reader.Name);
327                         if (parent == null)
328                                 throw new Exception("Class '" + reader.Name + "' not found.");
329                 
330                         // whichever of these functions runs will push something
331                         if (currentState() == null) {
332                                 parseTopLevelObjectElement(parent);
333                         } else {
334                                 parseChildObjectElement(parent);
335                         }
336                         
337                         if (isEmpty)
338                                 tempStateCount ++;
339                         processObjectAttributes();
340
341                         if (isEmpty) {
342                                 closeEmptyObjectElement();
343                         }
344                 }
345                 void parseTopLevelObjectElement(Type parent)
346                 {
347                         if (reader.GetAttribute("Name", XAML_NAMESPACE) != null)
348                                 throw new Exception("The XAML Name attribute can not be applied to top level elements\n"+
349                                                 "Do you mean the Class attribute?");
350                         begun = true;
351                         createTopLevel(parent.AssemblyQualifiedName, reader.GetAttribute("Class", XAML_NAMESPACE));
352                 }
353
354                 void parseChildObjectElement(Type parent)
355                 {
356                         if (reader.GetAttribute("Class", XAML_NAMESPACE) != null)
357                                 throw new Exception("The XAML Class attribute can not be applied to child elements\n"+
358                                                 "Do you mean the Name attribute?");
359                         string name = reader.GetAttribute("Name", XAML_NAMESPACE);
360                         if (name == null)
361                                 name = reader.GetAttribute("Name", reader.NamespaceURI);
362
363                         Debug.WriteLine("XamlParser: parent is " + parent);
364                         if (currentState().type == CurrentType.Object) {
365                                 abortIfNotAddChild("object");
366                                 addChild(parent, name);
367                         } else if (currentState().type == CurrentType.Property) {
368                                 addPropertyChild(parent, name);
369                         } else {
370                                 throw new NotImplementedException();
371                         }
372                 }
373                 void processObjectAttributes()
374                 {
375                         if (reader.MoveToFirstAttribute()) {
376                                 do {
377                                         if (reader.Name.StartsWith("xmlns"))
378                                                 continue;
379                                         if (reader.NamespaceURI == XAML_NAMESPACE)
380                                                 continue;
381                                         if (reader.LocalName.IndexOf(".") < 0)
382                                                 parseLocalPropertyAttribute();
383                                         else
384                                                 parseDependencyPropertyAttribute();
385                                 } while (reader.MoveToNextAttribute());
386                         }
387                 }
388
389                 void closeEmptyObjectElement()
390                 {
391                         if (currentState().type == CurrentType.Object) {
392                                 nodeQueue.Add(new XamlElementEndNode(
393                                         reader.LineNumber,
394                                         reader.LinePosition,
395                                         getDepth()));
396 //                              writer.EndObject();
397                         } else if (currentState().type == CurrentType.PropertyObject) {
398                                 nodeQueue.Add(new XamlElementEndNode(
399                                         reader.LineNumber,
400                                         reader.LinePosition,
401                                         getDepth()));
402                                 ((XamlElementEndNode)topNode()).setpropertyObject(true);
403                                 nodeQueue.Add(new XamlPropertyComplexEndNode(
404                                         reader.LineNumber,
405                                         reader.LinePosition,
406                                         getDepth()));
407                                 ((XamlPropertyComplexEndNode)topNode()).setfinalType((Type)currentState().obj);
408 //                              ParserState state = (ParserState)oldStates[oldStates.Count - 1];
409 //                              writer.EndPropertyObject(((PropertyInfo)state.obj).PropertyType);
410                         }
411                         tempStateCount --;
412                         pop();
413                 }
414
415                 void createTopLevel(string parentName, string className)
416                 {
417                         Type t = Type.GetType(parentName);
418                         nodeQueue.Add(new XamlDocumentStartNode(reader.LineNumber, reader.LinePosition, getDepth()));
419                         nodeQueue.Add(new XamlElementStartNode(
420                                         reader.LineNumber,
421                                         reader.LinePosition,
422                                         getDepth(),
423                                         t.Assembly.FullName,
424                                         t.AssemblyQualifiedName,
425                                         t,
426                                         null));
427
428                         ((XamlElementStartNode)topNode()).setname(className);
429
430 //                      writer.CreateTopLevel(t, className);
431                         push(CurrentType.Object, t);
432                 }
433
434                 void addChild(Type type, string objectName)
435                 {
436                         nodeQueue.Add(new XamlElementStartNode(
437                                         reader.LineNumber,
438                                         reader.LinePosition,
439                                         getDepth(),
440                                         type.Assembly.FullName,
441                                         type.AssemblyQualifiedName,
442                                         type,
443                                         null));
444                         ((XamlElementStartNode)topNode()).setname(objectName);
445
446 //                      writer.CreateObject(type, objectName);
447                         push(CurrentType.Object, type);
448                 }
449                 
450                 void addPropertyChild(Type type, string objectName)
451                 {
452 //                      writer.CreatePropertyObject(type, objectName);
453                         nodeQueue.Add(new XamlElementStartNode(
454                                         reader.LineNumber,
455                                         reader.LinePosition,
456                                         getDepth(),
457                                         type.Assembly.FullName,
458                                         type.AssemblyQualifiedName,
459                                         type,
460                                         null));
461                         ((XamlElementStartNode)topNode()).setname(objectName);
462                         ((XamlElementStartNode)topNode()).setpropertyObject(true);
463
464
465                         push(CurrentType.PropertyObject, type);
466                 }
467
468
469                 
470                 void parseLocalPropertyAttribute()
471                 {
472                         string propertyName = reader.LocalName;
473                         Type currentType = (Type)currentState().obj;
474                         PropertyInfo prop = currentType.GetProperty(propertyName);
475                         if (parsedAsEventProperty(currentType, propertyName))
476                                 return;
477                         if (prop == null)
478                                 throw new Exception ("Property '" + propertyName + "' not found on '" + currentType.Name + "'.");
479                         nodeQueue.Add(new XamlPropertyNode(
480                                         reader.LineNumber,
481                                         reader.LinePosition,
482                                         getDepth(),
483                                         null,
484                                         currentType.Assembly.FullName,
485                                         currentType.AssemblyQualifiedName,
486                                         propertyName,
487                                         reader.Value,
488                                         reader.NamespaceURI,
489                                         BamlAttributeUsage.Default,
490                                         false));
491                         ((XamlPropertyNode)nodeQueue[nodeQueue.Count - 1]).setPropInfo(prop);
492
493                         if (!prop.PropertyType.IsSubclassOf(typeof(Delegate))) {
494
495                                 nodeQueue.Add(new XamlTextNode(
496                                                 reader.LineNumber,
497                                                 reader.LinePosition,
498                                                 getDepth(),
499                                                 reader.Value));
500
501                                 ((XamlTextNode)topNode()).setmode(XamlParseMode.Property);
502 //                              writer.CreatePropertyText(reader.Value, prop.PropertyType);
503                                                         
504 //                              writer.EndProperty();
505                                 ((XamlTextNode)topNode()).setfinalType(prop.PropertyType);
506                         } else {
507 //                              writer.CreatePropertyDelegate(reader.Value, prop.PropertyType);
508                                 nodeQueue.Add(new XamlClrEventNode(
509                                                 reader.LineNumber,
510                                                 reader.LinePosition, 
511                                                 getDepth(),
512                                                 propertyName,
513                                                 prop,
514                                                 reader.Value));
515                         }
516                 }
517                 
518                 bool parsedAsEventProperty(Type currentType, string eventName)
519                 {
520                         EventInfo evt = currentType.GetEvent(eventName);
521                         if (evt == null)
522                                 return false;
523                         nodeQueue.Add(new XamlClrEventNode(
524                                         reader.LineNumber,
525                                         reader.LinePosition,
526                                         getDepth(),
527                                         eventName, 
528                                         evt, 
529                                         reader.Value));
530 //                      writer.CreateEvent(evt);
531 //                      writer.CreateEventDelegate(reader.Value, evt.EventHandlerType);
532 //                      writer.EndEvent();
533                         return true;
534                 }
535
536                 void ensureDependencyObject(Type currentType)
537                 {
538                         if (!currentType.IsSubclassOf(typeof(System.Windows.DependencyObject)))
539                                         throw new Exception("Dependency properties can only be set on "+
540                                                         "DependencyObjects (not " + currentType.Name + ")");
541                 }
542                 Type findTypeToAttachTo(string attachedTo, string propertyName)
543                 {
544                         Type typeAttachedTo = null;
545                         foreach (ParserState state in oldStates) {
546                                 if ((state.type == CurrentType.Object || 
547                                                 state.type == CurrentType.PropertyObject) &&
548                                                 ((Type)state.obj).Name == attachedTo) {
549                                         typeAttachedTo = (Type)state.obj;
550                                         break;
551                                 }
552                         }
553                         if (typeAttachedTo == null)
554                                 throw new Exception("Nothing to attach to: " + attachedTo + "." + propertyName);
555                         return typeAttachedTo;
556                 }
557
558                 DependencyProperty getDependencyProperty(Type typeAttachedTo, string propertyName)
559                 {
560                         FieldInfo propField = typeAttachedTo.GetField(propertyName + "Property");
561                         if (propField == null)
562                                 throw new Exception("Property '" + propertyName + "' does not exist on '" + typeAttachedTo.Name + "'.");
563                         return (DependencyProperty)propField.GetValue(null);
564                 }
565
566                 void parseDependencyPropertyAttribute()
567                 {
568                         int index = reader.LocalName.LastIndexOf('.');
569                         string attachedTo = reader.LocalName.Substring(0, index);
570                         string propertyName = reader.LocalName.Substring(index + 1);
571                         
572                         Type currentType = (Type)currentState().obj;
573                         ensureDependencyObject(currentType);
574                         Type typeAttachedTo = findTypeToAttachTo(attachedTo, propertyName);
575                         DependencyProperty dp = getDependencyProperty(typeAttachedTo, propertyName);
576                         
577                         nodeQueue.Add(new XamlPropertyNode(
578                                         reader.LineNumber,
579                                         reader.LinePosition,
580                                         getDepth(),
581                                         null,
582                                         currentType.Assembly.FullName,
583                                         currentType.AssemblyQualifiedName,
584                                         propertyName,
585                                         reader.Value,
586                                         reader.NamespaceURI,
587                                         BamlAttributeUsage.Default,
588                                         false));
589                         ((XamlPropertyNode)topNode()).setDP(dp);
590
591                         nodeQueue.Add(new XamlTextNode(reader.LineNumber, reader.LinePosition, getDepth(), reader.Value));
592                         ((XamlTextNode)topNode()).setmode(XamlParseMode.DependencyProperty);
593                         ((XamlTextNode)topNode()).setfinalType(dp.PropertyType);
594
595 //                      writer.CreateDependencyProperty(typeAttachedTo, propertyName, dp.PropertyType);
596 //                      writer.CreateDependencyPropertyText(reader.Value, dp.PropertyType);
597 //                      writer.EndDependencyProperty();
598                 }
599
600                 void parseEndElement()
601                 {
602                         Debug.WriteLine("XamlParser: IN ENDELEMENT, SWITCHING ON " + currentState().type);
603                         switch (currentState().type) {
604                         case CurrentType.Code:
605                                 nodeQueue.Add(new XamlLiteralContentNode(
606                                                 reader.LineNumber,
607                                                 reader.LinePosition,
608                                                 getDepth(),
609                                                 (string)currentState().obj));
610 //                              writer.CreateCode((string)currentState().obj);
611                                 break;
612                         case CurrentType.Object:
613                                 nodeQueue.Add(new XamlElementEndNode(
614                                                 reader.LineNumber,
615                                                 reader.LinePosition,
616                                                 getDepth()));
617 //                              writer.EndObject();
618                                 break;
619                         case CurrentType.PropertyObject:
620                                 nodeQueue.Add(new XamlElementEndNode(
621                                                 reader.LineNumber,
622                                                 reader.LinePosition,
623                                                 getDepth()));
624                                 ((XamlElementEndNode)topNode()).setpropertyObject(true);
625                                 nodeQueue.Add(new XamlPropertyComplexEndNode(
626                                                 reader.LineNumber,
627                                                 reader.LinePosition,
628                                                 getDepth()));
629                                 Debug.WriteLine("XamlParser: XXXXXXXX" + currentState().obj);
630                                 Debug.WriteLine("XamlParser: XXXXXXXX" + (currentState().obj is Type));
631                                 ((XamlPropertyComplexEndNode)topNode()).setfinalType((Type)currentState().obj);
632                                 Debug.WriteLine("XamlParser: XXXXXXXX" + ((XamlPropertyComplexEndNode)topNode()).finalType);
633                                 Debug.WriteLine("TTTTTTTTT " + ((ParserState)oldStates[oldStates.Count - 1]).obj.GetType());
634                                 Debug.WriteLine("TTTTTTTTT " + ((ParserState)oldStates[oldStates.Count - 1]).type);
635                                 Debug.WriteLine("TTTTTTTTT " + ((ParserState)oldStates[oldStates.Count - 2]).obj.GetType());
636                                 Debug.WriteLine("TTTTTTTTT " + ((ParserState)oldStates[oldStates.Count - 2]).type);
637                                 Debug.WriteLine("TTTTTTTTT " + ((ParserState)oldStates[oldStates.Count - 3]).obj.GetType());
638                                 Debug.WriteLine("TTTTTTTTT " + ((ParserState)oldStates[oldStates.Count - 3]).type);
639                                 Debug.WriteLine("TTTTTTTTT " + ((ParserState)oldStates[oldStates.Count - 4]).obj.GetType());
640                                 Debug.WriteLine("TTTTTTTTT " + ((ParserState)oldStates[oldStates.Count - 4]).type);
641 //                              writer.EndPropertyObject((Type)currentState().obj);
642 //                              return;
643                                 break;
644                         // these next two happen automatically in the new model
645                         case CurrentType.Property:
646 //                              writer.EndProperty();
647                                 break;
648                         case CurrentType.DependencyProperty:
649 //                              writer.EndDependencyProperty();
650                                 break;
651                         }
652                         pop();
653                 }
654
655                 void pop()
656                 {
657                         Debug.WriteLine("XamlParser: POPPING: " + currentState().type);
658                         // we are popping the last element
659                         if (oldStates.Count == 1) {
660 //                              writer.Finish();
661                                 nodeQueue.Add(new XamlDocumentEndNode(
662                                                 reader.LineNumber,
663                                                 reader.LinePosition,
664                                                 getDepth()));
665                                 return;
666                         }
667                         int lastIndex = oldStates.Count - 1;
668                         oldStates.RemoveAt(lastIndex);
669                 }
670                 void push(CurrentType type, Object obj)
671                 {
672                         Debug.WriteLine("XamlParser: PUSHING: " + oldStates.Count + " " + type);
673                         ParserState currentState = new ParserState();
674                         currentState.type = type;
675                         currentState.obj = obj;
676                         oldStates.Add(currentState);
677                 }
678         }
679 }