Tuesday, July 03, 2007

So I've tidied up the source for the DSL from my last post a little... though my "test" was to represent a DSL similar to the one Ayende displayed in Brail - I haven't implemented any monorail view engine integration, there's little point I feel, I was more interested in being able to display a nested DSL-like syntax, and parse the necessary information out of it as required. 

You can grab it from SVN repository here (edit: I've now fix the PROPFIND proxy issue, so the link should work)

At any rate, probably the most interesting example is the one that takes this code:

var people = new List<Person>()
{
    new Person() { FirstName = "Alex", LastName = "Henderson"},
    new Person() { FirstName = "Joe", LastName = "Bloggs"}
};
 
var compDsl = new ComponentDsl();
 
compDsl.Add
(
    GridComponent => compDsl.Component
    (
        compDsl.Parameters
        (
            source => people
        ),
        header => compDsl.Section
        (
            tr => compDsl.As
            (
                th => compDsl.As
                (
                    compDsl.Text("Names")
                )
            )
        ),
        item => compDsl.Section
        (
            tr => compDsl.As
            (
                td => compDsl.As
                (
                    compDsl.Item<Person>(p => p.FirstName + " " + p.LastName)
                )
            )
        )
    )
);
 
var dsl = new StandardDsl();
 
dsl.Add
(
    html => dsl.As
    (
        body => compDsl
    )
);

And converts it to this xhtml...

<html>
  <body>
    <table>
      <tr>
        <th>Names</th>
      </tr>
      <tr>
        <td>Alex Henderson</td>
      </tr>
      <tr>
        <td>Joe Bloggs</td>
      </tr>
    </table>
  </body>
</html>

You can pretty quickly figure out what's going on by placing a breakpoint on the Execute() method of the StandardDsl class and tracing through all the calls - in essence all the nodes are emitted by calling the top-level Batch delegate which causes a recursive call down the "tree", with the information being emitted as a side-effect to an evaluation scope.

Though I used nodes - effectively creating a structure that's easier to parse, there's no reason why you couldn't make immediate calls to some kind of object, avoiding the need for a second round of parsing - the only trick is that you'd still need to use some kind of scoped stack to push/pop the names of the components because in a statement like this:

dsl.As
(
    GridComponent => dsl.Component
    (
      // etc. etc.
    )  
)


the call to dsl.Component needs some way to inspect the stack of names and pull "GridComponent" off the top.

I'd love to hear from anyone who could see a use for this kind of thing... it'd be nice to get a more realistic example... I'm struggling to think of anything practical myself.

[Edit: I Noticed the code formatting was pretty awful, so I've tidied it up a little... anyone got a good solution for copy/pasting code out of orcas (CopyAsHtml2005 doesn't appear to install under Orcas)]
 |  | 
posted @ Tuesday, July 03, 2007 11:01:26 AM (New Zealand Standard Time, UTC+12:00)    Comments [2] | Trackback | Tracked by:
"Writing a DSL using nested lambda's in C# 3.0" (DotNetKicks.com) [Trackback]
"mucking about with hashes..." (Bitter Coder) [Trackback]
Search
FeedCount

Tags...
Who am I?
Alex Henderson
Alex Henderson
Auckland, New Zealand
Managing Director at Dev|Defined Limited

"Self Confessed Coding Junky for 15 years"
View Alex Henderson's profile on LinkedIn
 
Mobile: +64-21-402-969
Email: bittercoder 'at' gmail 'dot' com
MSN: bittercoder_nz@hotmail
Skype: alex.devdefined
Navigation