Newbie question CustomTerminal

May 24, 2012 at 11:37 AM
Edited May 24, 2012 at 1:12 PM

Hi everybody, i have just started to play with the Irony project and my first attempt was to extend the functionality of the Irony tutorial at:

This project parses expressions like:

1 + ( 3 *5 )

My extension was supposed to allow the usage of XPath expression in the expression, for example:

1 + ( 3 * 5 ) - xpath(//item[@id='1']/@quantity)

For this i found out that the CustomTerminal would be handy, and in the MatchHandler try to compile the XPath expression as sort of validation and then put the entire xpath expression in the parsetree/AST

I have trouble to get this to work and before i dig to deep i just wonder if this is correct approach, my grammar is defined as:

public SimpleCalcGrammar()
			var xpath = new CustomTerminal("xpath", ParseXPathExpressionHandler);
			var number = TerminalFactory.CreateCSharpNumber("number");
			var identifier = TerminalFactory.CreateCSharpIdentifier("identifier");
			var expression = new NonTerminal("expression");
			var binexpr = new NonTerminal("binexpr");
			var parexpr = new NonTerminal("parexpr");
			var fncall = new NonTerminal("fncall");
			var binop = new NonTerminal("binop");
			var xpathexpr = new NonTerminal("xpathexpr");

			xpathexpr.Rule = "xpath(" + xpath + ")";
			expression.Rule = parexpr | binexpr | number | fncall | xpathexpr;
			parexpr.Rule = "(" + expression + ")";
			binexpr.Rule = expression + binop + expression;
			binop.Rule = ToTerm("+") | "-" | "/" | "*" | "%";
			fncall.Rule = identifier + "(" + expression + ")";
			this.Root = expression;

			RegisterOperators(1, "+", "-");
			RegisterOperators(2, "*", "/", "%");


I would very much appreciate input on how the MatchHandler is supposed to be defined, do i my self have to analyze the input string for the closing paranthesis of the xpath(...) statement, i dont find much documentation on this...

I would very much like to avoid parsing XPath expressions but instead compile it in C# as a sort of basic validation.

Regards Andreas

May 25, 2012 at 8:45 AM

Hi, i finally got it to work, is this the way to go?

It successfully parses strings like #//item[@id='id1']/@price#

Regards Andreas

 var xpath = new StringLiteral("xpath", "#"); xpath.ValidateToken += delegate(object sender, ValidateTokenEventArgs args) 
		Token currentToken = args.Context.CurrentToken; 
		// Get rid of # at beginning and end and try to parse 
		string xpathString = currentToken.Text.Substring(1, currentToken.Length - 2); 
			XPathExpression compiledExpression = XPathExpression.Compile(xpathString); 
			currentToken.Value = compiledExpression; 
		catch (Exception exception) 
			currentToken = args.Context.CreateErrorToken("Not a valid xpath expression: {0} \nDetails: {1}", xpathString, exception.Message); 
May 25, 2012 at 4:50 PM

looks ok, as long as it works for you

May 25, 2012 at 5:34 PM

Thanks for your reply, its a bit tricky to get going with this, however i have got something up and running by now but still have questions, now about evaluation. I have modified the EvaluationGrammar provided in the Samples to fit my needs, but when im about to evaluate my script i need access to the underlying xml, how am i supposed to access that, ie i need to execute my xpath expressions to get some element/attributes from my xml to perform calculations...

Regards Andreas

May 26, 2012 at 3:10 AM
Edited May 26, 2012 at 3:11 AM

put your Xml document into Globals variables under some special key, so it would be readily available in your custom Ast node - that you need to write and associate with your terminal

(put XML doc into ... I mean, assume it is there in you node's code, and when you call the script to evaluate, make sure you put into Globals)