HQL Parser: Progress

time to read 2 min | 379 words

I still have recursive headache, but I think that I managed to grok how this works. To the point where I can now follow errors in the grammar and actually fix them. I was very surprised (pleasantly so) that the output from ANTLR is actually debuggable and make sense.

At any rate, I now got this test to pass, which is very encouraging:

[Test]
public void ComplexWhere_AlternativeCase()
{
	Query q = Parse("from Customer c where 1 = (case c.Name  when 'ayende' then 1 else 0 end)");
	BinaryExpression expression = (BinaryExpression) q.WhereClause.Expression;
	Assert.AreEqual(BinaryOperatorType.Eq, expression.Operator);
	Assert.AreEqual("1", ((ConstantExpression) expression.Left).Value);
	CaseExpression caseExpr = (CaseExpression) expression.Right;
	Assert.AreEqual("c.Name", caseExpr.ConditionalExpression.ToString());
	AlternativeWhenExpression whenClause = (AlternativeWhenExpression) caseExpr.Conditions[0];
	Assert.AreEqual("'ayende'",((ConstantExpression) whenClause.Value).Value);
	Assert.AreEqual("1",((ConstantExpression)whenClause.Then).Value);
	Assert.AreEqual("0", ((ConstantExpression) caseExpr.ElseClause).Value);
}

About the whole point of this exercise, beyond sharpening my parsing skills, is to allow an AST based HQL query translator. Right now the HQL query translator for NHibernate is an... item of historical interest. Very hard to modify and change, so that is a high priority item for making NHibernate gives us better error messages and easier extensibility. The end goal of having a unified AST for all the query capabilities, HQL, Criteria and Linq, but that is a long way yet.

My main goal is to have reasonable error messages, because while it is gratifying to know that "in expected" means that you misspelled a class name, it is usually preferred to have a more accurate error message.

As before, you can get the Hql Parser source here: svn co https://rhino-tools.svn.sourceforge.net/svnroot/rhino-tools/experiments/Hql

Note: I am keeping it there until it is matured enough to move it to the NHibernate's trunk.

Next, I need to figure out how to get parser error messages from ANTLR, right now I can't seem to manage to get reasonable errors for things like:

from Customer where

It simply reports a no viable alternative, which is a very vague error message. To be exact, it reports: "line 0:-1 no viable alternative at input '<EOF>'" which is no help at all. It is not even the correct location from the point of view of the user (from the parser point of view, it backtracked to try to find a better solution, failed, and then reported from the backtracked location, I presume).

There has to be a better way to do it.