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 += "" }, 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