views:

108

answers:

3

I am reading the The Pragmatic programmer and doing the following exercise in .net world (Chapter 3 - Code Generators)

The Exercise

"Write a code generator that takes the input in Listing 1, and generates output in two languages of your choice. Try to make it easy to add new languages."

Listing 1
# Add a product
# to the 'on-order' list
M AddProduct
F id                 int
F name           char[30]
F order_code  int
E

How would you implement the solution in T4 or anything else in .net world (CodeDOM is too complex) so that we can generate the code in c# and in one other .net language (visual basic or IronRuby etc.)

A: 

I know you say CodeDOM is too complex, but I would suggest using CodeDOM =). Here's a short example to start with: http://asp.dotnetheaven.com/howto/doc/listbuilder.aspx. For your example, you probably want to add a CodeMemberMethod to CodeTypeDeclaration's members - MSDN has some examples.

T4 could work, but it I don't think it's really ideal for this situation.

Aeka
A: 

I don't think this is intended to be an exercise in working with existing code generators. Actually there's much more to it. The goal, I believe, is to build your own code generator, domain-specific language and deal with concepts like parsing and extensibility/pluggability. Perhaps I am reading too much into the exercise, but perhaps it's more about developing core developer skills/knowledge than educating oneself on existing tools.

Ben Griswold
Here you go: http://www.theserverside.com/news/1365073/The-Pragmatic-Code-Generator-Programmer. This write up gets to the essence of the exercise rather nicely. Good luck.
Ben Griswold
A: 

Taking Ben Griswold advice, I think it is a good idea to implement it myself. And while just a little into implementing code generator in C#, I realized few things -
1. Need text manipulation language like Python etc.
2. Need to learn Regular expressions

I do intend to implement it in Ruby but for now, I implemented it in C# as -

static void Main(string[] args)
{
    CodeGenerator gen = new CodeGenerator();
    gen.ReadFile("Input.txt");
}
public class CodeGenerator
{
    public void ReadFile(string filename)
    {
        StreamReader fs = new StreamReader(filename);
        string line;
        CSharpCode CG = new CSharpCode();

        while ((line = fs.ReadLine()) != null)
        {
            line = line.TrimEnd('\n');

            if (Regex.IsMatch(line, @"^\s*S"))
                CG.BlankLine();
            else if (Regex.IsMatch(line, @"^\#(.*)")) // match comments
                CG.Comment(line.TrimStart('#'));
            else if (Regex.IsMatch(line, @"^M\s*(.+)")) // start msg
                CG.StartMsg(line.Split(' ')[1]);
            else if (Regex.IsMatch(line, @"^E")) // end msg
                CG.EndMsg();
            else if (Regex.IsMatch(line, @"^F\s*(\w+)")) // simple type
                CG.SimpleType(Regex.Split(line, @"^F\s*(\w+)")[1], Regex.Split(line, @"^F\s*(\w+)")[2]);
            else
                Console.WriteLine("Invalid line " + line);
        }
    }
}

// Code Generator for C#
public class CSharpCode
{
    public void BlankLine() { Console.WriteLine(); }
    public void Comment(string comment) { Console.WriteLine("//" + comment); }
    public void StartMsg(string name) { Console.WriteLine("public struct " + name + "{"); }
    public void EndMsg() { Console.WriteLine("}"); }
    public void SimpleType(string name, string type)
    {
        if(type.Contains("char["))
            type = "string";

        Console.WriteLine(string.Format("\t{0} {1};", type.Trim(), name));
    }
}  
The ruby version http://devnetfx.blogspot.com/2010/10/code-generation-in-ruby.html