Angel \”Java\” Lopez on Blog

September 9, 2010

Writing an Interpreter in .NET (Part 5)

Filed under: .NET, Programming Languages, Test-Driven Development — ajlopez @ 9:45 am

Continuing with this series, this time I added a simple parser. The new solution:

You can download from InterpreterStep05.zip.

The new class is:

The parser can be constructed using a TextReader or a string:

    public class Parser
    {
        private Lexer lexer;
        public Parser(Lexer lexer)
        {
            this.lexer = lexer;
        }
        public Parser(TextReader reader)
            : this(new Lexer(reader))
        {
        }
        public Parser(string text)
            : this(new Lexer(text))
        {
        }
//...
    }

I have only two defined expressions (ConstantExpression and VariableExpression). The public method ParseExpression now recognize integers and names (the lexer still does not recognize delimeted strings):

        public IExpression ParseExpression()
        {
            Token token = this.NextToken();
            if (token == null)
                return null;
            if (token.TokenType == TokenType.Integer)
                return new ConstantExpression(token.Value);
            if (token.TokenType == TokenType.String)
                return new ConstantExpression(token.Value);
            if (token.TokenType == TokenType.Name)
                return new VariableExpression((string) token.Value);
            throw new InvalidDataException(string.Format("Unexpected token '{0}'",
                 token.Value));
        }

The parser uses the lexer defined in the previous post. As usual, the new Parser and ParseExpression were written using TDD. Some tests:

        [TestMethod]
        public void ParseIntegerExpression()
        {
            Parser parser = new Parser("1");
            IExpression expression = parser.ParseExpression();
            Assert.IsNotNull(expression);
            Assert.IsInstanceOfType(expression, typeof(ConstantExpression));
            Assert.AreEqual(1, expression.Evaluate(null));
            Assert.IsNull(parser.ParseExpression());
        }
        [TestMethod]
        public void ParseVariableExpression()
        {
            Parser parser = new Parser("one");
            IExpression expression = parser.ParseExpression();
            Assert.IsNotNull(expression);
            Assert.IsInstanceOfType(expression, typeof(VariableExpression));
            VariableExpression varexpr = (VariableExpression)expression;
            Assert.AreEqual("one", varexpr.Name);
            Assert.IsNull(parser.ParseExpression());
        }

All tests in green:

Good code coverage:

Note that using TDD, I can add features in “baby steps”, avoiding debugging times and big chunks of added code. And I have the “green” feedback: each new functionality is tested and it doesn’t broke the previous code.

Next steps: add more expressions (binary arithmetic expressions, operators, …) and commands (if, for, …), “training” parser to process them, and add to lexer the process of delimited strings.

Keep tuned!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

1 Comment »

  1. I lately stumbled upon your blog and wanted to sway that I procure in reality enjoyed reading your blog post.

    Comment by teak gartenmöbel — March 7, 2011 @ 10:25 am


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at WordPress.com.

%d bloggers like this: