<feed xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US">
    <title>Jeff Ferguson</title>
    <link rel="self" type="application/xml" href="http://geekswithblogs.net/JeffFerguson/Atom.aspx" />
    <subtitle type="html"> Irritating other people since 1967</subtitle>
    <id>http://geekswithblogs.net/JeffFerguson/Default.aspx</id>
    <author>
        <name>Jeff Ferguson</name>
        <uri>http://geekswithblogs.net/JeffFerguson/Default.aspx</uri>
    </author>
    <generator uri="http://subtextproject.com" version="Subtext Version 0.0.0.0">Subtext</generator>
    <updated>2009-08-28T20:41:18Z</updated>
    <entry>
        <title>Is Software Development Hard?</title>
        <link rel="self" type="text/html" href="http://geekswithblogs.net/JeffFerguson/archive/2009/08/28/is-software-development-hard.aspx" />
        <id>http://geekswithblogs.net/JeffFerguson/archive/2009/08/28/is-software-development-hard.aspx</id>
        <published>2009-08-28T20:41:18-05:00:00</published>
        <updated>2009-08-28T20:41:18Z</updated>
        <content type="html">&lt;p&gt;A &lt;a href="http://www.dotnetrocks.com/default.aspx?showNum=476"&gt;recent episode&lt;/a&gt; of &lt;a href="http://www.dotnetrocks.com/"&gt;.NET Rocks&lt;/a&gt; asked this very question, and listening to the episode made me consider my thoughts on the matter.&lt;/p&gt;  &lt;p&gt;[&lt;em&gt;&lt;strong&gt;Disclaimer&lt;/strong&gt;: Some of this post may be interpreted as “beating up on Microsoft”. This is not my intent. I use Microsoft in my examples because Microsoft development experiences have been the totality of my professional career. The issues I apply to Microsoft can assuredly be applied to any other company out there.&lt;/em&gt;]&lt;/p&gt;  &lt;p&gt;The short answer is “no”. I started writing software for Windows machines in 1989. Back then, I had a copy of the 16-bit Windows 3.0 SDK and the &lt;a href="http://en.wikipedia.org/wiki/Charles_Petzold"&gt;Charles Petzold&lt;/a&gt; “Programming Windows” Second Edition book (which I still have, thank you very much). I lived with window classes, message loops, and WM_PAINT messages, all in the C language. No one can look me in the eye with a straight face and say that .NET Windows Forms is harder. If you doubt this, I will give you a copy of the 16-bit Windows SDK and the “Programming Windows” Second Edition book and I will sit down with Visual Studio 2008 and Windows Forms. We’ll both set out to write a standard line-of-business application, and we’ll see who gets done first. Go ahead. I’ll wait. I’ll even give you a head start.&lt;/p&gt;  &lt;p&gt;I recognize, however, that I can say that because I understand the toolset. I understand it, in part, because I have had twenty years of experience with the Microsoft tools and technologies. I have lived this life for two decades, and, because of that, my view of the software development world may be colored by my experience. If I take a step back, and consider what a person just coming into the industry might be facing, I recognize that their answer may be “yes”. It would be a legitimate response, and I can think of several reasons why someone with less experience may offer that opinion.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Too Many Choices Make It Hard&lt;/strong&gt;    &lt;br /&gt;Microsoft’s myriad of competing technologies often have overlapping use cases, and it can be difficult for new folks (and veterans alike) to decide what technologies to use. Should my data access layer be written in ADO.NET, use the Entity Framework, or ASP.NET Dynamic Data? Should my collaboration work be Sharepoint or Groove? Should I use WPF or Silverlight Out of Browser? No one provides easy answers to these types of questions (often times because the answer is “it depends”). The choices can be daunting, and the ramifications of the choice can make or break a project.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Demo Code Versus Best Practices Code Make It Hard&lt;/strong&gt;    &lt;br /&gt;Conference demos often showcase the state of the art in the Microsoft tools and technologies set. The demos are carefully designed to highlight a specific feature: perhaps of ease-of-use or a subsystem feature. These demos are designed to be performed quickly without regards to actual best practices. An example of this might be a button on a form with code behind that uses dynamic SQL to access some data. This works well for the demo, but the problem is that the sessions showcasing the demos are recorded for posterity and replayed across the Internet by everyone needing to get a basic understanding of a technology.&lt;/p&gt;  &lt;p&gt;This video-based online review of the demo code works well, until the person stumbles across a blog post that tells them that code behind is bad, and dynamic SQL is bad, and not having a separate domain objects layer is bad. Where does this person go after watching the video of the canned demo? Have we confused the new folks by doing one thing in a demo and doing something else in blog posts? Are we compounding the issue by offering different ways to get the same thing done?&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Lack of Mentors Make It Hard&lt;/strong&gt;    &lt;br /&gt;Much has been made of the fact that our industry is terrible in the areas of apprenticeships and mentoring. It has been suggested that we, as an industry, put some journeyman program in place to help new people learn the craft. It’s a great idea, but I think we can do things now with what we have in place today before that comes to be reality.&lt;/p&gt;  &lt;p&gt;I think us “experts”, or “veterans”, or whatever we want to call ourselves – and I put myself in this category – don’t do enough to reach out to those who could benefit from our level of experience. We are, frankly, all full of ourselves, and love to write about esoteric topics like “Building Your Own C# Compiler Using MSIL, Notepad, and the IL Assembler” (or, in my case, discussing the implementation of lexical analysis state machines). That’s fine, but who do we hang out with? Other experts! Our associates are people who also write the “Building Your Own C# Compiler Using MSIL, Notepad, and the IL Assembler” articles. Do we reach out to those who could benefit from what we know? Do we intimidate them? Are they afraid to reach out to us because we’re “so far ahead”? Are we leaving the poor folks who need to know how to get a Windows Form to talk to a database through a business object in the dust because we’re too busy writing about the internals of BizTalk 2009?&lt;/p&gt;  &lt;p&gt;Perhaps we can change that. The next generation hangs out where we “experts” do not: in beginner’s forums, such as the Visual C# Express forums on MSDN. If they, for whatever reason, are “intimidated” by us, maybe we could take the first step by spending some time answering questions on those forums. Perhaps we can spend some time there, answering some “basic” questions and, along the way, imparting some of our knowledge to help the new people. It’s worth a try.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Hard For The Experts … Because &lt;em&gt;We Make It Hard&lt;/em&gt;&lt;/strong&gt;     &lt;br /&gt;As I look back on projects that have caught my attention for one reason or another, I wonder if we have brought some of this “difficult software” on ourselves. I have seen many projects become over-engineered, over-thought, and over-designed. I have seen many technical leads spend time on features that won’t be used in the initial version but are built because “someday, the customer will need this”. I have seen teams spend six weeks in requirements and design phases, over-thinking problems and designing the ultimate system with ultimate scalability and ultimate flexibility – regardless of whether or not that flexibility is in the customer’s time frame or budgets. Often times, we don’t build what the customers need, but what we think the customers need. Do we really know better than the customer? Is our over-engineering justified? Often times, the answer is “no”, but we, in our infinite wisdom, build huge scalability, flexibility, and configuration subsystems for design features that the customer may or may not ever use. Software may be “hard” because we over-think the problem and, in so doing, we make it hard.&lt;/p&gt;  &lt;p&gt;Build what the customer wants, but no more. You’re not on site to throw technology at people. You’re there to solve someone’s business problem. Build the software that solves their business problem, but don’t build more than that. Don’t over-complicate matters that are already difficult.&lt;/p&gt;  &lt;p&gt;Now, if you’ll excuse me, I’m going to subscribe to an RSS feed of the Visual C# Express forum on MSDN.&lt;/p&gt;&lt;img src="http://geekswithblogs.net/JeffFerguson/aggbug/134370.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://geekswithblogs.net/JeffFerguson/comments/134370.aspx</wfw:comment>
        <slash:comments>3</slash:comments>
        <wfw:commentRss>http://geekswithblogs.net/JeffFerguson/comments/commentRss/134370.aspx</wfw:commentRss>
        <trackback:ping>http://geekswithblogs.net/JeffFerguson/services/trackbacks/134370.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Prism and Unique Module Names</title>
        <link rel="self" type="text/html" href="http://geekswithblogs.net/JeffFerguson/archive/2009/07/12/prism-and-unique-module-names.aspx" />
        <id>http://geekswithblogs.net/JeffFerguson/archive/2009/07/12/prism-and-unique-module-names.aspx</id>
        <published>2009-07-12T22:15:51-05:00:00</published>
        <updated>2009-07-12T22:15:51Z</updated>
        <content type="html">&lt;p&gt;This code won’t work in a &lt;a href="http://www.codeplex.com/CompositeWPF"&gt;Prism&lt;/a&gt; bootstrapper:&lt;/p&gt;  &lt;div class="csharpcode"&gt;   &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; IModuleCatalog GetModuleCatalog()&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;{&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;    ModuleCatalog NewModuleCatalog = &lt;span class="kwrd"&gt;new&lt;/span&gt; ModuleCatalog();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;    NewModuleCatalog.AddModule(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(JeffFerguson.Narrative.Wpf.Units.Module));&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;    NewModuleCatalog.AddModule(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(JeffFerguson.Narrative.Wpf.XbrlDocumentLoader.Module));&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;    &lt;span class="kwrd"&gt;return&lt;/span&gt; NewModuleCatalog;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;style type="text/css"&gt;&lt;![CDATA[

.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }]]&gt;&lt;/style&gt;

&lt;p&gt;If you run code like this, Prism will throw an exception of type DuplicateModuleException with a message that reads “A duplicated module with name Module has been found by the loader.”.&lt;/p&gt;

&lt;p&gt;The issue is that Prism uses module names to distinguish one module for another, and, by default, the class name is used as the module name when a module name is not specified. Since, according to Prism (and much to my chagrin), only the tail end of the class name is used when constructing module names, there are, according to Prism, two classes named Module in the code snippet above.&lt;/p&gt;

&lt;p&gt;Fortunately, this is all easily fixed through the use of a ModuleInfo object, where all of the information about a module can be specified and added to a module catalog as a unit. My bootstrapper code looks (in part) like this:&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; IModuleCatalog GetModuleCatalog()&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;{&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;    ModuleCatalog NewModuleCatalog = &lt;span class="kwrd"&gt;new&lt;/span&gt; ModuleCatalog();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;    AddModuleToCatalog(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(JeffFerguson.Narrative.Wpf.Units.Module), NewModuleCatalog);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;    AddModuleToCatalog(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(JeffFerguson.Narrative.Wpf.XbrlDocumentLoader.Module), NewModuleCatalog);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;    &lt;span class="kwrd"&gt;return&lt;/span&gt; NewModuleCatalog;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;}&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; AddModuleToCatalog(Type ModuleType, ModuleCatalog Catalog)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;{&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;    ModuleInfo NewModuleInfo = &lt;span class="kwrd"&gt;new&lt;/span&gt; ModuleInfo();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;    NewModuleInfo.ModuleName = ModuleType.AssemblyQualifiedName;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;    NewModuleInfo.ModuleType = ModuleType.AssemblyQualifiedName;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;    Catalog.AddModule(NewModuleInfo);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;style type="text/css"&gt;&lt;![CDATA[
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }]]&gt;&lt;/style&gt;

&lt;p&gt;This code simply uses the module type’s assembly qualified name, which will be unique throughout the application, as the name of the module.&lt;/p&gt;

&lt;p&gt;My rant here is that I believe Prism should be using the value of the module type’s AssemblyQualifiedName property, and not just the Name property, by default as the module’s name. The two types in the original example are uniquely named, since the class’ namespace forms a part of its fully qualified name. If I had to name my two Module classes with unique tail names (like “UnitsModule” and “XbrlDocumentLoaderModule”, for example), then I wouldn’t have much need for a unique namespace.&lt;/p&gt;

&lt;p&gt;OK. Rant over.&lt;/p&gt;&lt;img src="http://geekswithblogs.net/JeffFerguson/aggbug/133447.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://geekswithblogs.net/JeffFerguson/comments/133447.aspx</wfw:comment>
        <slash:comments>2</slash:comments>
        <wfw:commentRss>http://geekswithblogs.net/JeffFerguson/comments/commentRss/133447.aspx</wfw:commentRss>
        <trackback:ping>http://geekswithblogs.net/JeffFerguson/services/trackbacks/133447.aspx</trackback:ping>
    </entry>
    <entry>
        <title>RDBMS and The Right Tool for the Right Job</title>
        <link rel="self" type="text/html" href="http://geekswithblogs.net/JeffFerguson/archive/2009/07/06/rdbms-and-the-right-tool-for-the-right-job.aspx" />
        <id>http://geekswithblogs.net/JeffFerguson/archive/2009/07/06/rdbms-and-the-right-tool-for-the-right-job.aspx</id>
        <published>2009-07-06T21:09:58-05:00:00</published>
        <updated>2009-07-06T21:09:58Z</updated>
        <content type="html">&lt;p&gt;I read, with interest, &lt;a href="http://whitneyweaver.com/post/Are-you-ready-for-a-world-without-SQL.aspx"&gt;a post&lt;/a&gt; by &lt;a href="http://whitneyweaver.com/"&gt;Whitney Weaver&lt;/a&gt; about the “No SQL” movement. I have been, to this point, blissfully unaware of &lt;a href="http://www.computerworld.com/action/article.do?command=viewArticleBasic&amp;amp;taxonomyName=Databases&amp;amp;articleId=9135086&amp;amp;taxonomyId=173&amp;amp;pageNumber=1"&gt;this movement&lt;/a&gt;. While I am not quite ready to get rid of SQL, I have been known to gripe about some of its applications and wanted to share my thoughts on the subject.&lt;/p&gt;  &lt;p&gt;SQL (or, more correctly, a Relational Database Management System, or RDBMS) is fantastic at performing the work for which it was designed: the storage of related data. Through mechanisms such as referential integrity and triggers, the RDBMS platform has become a powerful engine for the storage of data. I remember my first internship in 1987, where I watched people run queries directly against an RDBMS and pull back just the data they needed. It truly was the right tool for the right job.&lt;/p&gt;  &lt;p&gt;However, we have spent the last two decades (if not longer) building software systems on top of an RDBMS engine. From &lt;a href="http://en.wikipedia.org/wiki/ODBC"&gt;ODBC&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Java_Database_Connectivity"&gt;JDBC&lt;/a&gt; to &lt;a href="http://en.wikipedia.org/wiki/OLE_DB"&gt;OLE DB&lt;/a&gt; to &lt;a href="http://en.wikipedia.org/wiki/ActiveX_Data_Objects"&gt;ADO&lt;/a&gt; to &lt;a href="http://en.wikipedia.org/wiki/ADO.NET"&gt;ADO.NET&lt;/a&gt;, we, as an industry, have invested a lot of time and effort into building software bridges to allow our object data (which can often be represented in a two-dimensional object graph, with parent objects holding references to children and collections of children) to be stuffed into an RDBMS. Has it been successful? Perhaps. In my opinion, though, it’s a fragile system overall, for a few reasons:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Dimensional Mismatch:&lt;/strong&gt; As I noted above, RDBMSs are best at storing one dimensional data in a single row housed in a table. Our object graphs, however, can be two dimensional data representations, with cross-object references and related data. We have overcome this hurdle, for the most part, with careful management of primary and foreign keys, but, without continued care, this sort of system can become out of sync.&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Separate Tools, Independent Management&lt;/strong&gt;: I can design the best object model and data store in the world, but any such system comes down to independent system management by separate groups of people. The developers take care of their object model and the DBAs take care of the database. This works well, until one group decides to change something. Have you ever been on a project where a DBA decides to change the data type of a column, or a developer changes some data validation logic without informing the DBAs? Separate tools and separate maintenance teams offer one more place where something can go wrong. I once attended a class led by &lt;a href="http://www.wiseowl.com/about/about.aspx"&gt;Brent Rector&lt;/a&gt; who said, “A thing built on top of a thing is not as good as a thing”. I have never forgotten that, and I think of it every time I see one architectural idea, such as classes, built on top of a separate tool, such as an RDBMS.&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Not Data, But Data And Behavior&lt;/strong&gt;: We very rarely pull data from a database and use it as is. Instead, we pull the data and run calculations or validations against the data. Where should this validation and calculation code live? If it is to live in stored procedures – which &lt;a href="http://en.wikipedia.org/wiki/SQL_Server_Compact"&gt;not all RDBMSs have&lt;/a&gt; – then the DBAs are in for a bit of a ride as all of the business logic is implemented in a set-based language like &lt;a href="http://en.wikipedia.org/wiki/SQL"&gt;SQL&lt;/a&gt;. If, instead, the validation and calculation code is to live in business objects, then people who query the database without using the business objects miss out on the value-added business logic. Again, the “separate tool” idea comes back to bite us.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;At this point, you can offer one big rebuttal to all of my whining: “OK, Jeff, then show me something better.” I can’t. For better or for worse, this is where we are today. But I am hopeful that things can change. If we, as a community, didn’t innovate, then we would all still be running Windows 3.1 on top of DOS. Perhaps “No SQL”, as a mantra, is a bit drastic; however, stretching the imagination and moving into new territory is not such a bad idea, either. Personally, I’d like to see a general purpose language carry more tightly integrated object state storage support rather than relying on a separate tool. Time will tell whether or not this will actually happen.&lt;/p&gt;  &lt;p&gt;I find it interesting (but &lt;a href="http://www.azlyrics.com/lyrics/alanismorissette/ironic.html"&gt;not ironic&lt;/a&gt;) that we are the industry who says “use the right tool for the right job”, and, in the next sentence, says “of course, everything has to be on the Web, the data format always has to be XML, and the data storage engine always has to be SQL”. I subscribe to the old adage that the answer to any design problem is “it depends”, which aligns much more closely with “use the right tool for the right job” than it does with “the data storage engine always has to be SQL”.&lt;/p&gt;&lt;img src="http://geekswithblogs.net/JeffFerguson/aggbug/133302.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://geekswithblogs.net/JeffFerguson/comments/133302.aspx</wfw:comment>
        <slash:comments>1</slash:comments>
        <wfw:commentRss>http://geekswithblogs.net/JeffFerguson/comments/commentRss/133302.aspx</wfw:commentRss>
        <trackback:ping>http://geekswithblogs.net/JeffFerguson/services/trackbacks/133302.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Working with Prism and the Blacklight Controls</title>
        <link rel="self" type="text/html" href="http://geekswithblogs.net/JeffFerguson/archive/2009/06/30/working-with-prism-and-the-blacklight-controls.aspx" />
        <id>http://geekswithblogs.net/JeffFerguson/archive/2009/06/30/working-with-prism-and-the-blacklight-controls.aspx</id>
        <published>2009-06-30T18:58:38-05:00:00</published>
        <updated>2009-06-30T19:04:31Z</updated>
        <content type="html">&lt;p&gt;I recently set out to build a WPF application using the &lt;a href="http://www.codeplex.com/CompositeWPF"&gt;Composite Client Application Guidance&lt;/a&gt; (lovingly known as “Prism”) code base. Additionally, I wanted to make use of the &lt;a href="http://blacklight.codeplex.com/"&gt;Blacklight&lt;/a&gt; controls – specifically, the DragDockPanelHost and DragDockPanel controls – in the application. I soon discovered that these two code bases didn’t work together “right out of the box”. I found a problem, and a solution, and this post describes both the issue and its resolution.&lt;/p&gt;  &lt;p&gt;The architecture promoted by Prism is that of an application made up of an executable shell and a set of module assemblies. In this pattern, each of the application views are implemented in their own module assembly, which is loaded by the shell at runtime. So far, so good.&lt;/p&gt;  &lt;p&gt;Since I was interested in using the DragDockPanelHost and DragDockPanel controls in my WPF application, my approach was to put the DragDockPanelHost in my shell application, and a DragDockPanel in each of my Prism modules. With this design, and after assigning a Prism region name to the DragDockPanelHost in the shell application, Prism would do its thing and load each of the DragDockPanels from each module and add them into my DragDockPanelHost region at runtime.&lt;/p&gt;  &lt;p&gt;You may be asking yourself, “And how did that work out for you?” To quote Stewie on &lt;em&gt;Family Guy&lt;/em&gt;, &lt;a href="http://www.tv.com/family-guy/lois-kills-stewie-2/episode/920141/summary.html"&gt;“Not well, Brian. Not well.”&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;My first mistake was in assuming that Prism regions worked with any kind of container control, and, therefore, putting a region name on my DragDockPanelHost XAML element would be enough. It wasn’t. Prism, by default, only supports regions defined on containers derived from one of the following classes:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;System.Windows.Controls.Primitives.Selector &lt;/li&gt;    &lt;li&gt;System.Windows.Controls.ItemsControl &lt;/li&gt;    &lt;li&gt;System.Windows.Controls.ContentControl &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The DragDockPanelHost class is derived from Canvas, which explains the lack of love that I got from Prism.&lt;/p&gt;  &lt;p&gt;Fortunately, Prism has a way to add support for other containers defined as regions through the RegionAdapterBase class. In my solution, I wrote a class, derived from RegionAdapterBase, that defined a region adapter for the Blacklight DragDockPanelHost. The class looks like this:&lt;/p&gt;  &lt;div class="csharpcode"&gt;   &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; DragDockPanelHostRegionAdapter : RegionAdapterBase&amp;lt;DragDockPanelHost&amp;gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; DragDockPanelHostRegionAdapter(IRegionBehaviorFactory BehaviorFactory) : &lt;span class="kwrd"&gt;base&lt;/span&gt;(BehaviorFactory)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Adapt(IRegion region, DragDockPanelHost regionTarget)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;            region.Views.CollectionChanged += (s, e) =&amp;gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;                {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;                    &lt;span class="kwrd"&gt;if&lt;/span&gt; (e.Action == NotifyCollectionChangedAction.Add)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;                    {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;                        &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (FrameworkElement CurrentElement &lt;span class="kwrd"&gt;in&lt;/span&gt; e.NewItems)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;                        {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;                            UserControl CurrentElementAsUserControl = CurrentElement &lt;span class="kwrd"&gt;as&lt;/span&gt; UserControl;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;                            DragDockPanel PanelToAdd = CurrentElementAsUserControl.Content &lt;span class="kwrd"&gt;as&lt;/span&gt; DragDockPanel;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;                            CurrentElementAsUserControl.Content = &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;                            regionTarget.AddPanel(PanelToAdd);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;                        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;                    }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;                    &lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; (e.Action == NotifyCollectionChangedAction.Remove)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  22:  &lt;/span&gt;                    {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  23:  &lt;/span&gt;                        &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (FrameworkElement CurrentElement &lt;span class="kwrd"&gt;in&lt;/span&gt; e.OldItems)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  24:  &lt;/span&gt;                            regionTarget.Children.Remove(CurrentElement);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  25:  &lt;/span&gt;                    }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  26:  &lt;/span&gt;                };&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  27:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  28:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  29:  &lt;/span&gt;        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; IRegion CreateRegion()&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  30:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  31:  &lt;/span&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; AllActiveRegion();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  32:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  33:  &lt;/span&gt;    }&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;&lt;style type="text/css"&gt;&lt;![CDATA[



.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }]]&gt;&lt;/style&gt;

&lt;p&gt;The generic type used in the RegionAdapterBase class is the type of the class for which you need Prism to support as a region. The body of the effort is in the Adapt() method, which is called when controls are added or removed from the container.&lt;/p&gt;

&lt;p&gt;This class needs to be used in the shell’s Prism bootstrapper through an overloaded method called ConfigureRegionAdapterMappings():&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;    &lt;span class="kwrd"&gt;internal&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Bootstrapper : UnityBootstrapper&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; DependencyObject CreateShell()&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;            &lt;span class="rem"&gt;// ... snip&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; IModuleCatalog GetModuleCatalog()&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;            &lt;span class="rem"&gt;// ... snip&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt; &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; RegionAdapterMappings ConfigureRegionAdapterMappings()&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;            RegionAdapterMappings Mappings = &lt;span class="kwrd"&gt;base&lt;/span&gt;.ConfigureRegionAdapterMappings();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;            Mappings.RegisterMapping(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(DragDockPanelHost), Container.Resolve&amp;lt;DragDockPanelHostRegionAdapter&amp;gt;());&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; Mappings;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;    }&lt;/pre&gt;
&lt;/div&gt;
&lt;style type="text/css"&gt;&lt;![CDATA[


.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }]]&gt;&lt;/style&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;The region adapter is registered with Prism in the RegisterMapping() method of the RegionAdapterMappings class.&lt;/p&gt;

&lt;p&gt;With this, I can now define a user control in my Prism module that defines a DragDockPanel:&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;UserControl&lt;/span&gt; &lt;span class="attr"&gt;x:Class&lt;/span&gt;&lt;span class="kwrd"&gt;="Narrative.Units.View"&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;    &lt;span class="attr"&gt;xmlns&lt;/span&gt;&lt;span class="kwrd"&gt;="http://schemas.microsoft.com/winfx/2006/xaml/presentation"&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;    &lt;span class="attr"&gt;xmlns:x&lt;/span&gt;&lt;span class="kwrd"&gt;="http://schemas.microsoft.com/winfx/2006/xaml"&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;    &lt;span class="attr"&gt;xmlns:blacklight&lt;/span&gt;&lt;span class="kwrd"&gt;="clr-namespace:Blacklight.Controls;assembly=Blacklight.WPFControls"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;blacklight:DragDockPanel&lt;/span&gt; &lt;span class="attr"&gt;Header&lt;/span&gt;&lt;span class="kwrd"&gt;="Title"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;UserControl&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Then I can, in my Prism shell, define a DragDockPanelHost with a region:&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Window&lt;/span&gt; &lt;span class="attr"&gt;x:Class&lt;/span&gt;&lt;span class="kwrd"&gt;="App.MainWindow"&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;    &lt;span class="attr"&gt;xmlns&lt;/span&gt;&lt;span class="kwrd"&gt;="http://schemas.microsoft.com/winfx/2006/xaml/presentation"&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;    &lt;span class="attr"&gt;xmlns:x&lt;/span&gt;&lt;span class="kwrd"&gt;="http://schemas.microsoft.com/winfx/2006/xaml"&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;    &lt;span class="attr"&gt;xmlns:blacklight&lt;/span&gt;&lt;span class="kwrd"&gt;="clr-namespace:Blacklight.Controls;assembly=Blacklight.WPFControls"&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;    &lt;span class="attr"&gt;xmlns:regions&lt;/span&gt;&lt;span class="kwrd"&gt;="clr-namespace:Microsoft.Practices.Composite.Presentation.Regions;assembly=Microsoft.Practices.Composite.Presentation"&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;    &lt;span class="attr"&gt;Title&lt;/span&gt;&lt;span class="kwrd"&gt;="App Title"&lt;/span&gt; &lt;span class="attr"&gt;Height&lt;/span&gt;&lt;span class="kwrd"&gt;="300"&lt;/span&gt; &lt;span class="attr"&gt;Width&lt;/span&gt;&lt;span class="kwrd"&gt;="300"&lt;/span&gt; &lt;span class="attr"&gt;x:Name&lt;/span&gt;&lt;span class="kwrd"&gt;="Main"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Grid&lt;/span&gt; &lt;span class="attr"&gt;x:Name&lt;/span&gt;&lt;span class="kwrd"&gt;="MainGrid"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Grid.RowDefinitions&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;RowDefinition&lt;/span&gt; &lt;span class="attr"&gt;Height&lt;/span&gt;&lt;span class="kwrd"&gt;="auto"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;RowDefinition&lt;/span&gt; &lt;span class="attr"&gt;Height&lt;/span&gt;&lt;span class="kwrd"&gt;="auto"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;RowDefinition&lt;/span&gt; &lt;span class="attr"&gt;Height&lt;/span&gt;&lt;span class="kwrd"&gt;="*"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Grid.RowDefinitions&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;blacklight:DragDockPanelHost&lt;/span&gt; &lt;span class="attr"&gt;Background&lt;/span&gt;&lt;span class="kwrd"&gt;="Khaki"&lt;/span&gt; &lt;span class="attr"&gt;HorizontalAlignment&lt;/span&gt;&lt;span class="kwrd"&gt;="Stretch"&lt;/span&gt; &lt;span class="attr"&gt;VerticalAlignment&lt;/span&gt;&lt;span class="kwrd"&gt;="Stretch"&lt;/span&gt; &lt;span class="attr"&gt;Width&lt;/span&gt;&lt;span class="kwrd"&gt;="Auto"&lt;/span&gt; &lt;span class="attr"&gt;Height&lt;/span&gt;&lt;span class="kwrd"&gt;="Auto"&lt;/span&gt; &lt;span class="attr"&gt;Grid&lt;/span&gt;.&lt;span class="attr"&gt;Row&lt;/span&gt;&lt;span class="kwrd"&gt;="2"&lt;/span&gt; &lt;span class="attr"&gt;x:Name&lt;/span&gt;&lt;span class="kwrd"&gt;="PanelHost"&lt;/span&gt; &lt;span class="attr"&gt;Margin&lt;/span&gt;&lt;span class="kwrd"&gt;="15"&lt;/span&gt; &lt;span class="attr"&gt;regions:RegionManager&lt;/span&gt;.&lt;span class="attr"&gt;RegionName&lt;/span&gt;&lt;span class="kwrd"&gt;="PanelHostRegion"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Grid&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Window&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;This solved the issue, and I can now have my DragDockPanelHost in a Prism executable shell and a DragDockPanel user control in a Prism module.&lt;/p&gt;&lt;img src="http://geekswithblogs.net/JeffFerguson/aggbug/133172.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://geekswithblogs.net/JeffFerguson/comments/133172.aspx</wfw:comment>
        <slash:comments>13</slash:comments>
        <wfw:commentRss>http://geekswithblogs.net/JeffFerguson/comments/commentRss/133172.aspx</wfw:commentRss>
        <trackback:ping>http://geekswithblogs.net/JeffFerguson/services/trackbacks/133172.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Slides and Code for Lexical Analysis Talk</title>
        <link rel="self" type="text/html" href="http://geekswithblogs.net/JeffFerguson/archive/2009/04/10/slides-and-code-for-lexical-analysis-talk.aspx" />
        <id>http://geekswithblogs.net/JeffFerguson/archive/2009/04/10/slides-and-code-for-lexical-analysis-talk.aspx</id>
        <published>2009-04-10T07:42:39-05:00:00</published>
        <updated>2009-04-10T07:42:39Z</updated>
        <content type="html">&lt;p&gt;Last evening, I presented my “Inside Lexical Analysis” talk to the &lt;a href="http://www.twincitieslanguagesusergroup.com/"&gt;Twin Cities Languages User Group&lt;/a&gt; (TCLUG). I have posted both the &lt;a href="http://cwehyw.blu.livefilestore.com/y1p1_Wy35rd53iXlwDVvB2a069BSqsYRn6ey09PgIrGpqdtrgm20gaQt3S0Glf03eJVzPoenSv5tHn0I3HdSTSJkIofDz7Rad6w/Inside%20Lexical%20Analysis.pptx?download"&gt;slide deck&lt;/a&gt; and &lt;a href="http://cwehyw.blu.livefilestore.com/y1pcmMznhzunY8lk5jLhFdPzUh4eloVaKweBvB_VqBUgQpKOknxl-IzVgdtgF5mNFiVlChH1nJzqUT4etg0wIXW2Z0D4U4UX4ze/Code%20for%20Inside%20Lexical%20Analysis.zip?download"&gt;code samples&lt;/a&gt; that used during the talk; feel free to grab a copy if you wish. If you have any questions or comments about the material, feel free to get in touch with me and let me know (you can find me on Twitter &lt;a href="http://www.twitter.com/JeffFerguson"&gt;here&lt;/a&gt;, or leave a comment on this blog post).&lt;/p&gt;  &lt;p&gt;Many thanks to TCLUG coordinator (and friend and colleague) &lt;a href="http://www.jasonbock.net/"&gt;Jason Bock&lt;/a&gt; for arranging the event and allowing me the opportunity to speak!&lt;/p&gt;&lt;img src="http://geekswithblogs.net/JeffFerguson/aggbug/130889.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://geekswithblogs.net/JeffFerguson/comments/130889.aspx</wfw:comment>
        <slash:comments>5</slash:comments>
        <wfw:commentRss>http://geekswithblogs.net/JeffFerguson/comments/commentRss/130889.aspx</wfw:commentRss>
        <trackback:ping>http://geekswithblogs.net/JeffFerguson/services/trackbacks/130889.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Expression Evaluation Coming to MGrammar?</title>
        <link rel="self" type="text/html" href="http://geekswithblogs.net/JeffFerguson/archive/2009/04/01/expression-evaluation-coming-to-mgrammar.aspx" />
        <id>http://geekswithblogs.net/JeffFerguson/archive/2009/04/01/expression-evaluation-coming-to-mgrammar.aspx</id>
        <published>2009-04-01T07:47:25-05:00:00</published>
        <updated>2009-04-01T07:47:25Z</updated>
        <content type="html">&lt;p&gt;Consider the following simple calculator authored in &lt;a href="http://en.wikipedia.org/wiki/Yacc"&gt;yacc&lt;/a&gt;:&lt;/p&gt;  &lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt;   &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;%{  
    #include &amp;lt;stdio.h&amp;gt;   
    &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; yylex(&lt;span style="color: #0000ff"&gt;void&lt;/span&gt;);   
    &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; yyerror(&lt;span style="color: #0000ff"&gt;char&lt;/span&gt; *);   
%}   
  
%token INTEGER   
  
%%   
   
program:   
        program expr &lt;span style="color: #006080"&gt;'\n'&lt;/span&gt;         { printf(&lt;span style="color: #006080"&gt;"%d\n"&lt;/span&gt;, $2); }   
        |    
        ;   
  
expr:   
        INTEGER   
        | expr &lt;span style="color: #006080"&gt;'+'&lt;/span&gt; expr           { $$ = $1 + $3; }   
        | expr &lt;span style="color: #006080"&gt;'-'&lt;/span&gt; expr           { $$ = $1 - $3; }   
        ;   
  
%%   
  
&lt;span style="color: #0000ff"&gt;void&lt;/span&gt; yyerror(&lt;span style="color: #0000ff"&gt;char&lt;/span&gt; *s) {   
    fprintf(stderr, &lt;span style="color: #006080"&gt;"%s\n"&lt;/span&gt;, s);   
}   
  
&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; main(&lt;span style="color: #0000ff"&gt;void&lt;/span&gt;) {   
    yyparse();   
    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; 0;   
}   &lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;A notable feature of this grammar is that the syntax definitions are augmented with C code statements that are executed when the syntax is discovered in the input stream. This code is able to interpret the input and, if necessary, perform a calculation and send the result of the calculation into the abstract syntax tree (AST). Consider, for example, the following fragment from the &lt;strong&gt;yacc&lt;/strong&gt; grammar above:&lt;/p&gt;

&lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt;
  &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;expr &lt;span style="color: #006080"&gt;'+'&lt;/span&gt; expr           { $$ = $1 + $3; } &lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;strong&gt;yacc&lt;/strong&gt; engine will assign temporary variables to matching input as follows:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;$1: the first expression &lt;/li&gt;

  &lt;li&gt;$2: the ‘+’ token &lt;/li&gt;

  &lt;li&gt;$3: the second expression &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An additional variable, called $$, contains the results of the parsed input. In this fragment, the equivalent of an anonymous delegate includes C code to perform the addition operation on the contents of $1 and $3 and place the results in $$. With this, some work can be done “in place” to not only construct, but also to evaluate, the AST.&lt;/p&gt;

&lt;p&gt;This background information is necessary to understand the following: MGrammar has no such capability today. Anonymous methods cannot be attached to MGrammar syntax productions, and “in place” interpretations of the AST in this manner is not possible.&lt;/p&gt;

&lt;p&gt;However, this doesn’t mean that such a feature will never appear in MGrammar. In &lt;a href="http://social.msdn.microsoft.com/Forums/en-US/oslo/thread/625ba3a1-df8c-416a-917d-a4a99a0a8aa5/"&gt;discussing this issue&lt;/a&gt; in the &lt;a href="http://social.msdn.microsoft.com/Forums/en-US/oslo/threads"&gt;MSDN Forums for “Oslo”&lt;/a&gt;, Microsoft’s Paul Vick made this comment: &lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;I thought I'd interject that we're considering ways to evaluate expressions directly in grammars. It's a pretty useful feature, and we'd love to provide the full M expression capabilities on the RHS of a grammar production. So stay tuned!&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Disclaimer&lt;/strong&gt;&lt;/em&gt;:This does not represent an official commitment from Microsoft. Don’t read too much into this. It might happen. It might not. Don’t storm Paul’s office with torches and pitchforks if it doesn’t appear. But Microsoft is thinking about it, and that’s all we can ask.&lt;/p&gt;&lt;img src="http://geekswithblogs.net/JeffFerguson/aggbug/130633.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://geekswithblogs.net/JeffFerguson/comments/130633.aspx</wfw:comment>
        <slash:comments>3</slash:comments>
        <wfw:commentRss>http://geekswithblogs.net/JeffFerguson/comments/commentRss/130633.aspx</wfw:commentRss>
        <trackback:ping>http://geekswithblogs.net/JeffFerguson/services/trackbacks/130633.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Error 8013150A Importing TFS Work Item Templates with TFS Power Tools</title>
        <link rel="self" type="text/html" href="http://geekswithblogs.net/JeffFerguson/archive/2009/03/30/error-8013150a-importing-tfs-work-item-templates-with-tfs-power.aspx" />
        <id>http://geekswithblogs.net/JeffFerguson/archive/2009/03/30/error-8013150a-importing-tfs-work-item-templates-with-tfs-power.aspx</id>
        <published>2009-03-30T09:30:38-05:00:00</published>
        <updated>2009-03-30T09:30:38Z</updated>
        <content type="html">&lt;p&gt;I just ran across this error while using the Team Foundation Server Power Tools to import a work item template XML document into a TFS instance:&lt;/p&gt;  &lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt;   &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;Error 0x8013150A: An error relating to security occurred.&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;So it’s a security issue, right? No.&lt;/p&gt;

&lt;p&gt;As it turns out, I had edited the XML file in Notepad and added values to a field definition with the ALLOWEDVALUES rule. In my over-zealous copy-and-paste efforts, I had added a few of the allowable values in more than one place:&lt;/p&gt;

&lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt;
  &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&amp;lt;FIELD reportable=&lt;span style="color: #006080"&gt;"dimension"&lt;/span&gt; type=&lt;span style="color: #006080"&gt;"String"&lt;/span&gt; name=&lt;span style="color: #006080"&gt;"MyName"&lt;/span&gt; refname=&lt;span style="color: #006080"&gt;"MyProject.MyName"&lt;/span&gt;&amp;gt;
  &amp;lt;ALLOWEDVALUES&amp;gt;
    &amp;lt;LISTITEM &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;=&lt;span style="color: #006080"&gt;"Value1"&lt;/span&gt; /&amp;gt;
    &amp;lt;LISTITEM &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;=&lt;span style="color: #006080"&gt;"Value2"&lt;/span&gt; /&amp;gt;
    &amp;lt;LISTITEM &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;=&lt;span style="color: #006080"&gt;"Value3"&lt;/span&gt; /&amp;gt;
    &amp;lt;LISTITEM &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;=&lt;span style="color: #006080"&gt;"Value1"&lt;/span&gt; /&amp;gt;
    &amp;lt;!-- more values --&amp;gt;
  &amp;lt;/ALLOWEDVALUES&amp;gt;
&amp;lt;/FIELD&amp;gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The attempt to import this file into the TFS Process Editor Power Tool failed with the 8013150A error. After playing with security rights for a while, to no avail, I decided to double check my edits. I found and removed the duplicate entries in Notepad and tried again to load the file into TFS Process Editor Power Tool. Success!&lt;/p&gt;

&lt;p&gt;Just thought that I would document the issue in case someone else runs across the same problem. The moral of the story is this: an error message of “an error relating to security occurred” does not necessarily mean that you have a security issue with your file. Check the contents of the file and make sure that is valid with regards to both syntax and semantics. In particular, do not list an item in an ALLOWEDVALUES list more than once … or you’ll get a security error … which makes perfect sense … I guess …&lt;/p&gt;&lt;img src="http://geekswithblogs.net/JeffFerguson/aggbug/130522.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://geekswithblogs.net/JeffFerguson/comments/130522.aspx</wfw:comment>
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://geekswithblogs.net/JeffFerguson/comments/commentRss/130522.aspx</wfw:commentRss>
        <trackback:ping>http://geekswithblogs.net/JeffFerguson/services/trackbacks/130522.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Interpreting Mathematical Operators in MGrammar</title>
        <link rel="self" type="text/html" href="http://geekswithblogs.net/JeffFerguson/archive/2009/03/24/interpreting-mathematical-operators-in-mgrammar.aspx" />
        <id>http://geekswithblogs.net/JeffFerguson/archive/2009/03/24/interpreting-mathematical-operators-in-mgrammar.aspx</id>
        <published>2009-03-24T09:23:15-05:00:00</published>
        <updated>2009-03-24T09:23:15Z</updated>
        <content type="html">&lt;p&gt;Suppose that you have a need for a domain specific language that supports mathematical expressions. Specifically, you want to support the following:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;unsigned integers&lt;/li&gt;    &lt;li&gt;signed integers&lt;/li&gt;    &lt;li&gt;addition expressions&lt;/li&gt;    &lt;li&gt;subtraction expressions&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Your first attempt at such a grammar using MGrammar might look like this:&lt;/p&gt;  &lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt;   &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;module JeffFerguson.BlogPosts
{
    
    language MathOps
    {
        
        // ignore whitespace
        
        syntax LF = "\u000A";
        syntax CR = "\u000D";
        syntax Space = "\u0020";
        interleave Whitespace = LF | CR | Space;
        
        // operators
        
        token PlusOperator = "+";
        token MinusOperator = "-";
        token StatementEnd = ";";
        
        // numerics
        
        token UnaryOperator = PlusOperator | MinusOperator;
        token Digit = "0".."9";
        token WholeNumber = UnaryOperator? Digit+;
        
        // expressions
        
        syntax AdditionExpression = t1:WholeNumber PlusOperator t2:WholeNumber =&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;Add[t1,t2];
        syntax SubtractionExpression = t1:WholeNumber MinusOperator t2:WholeNumber =&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt; Subtract[t1,t2];
        syntax MathematicalExpression =
            WholeNumber
            | AdditionExpression
            | SubtractionExpression;
                             
        // language syntax
        syntax Statement = e:MathematicalExpression StatementEnd =&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt; Statement[valuesof(e)];
        syntax Main = Statement*;
    }
}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;There is a subtle problem with this grammar. Suppose that you offer the following input to the grammar:&lt;/p&gt;

&lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt;
  &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;1;
+2;
-3;
4+5;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This input will give you errors:&lt;/p&gt;

&lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt;
  &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;[file://untitled1/#4,2-4,4] error 5007: Token JeffFerguson.BlogPosts.MathOps.WholeNumber with text "+5" unexpected. 
[file://untitled1/#4,2-4,4] message 5011: Assuming an insertion of value ';' to continue parsing. Could also have inserted '-', '+'.&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The problem is with the “4+5” statement. The issue here is that the “+” symbol is being interpreted as the unary operator for the “5” symbol, and MGrammar is attempting to see the “4” and the “+5” as separate symbols, which is not what was intended. Rather, the input most likely meant to offer the “4+5” (as in “9”, for those of you not up on your math) as an additive operator.&lt;/p&gt;

&lt;p&gt;The issue has to do with the fact that MGrammar’s lexical analysis engine runs before the grammatical parser, just as &lt;strong&gt;lex&lt;/strong&gt; runs before &lt;strong&gt;yacc&lt;/strong&gt;. This means that token operations in an MGrammar definition are interpreted before the syntax definitions. Since the unary operator is defined as part of a token definition, then that binding will take precedence over the addition syntax.&lt;/p&gt;

&lt;p&gt;This can be fixed by specifying the unary operator as a syntax definition with a slight change to the grammar:&lt;/p&gt;

&lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt;
  &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;module JeffFerguson.BlogPosts
{
    
    language MathOps
    {
        
        // ignore whitespace
        
        syntax LF = "\u000A";
        syntax CR = "\u000D";
        syntax Space = "\u0020";
        interleave Whitespace = LF | CR | Space;
        
        // operators
        
        token PlusOperator = "+";
        token MinusOperator = "-";
        token StatementEnd = ";";
        
        // numerics
        
        token UnaryOperator = PlusOperator | MinusOperator;
        token Digit = "0".."9";
        syntax WholeNumber =
            n:Digit+ =&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt; UnsignedNumber[n]
            | s:UnaryOperator n:Digit+ =&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt; SignedNumber[s, valuesof(n)]
            ;
        
        // expressions
        
        syntax AdditionExpression = t1:WholeNumber PlusOperator t2:WholeNumber =&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;Add[t1,t2];
        syntax SubtractionExpression = t1:WholeNumber MinusOperator t2:WholeNumber =&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt; Subtract[t1,t2];
        syntax MathematicalExpression =
            WholeNumber
            | AdditionExpression
            | SubtractionExpression;
                             
        // language syntax
        syntax Statement = e:MathematicalExpression StatementEnd =&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt; Statement[valuesof(e)];
        syntax Main = Statement*;
    }
}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The abstract syntax tree (AST) for the input now looks like this:&lt;/p&gt;

&lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt;
  &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;Main[
  [
    Statement[
      UnsignedNumber[
        [
          "1"
        ]
      ]
    ],
    Statement[
      SignedNumber[
        "+",
        "2"
      ]
    ],
    Statement[
      SignedNumber[
        "-",
        "3"
      ]
    ],
    Statement[
      Add[
        UnsignedNumber[
          [
            "4"
          ]
        ],
        UnsignedNumber[
          [
            "5"
          ]
        ]
      ]
    ]
  ]
]&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;All better.&lt;/p&gt;&lt;img src="http://geekswithblogs.net/JeffFerguson/aggbug/130360.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://geekswithblogs.net/JeffFerguson/comments/130360.aspx</wfw:comment>
        <slash:comments>1</slash:comments>
        <wfw:commentRss>http://geekswithblogs.net/JeffFerguson/comments/commentRss/130360.aspx</wfw:commentRss>
        <trackback:ping>http://geekswithblogs.net/JeffFerguson/services/trackbacks/130360.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Defining String Literals in MGrammar</title>
        <link rel="self" type="text/html" href="http://geekswithblogs.net/JeffFerguson/archive/2009/03/21/defining-string-literals-in-mgrammar.aspx" />
        <id>http://geekswithblogs.net/JeffFerguson/archive/2009/03/21/defining-string-literals-in-mgrammar.aspx</id>
        <published>2009-03-21T19:03:12-05:00:00</published>
        <updated>2009-03-21T19:03:12Z</updated>
        <content type="html">&lt;p&gt;Consider a language authored in MGrammar that recognizes a keyword named “keyword” as well as string literals:&lt;/p&gt;  &lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt;   &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;module MyModule
{
    language MyLanguage
    {
        // ignore whitespace
        
        syntax LF = &lt;span style="color: #006080"&gt;"\u000A"&lt;/span&gt;;
        syntax CR = &lt;span style="color: #006080"&gt;"\u000D"&lt;/span&gt;;
        syntax Space = &lt;span style="color: #006080"&gt;"\u0020"&lt;/span&gt;;
        interleave Whitespace = LF | CR | Space;
        
        // string literals
        token Quote = &lt;span style="color: #006080"&gt;"\""&lt;/span&gt;;
        token StringLiteral = Quote a:any* Quote =&amp;gt; StringLiteral[a];
        token Keyword = &lt;span style="color: #006080"&gt;"keyword"&lt;/span&gt;;
        
        // statements
        token Semicolon = &lt;span style="color: #006080"&gt;";"&lt;/span&gt;;
        syntax Statement = s:(Keyword | StringLiteral) Semicolon =&amp;gt; Statement[s];
        syntax Main = Statement*;
    }
}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Now consider some sample input:&lt;/p&gt;

&lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt;
  &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;keyword;
&lt;span style="color: #006080"&gt;"this is a string"&lt;/span&gt;;
keyword;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Given this sample input, you would expect the abstract syntax tree (AST) for this input to define two “keyword" statements and one string literal. This is, in fact, exactly what happens:&lt;/p&gt;

&lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt;
  &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;Main[
  [
    Statement[
      [
        &lt;span style="color: #006080"&gt;"keyword"&lt;/span&gt;
      ]
    ],
    Statement[
      [
        StringLiteral[
          &lt;span style="color: #006080"&gt;"this is a string"&lt;/span&gt;
        ]
      ]
    ],
    Statement[
      [
        &lt;span style="color: #006080"&gt;"keyword"&lt;/span&gt;
      ]
    ]
  ]
]&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;But what happens when two string literals appear in the input, as in the following example?&lt;/p&gt;

&lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt;
  &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;keyword;
&lt;span style="color: #006080"&gt;"this is a string"&lt;/span&gt;;
keyword;
&lt;span style="color: #006080"&gt;"this is another string"&lt;/span&gt;;
keyword;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Given this sample input, you would expect the abstract syntax tree (AST) for this input to define two “keyword" statements and two string literals. This is, in fact, not what happens. The AST you’ll get back looks like this:&lt;/p&gt;

&lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt;
  &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;Main[
  [
    Statement[
      [
        &lt;span style="color: #006080"&gt;"keyword"&lt;/span&gt;
      ]
    ],
    Statement[
      [
        StringLiteral[
          &lt;span style="color: #006080"&gt;"this is a string\";\r\nkeyword;\r\n\"this is another string"&lt;/span&gt;
        ]
      ]
    ],
    Statement[
      [
        &lt;span style="color: #006080"&gt;"keyword"&lt;/span&gt;
      ]
    ]
  ]
]&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The problem lies in the grammar’s definition of a string literal. The definition states that a string literal starts with a quotation mark and finishes with a quotation mark. The input parsing engine for M, however, is as greedy as possible, swallowing as much input as possible until the syntax definition can no longer be satisfied. In this case, it finds the very last quotation mark in the input and uses that entire text as the string literal. This is not what we want.&lt;/p&gt;

&lt;p&gt;The workaround for this is to reduce our definition of what should appear between the quotation marks from the &lt;strong&gt;any&lt;/strong&gt; keyword, which states that any character can appear, to a definition which states that any character but a quotation mark can appear. The definition now looks like this:&lt;/p&gt;

&lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt;
  &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;token StringLiteral = Quote a:(any - Quote)* Quote =&amp;gt; StringLiteral[a];&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The AST for the input now looks as we expect:&lt;/p&gt;

&lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt;
  &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;Main[
  [
    Statement[
      [
        &lt;span style="color: #006080"&gt;"keyword"&lt;/span&gt;
      ]
    ],
    Statement[
      [
        StringLiteral[
          &lt;span style="color: #006080"&gt;"this is a string"&lt;/span&gt;
        ]
      ]
    ],
    Statement[
      [
        &lt;span style="color: #006080"&gt;"keyword"&lt;/span&gt;
      ]
    ],
    Statement[
      [
        StringLiteral[
          &lt;span style="color: #006080"&gt;"this is another string"&lt;/span&gt;
        ]
      ]
    ],
    Statement[
      [
        &lt;span style="color: #006080"&gt;"keyword"&lt;/span&gt;
      ]
    ]
  ]
]&lt;/pre&gt;
&lt;/div&gt;
Much better!

&lt;img src="http://geekswithblogs.net/JeffFerguson/aggbug/130298.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://geekswithblogs.net/JeffFerguson/comments/130298.aspx</wfw:comment>
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://geekswithblogs.net/JeffFerguson/comments/commentRss/130298.aspx</wfw:commentRss>
        <trackback:ping>http://geekswithblogs.net/JeffFerguson/services/trackbacks/130298.aspx</trackback:ping>
    </entry>
    <entry>
        <title>Making MGrammar Graph Traversal Easier</title>
        <link rel="self" type="text/html" href="http://geekswithblogs.net/JeffFerguson/archive/2009/03/18/making-mgrammar-graph-traversal-easier.aspx" />
        <id>http://geekswithblogs.net/JeffFerguson/archive/2009/03/18/making-mgrammar-graph-traversal-easier.aspx</id>
        <published>2009-03-18T08:06:06-05:00:00</published>
        <updated>2009-03-18T08:08:44Z</updated>
        <content type="html">&lt;p&gt;Do you enjoy writing the code to navigate graphs produced by MGrammar, looking for the nodes that you need? Neither do I.&lt;/p&gt;  &lt;p&gt;I have written a small helper class to make graph navigation just a little bit easier. The class, which I have called GraphNavigator, performs all of the navigation and calls delegates when interesting nodes are found. Here is an example usage:&lt;/p&gt;  &lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt;   &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;     &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; GraphNavigator Nav = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; GraphNavigator(&lt;span style="color: #006080"&gt;"Grammar.mgx"&lt;/span&gt;, &lt;span style="color: #006080"&gt;"JeffFerguson.Calculatix.Grammars.Calculus"&lt;/span&gt;);&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; Nav.AddNodeProcessorDelegate(&lt;span style="color: #006080"&gt;"Line"&lt;/span&gt;, LineNodeDelegate);&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt; Nav.AddNodeProcessorDelegate(&lt;span style="color: #006080"&gt;"Point"&lt;/span&gt;, PointNodeDelegate);&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt; Nav.AddNodeProcessorDelegate(&lt;span style="color: #006080"&gt;"Show"&lt;/span&gt;, ShowNodeDelegate);&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt; Nav.AddNodeProcessorDelegate(&lt;span style="color: #006080"&gt;"StringLiteral"&lt;/span&gt;, StringLiteralNodeDelegate);&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt; Nav.AddNodeProcessorDelegate(&lt;span style="color: #006080"&gt;"Slope"&lt;/span&gt;, SlopeNodeDelegate);&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt; Nav.Parse(&lt;span style="color: #006080"&gt;"SourceInputFile.txt"&lt;/span&gt;);&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;The key here is in the AddNodeProcessorDelegate() method. It accepts two arguments:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;the name of a node&lt;/li&gt;

  &lt;li&gt;a delegate to a method to be called when the named node is found during graph traversal. In the first example on line 2, the GraphNavigator is instructed to call the LineNodeDelegate() method when a node labeled “Line” is found in the tree.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The delegates, when called, are called with two arguments:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;a reference to the GraphBuilder object used to build the graph&lt;/li&gt;

  &lt;li&gt;an object representing the discovered node&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An example delegate implementation is as follows:&lt;/p&gt;

&lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt;
  &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;
    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; LineNodeDelegate(GraphBuilder builder, &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; LineNode)&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     Line NewLine = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Line();&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     NewLine.Name = builder.GetSequenceElementAt(LineNode, 0) &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;     NewLine.Point2 = thisValueStack.Pop() &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; Point;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     NewLine.Point1 = thisValueStack.Pop() &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; Point;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;     thisLines.Add(NewLine);&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt; }&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;This seemed, at least to me, a bit easier than doing all of the navigation inline.&lt;/p&gt;

&lt;p&gt;The implementation of the GraphNavigator class, which really isn’t all that complicated, is as follows:&lt;/p&gt;

&lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt;
  &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;
    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Dataflow;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.IO;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;  &lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt; JeffFerguson.Oslo.MGrammar&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt; {&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;internal&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; GraphNavigator&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;     {&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;internal&lt;/span&gt; &lt;span style="color: #0000ff"&gt;delegate&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; NodeProcessorDelegate(GraphBuilder Builder, &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; Node);&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;  &lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; DynamicParser thisParser;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; thisGraphRoot;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  13:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; Dictionary&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;, NodeProcessorDelegate&amp;gt; thisNodeDictionary;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  14:&lt;/span&gt;  &lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  15:&lt;/span&gt;         &lt;span style="color: #008000"&gt;//-----------------------------------------------------------------------------------&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  16:&lt;/span&gt;         &lt;span style="color: #008000"&gt;//-----------------------------------------------------------------------------------&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  17:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;internal&lt;/span&gt; GraphNavigator(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; MgxFile, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; LanguageName)&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  18:&lt;/span&gt;         {&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  19:&lt;/span&gt;             thisParser = DynamicParser.LoadFromMgx(MgxFile, LanguageName);&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  20:&lt;/span&gt;             thisNodeDictionary = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;, NodeProcessorDelegate&amp;gt;();&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  21:&lt;/span&gt;         }&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  22:&lt;/span&gt;  &lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  23:&lt;/span&gt;         &lt;span style="color: #008000"&gt;//-----------------------------------------------------------------------------------&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  24:&lt;/span&gt;         &lt;span style="color: #008000"&gt;//-----------------------------------------------------------------------------------&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  25:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;internal&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; AddNodeProcessorDelegate(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; NodeName, NodeProcessorDelegate NodeDelegate)&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  26:&lt;/span&gt;         {&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  27:&lt;/span&gt;             thisNodeDictionary.Add(NodeName, NodeDelegate);&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  28:&lt;/span&gt;         }&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  29:&lt;/span&gt;  &lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  30:&lt;/span&gt;         &lt;span style="color: #008000"&gt;//-----------------------------------------------------------------------------------&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  31:&lt;/span&gt;         &lt;span style="color: #008000"&gt;//-----------------------------------------------------------------------------------&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  32:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;internal&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Parse(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; SourceFileName)&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  33:&lt;/span&gt;         {&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  34:&lt;/span&gt;             StreamReader SourceFileReader = File.OpenText(SourceFileName);&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  35:&lt;/span&gt;             Parse(SourceFileReader);&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  36:&lt;/span&gt;             SourceFileReader.Close();&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  37:&lt;/span&gt;             SourceFileReader.Dispose();&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  38:&lt;/span&gt;         }&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  39:&lt;/span&gt;  &lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  40:&lt;/span&gt;         &lt;span style="color: #008000"&gt;//-----------------------------------------------------------------------------------&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  41:&lt;/span&gt;         &lt;span style="color: #008000"&gt;//-----------------------------------------------------------------------------------&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  42:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;internal&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Parse(StreamReader SourceStreamReader)&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  43:&lt;/span&gt;         {&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  44:&lt;/span&gt;             thisGraphRoot = thisParser.Parse&amp;lt;&lt;span style="color: #0000ff"&gt;object&lt;/span&gt;&amp;gt;(&lt;span style="color: #0000ff"&gt;null&lt;/span&gt;, SourceStreamReader, ErrorReporter.Standard);&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  45:&lt;/span&gt;             EnumerateGraph(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; GraphBuilder(), thisGraphRoot);&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  46:&lt;/span&gt;         }&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  47:&lt;/span&gt;  &lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  48:&lt;/span&gt;         &lt;span style="color: #008000"&gt;//-----------------------------------------------------------------------------------&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  49:&lt;/span&gt;         &lt;span style="color: #008000"&gt;//-----------------------------------------------------------------------------------&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  50:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; EnumerateGraph(GraphBuilder builder, &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; node)&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  51:&lt;/span&gt;         {&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  52:&lt;/span&gt;             NodeProcessorDelegate NodeDelegate = &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  53:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; Label = builder.GetLabel(node);&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  54:&lt;/span&gt;  &lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  55:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (Label != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  56:&lt;/span&gt;             {&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  57:&lt;/span&gt;                 Identifier IdentifierLabel = Label &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; Identifier;&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  58:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (IdentifierLabel != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  59:&lt;/span&gt;                     thisNodeDictionary.TryGetValue(IdentifierLabel.Text, &lt;span style="color: #0000ff"&gt;out&lt;/span&gt; NodeDelegate);&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  60:&lt;/span&gt;             }&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  61:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;object&lt;/span&gt; ChildNode &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; builder.GetSequenceElements(node))&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  62:&lt;/span&gt;             {&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  63:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; ((ChildNode &lt;span style="color: #0000ff"&gt;is&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;) == &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;)&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  64:&lt;/span&gt;                     EnumerateGraph(builder, ChildNode);&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  65:&lt;/span&gt;             }&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  66:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (NodeDelegate != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  67:&lt;/span&gt;                 NodeDelegate(builder, node);&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  68:&lt;/span&gt;         }&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  69:&lt;/span&gt;     }&lt;/pre&gt;

    &lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  70:&lt;/span&gt; }&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;I hope you find it useful. Enjoy!&lt;/p&gt;&lt;img src="http://geekswithblogs.net/JeffFerguson/aggbug/130188.aspx" width="1" height="1" /&gt;</content>
        <wfw:comment>http://geekswithblogs.net/JeffFerguson/comments/130188.aspx</wfw:comment>
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://geekswithblogs.net/JeffFerguson/comments/commentRss/130188.aspx</wfw:commentRss>
        <trackback:ping>http://geekswithblogs.net/JeffFerguson/services/trackbacks/130188.aspx</trackback:ping>
    </entry>
</feed>