Escribiendo un intérprete en .NET (Parte 5)

Continuando con esta serie de posts, esta vez agregaré un parser sencillo. La nueva solución:

Pueden bajar el código desde InterpreterStep05.zip. La nueva clase agregada es:

El parse puede ser construido usando un TextReader o un 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))
        {
        }
//...
    }

Tengo sólo dos Expr essions por ahora (ConstantExpr ession y VariableExpr ession). El método público ParseExpr ession ahora reconoce enteros y nombres(el lexer todavía no reconoce strings delimitados):

        public IExpr ession ParseExpr ession()
        {
            Token token = this.NextToken();
            if (token == null)
                return null;
            if (token.TokenType == TokenType.Integer)
                return new ConstantExpr ession(token.Value);
            if (token.TokenType == TokenType.String)
                return new ConstantExpr ession(token.Value);
            if (token.TokenType == TokenType.Name)
                return new VariableExpr ession((string) token.Value);
            throw new InvalidDataException(string.Format("Unexpected token '{0}'",
                 token.Value));
        }

El parser usa al lexer que comenté en el anterior post de la serie. Como antes, el nuevo Parser y el método ParseExpr ession fueron escritos usando TDD. Algunos tests:

        [TestMethod]
        public void ParseIntegerExpr ession()
        {
            Parser parser = new Parser("1");
            IExpr ession Expr ession = parser.ParseExpr ession();
            Assert.IsNotNull(Expr ession);
            Assert.IsInstanceOfType(Expr ession, typeof(ConstantExpr ession));
            Assert.AreEqual(1, Expr ession.Evaluate(null));
            Assert.IsNull(parser.ParseExpr ession());
        }
        [TestMethod]
        public void ParseVariableExpr ession()
        {
            Parser parser = new Parser("one");
            IExpr ession Expr ession = parser.ParseExpr ession();
            Assert.IsNotNull(Expr ession);
            Assert.IsInstanceOfType(Expr ession, typeof(VariableExpr ession));
            VariableExpr ession varexpr = (VariableExpr ession)Expr ession;
            Assert.AreEqual("one", varexpr.Name);
            Assert.IsNull(parser.ParseExpr ession());
        }

Todos los tes están en verde:

 

Buen code coverage:

Noten que usando TDD puedo agregar características nuevas en “baby steps” (pasos de bebé), evitando tiempos de depuración o agregar grandes fragmentos de código de una vez. Y siempre tengo al retroalimentación “verde”: cada cosa nueva que se agrega se prueba compatible con el anterior código.

Próximos pasos: agregar más expresiones (aritmética, operadores, ..) y comandos (como if, for, …), “entrenando” al parser en reconocerlas,. Luego puedo agregar al lexer el proceso de strings delimitados por dobles comillas.

Nos leemos!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

This entry was posted in 11699, 1389, 8870. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>