namespace NemerleDoc { using System.Xml; using System; using Nemerle.Collections; /// /// This class implements model of Xml parsing based on Python's library /// class xml.saxutils.DefaultHandler. However, handlers are not impelemnted /// in a subclass, but are attached to as events. /// public class SaxReader { mutable internal cursor : XmlTextReader; /// Name of a field /// Returns the value of an attribute internal attribute (field : string) : string { cursor[field] } private iterate () : void { do { match (cursor.NodeType) { | Element => when (ElementEvent != null) ElementEvent(cursor.Name) | EndElement => when (EndElementEvent != null) EndElementEvent(cursor.Name) | Text => when (TextEvent != null) TextEvent(cursor.Value) | Document => when (DocumentEvent != null) DocumentEvent() | EntityReference => when (EntityReferenceEvent != null) EntityReferenceEvent() | XmlDeclaration => when (XmlDeclarationEvent != null) XmlDeclarationEvent() | None => () | _ => Console.WriteLine("Unsupported XML node type {0}", cursor.NodeType) } // match } while (cursor.Read()) // } // iterate // -------- public interface ------------- public delegate tagHandler (_ : string) : void; public event ElementEvent : tagHandler; public event EndElementEvent : tagHandler; public delegate textHandler(_ : string) : void; public event TextEvent : textHandler; public delegate DocumentHandler () : void; public event DocumentEvent : DocumentHandler; public delegate EntityReferenceHandler () : void; public event EntityReferenceEvent : EntityReferenceHandler; public delegate XmlDeclarationHandler () : void; public event XmlDeclarationEvent : XmlDeclarationHandler; public run (filename : string) : void { cursor = XmlTextReader(filename); cursor.WhitespaceHandling = WhitespaceHandling.None; iterate(); } } // SaxDefaultHanler variant TagName { | Summary | Remarks | Returns | Param | Example | Exception | Permission | SeeAlso | Other } [Record] sealed class Handler { internal begin : void -> void; internal end : void -> void } /// /// Processes xml file /// class XmlDocParser { mutable buffer : string = ""; tree : DataTree ; mutable state : TagName = TagName.Other(); mutable static handlers : Hashtable [ string, Handler]; dh : SaxReader; cursor : XmlTextReader { get { dh.cursor } } /// /// Summary /// make_handler () : void { handlers = Hashtable(); handlers["member"] = Handler(fun () : void {tree.AddItem(dh.attribute("name"))}, fun () {} ); handlers["summary"] = Handler( fun () { state = TagName.Summary() }, fun () { when (buffer.Length > 0) this.tree.AddComment(buffer); buffer = ""; state = TagName.Other() }); handlers["remarks"] = Handler( fun () { state = TagName.Remarks() }, fun () { when (buffer.Length > 0) this.tree.AddRemark(buffer); buffer = ""; state = TagName.Other() }); handlers["returns"] = Handler( fun () { state = TagName.Returns() }, fun () { when (buffer.Length > 0) this.tree.AddReturn(buffer); buffer = ""; state = TagName.Other() }); handlers["example"] = Handler( fun () { state = TagName.Example() }, fun () { when (buffer.Length > 0) this.tree.AddExample(buffer); buffer = ""; state = TagName.Other() }); handlers["param"] = Handler(fun () {state = TagName.Param(); buffer = dh.attribute("name") + ": ";}, fun () { when (buffer.Length > 0) this.tree.AddParam(buffer); buffer = ""; state = TagName.Other() }); handlers["exception"] = Handler(fun () { state = TagName.Exception(); buffer = dh.attribute("cref") + ": ";}, fun () { when (buffer.Length > 0) this.tree.AddException(buffer); buffer = ""; state = TagName.Other() }); handlers["permission"] = Handler(fun () { state = TagName.Permission(); buffer = dh.attribute("cref") + ": ";}, fun () { when (buffer.Length > 0) this.tree.AddPermission(buffer); buffer = ""; state = TagName.Other() }); handlers["seealso"] = Handler( fun () { state = TagName.SeeAlso(); buffer = ""; when (this.cursor.IsEmptyElement) this.tree.AddSeeAlso(dh.attribute("cref")); }, fun () { Console.WriteLine("*** Warning: 'sealso' tag should be an empty element.") }); // formatting tags handlers["code"] = Handler(fun () { buffer += "
" }, fun () { buffer += "
" }); handlers["c"] = Handler(fun () { buffer += "" }, fun () { buffer += "" }); handlers["para"] = Handler( fun () { buffer += "

" }, fun () { buffer += "

" } ); handlers["paramref"] = Handler( fun () { buffer += "" }, fun () { buffer = "" } ); handlers["see"] = Handler( fun () { buffer += "" + dh.attribute("cref"); when (this.cursor.IsEmptyElement) buffer += ""; }, fun () { buffer = "" } ); handlers["value"] = Handler( fun () { buffer += "
" }, fun () { buffer += "
" }); // list and list family tags handlers["list"] = Handler( fun () { buffer += "" }); handlers["listheader"] = Handler( fun () { buffer += "
  • " }, fun () { buffer += "
  • " }); handlers["item"] = Handler( fun () { buffer += "
  • " }, fun () { buffer += "
  • " }); handlers["term"] = Handler( fun () { buffer += "" }, fun () { buffer += " " }); handlers["description"] = Handler( fun () { buffer += "" }, fun () { buffer += "" }); // not processed tags handlers["doc"] = Handler(fun () {}, fun () { }); handlers["assembly"] = Handler(fun () {}, fun () { }); handlers["name"] = Handler(fun () {}, fun () { }); handlers["members"] = Handler(fun () {}, fun () { }); } public Element ( tagName : string ) : void { if (handlers.Contains(tagName)) handlers[tagName].begin(); else Console.WriteLine("*** Warning: tag '{0}' is not supported", tagName); } public Text (text : string) : void { match (state) { | Summary | Remarks | Returns | Example | Exception | Permission | Param => buffer += text | SeeAlso => () | Other => () } } public EndElement (tagName : string ) : void { when (handlers.Contains(tagName)) handlers[tagName].end() } // public this(f : string) { base(f) } public this(tree : DataTree, file : string) { dh = SaxReader(); dh.ElementEvent += this.Element; dh.EndElementEvent += this.EndElement; dh.TextEvent += this.Text; this.tree = tree; make_handler(); dh.run(file); } } // MyHandler } // namespace NemerleDoc