Configurable error messages for different math expressions

SyntaxEditor for WPF Forum

Posted 2 years ago by Josh
Version: 18.1.0
Platform: .NET 4.7
Environment: Windows 10 (64-bit)
Avatar

Hello,

Using your sample app with the math expressions, there is an error alias for the primary expression.  This works great!  However, in certain situations the error message we want to display to the user is not the default "Expression expected."

For example:

int a= //  expression expected here is good
int a = 5 + // expression expected here is good
int a = contents(   // here, the user can use a location identifier or a loc() function. 

We have opted to set our grammer to the following for the contents function:

contentsFunction.Production = @contents + @openParenthesis + mathExpression["locationExp"]  + @closeParenthesis.OnErrorContinue()
   > Ast<ContentsNode>()
	.SetProperty(x => x.Location, AstFrom("locationExp"));

We have many other functions that have the same thing.  We have chosen to use the default math expression, so if the user does type in something like:

int a = contents(loc1+5*2)

They will get only 1 error over the loc1+5*2, instead of many errors.

We have many functions where we have chosen to use an expression here, but would like to report a different error to the user.  We currently have a hack in place that is not clean, but we have a error callback on the mathPrimaryExpression, and got some hand-jammed code to report a different error instead of the default "Expression expected".  

Is there a better way to report more specific errors on the mathExpression at a higher level when the mathPrimaryExpression has an error alias?

Any help would be greatly appreciated!  Thanks!

Comments (8)

Posted 2 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Josh,

Just to make sure we understand correctly, you have a mathExpression whose production directly or indirectly calls into mathPrimaryExpression.  Both of those non-terminals have a distinct ErrorAlias set and when the parse error occurs in the mathPrimaryExpression, the ErrorAlias for it is the one that shows up in the resulting parse error.  But you would rather have the outermost mathExpression's ErrorAlias show instead?

It might help if you can list out a detailed example too so we can make sure we're on the same page.  Thanks!


Actipro Software Support

Posted 2 years ago by Josh
Avatar

Yes, your correct in your assumption.  

I would like to do something like this:

contentsFunction.Production = @contents + @openParenthesis + mathExpression["locationExp"].OnError(OnCustomError)  + @closeParenthesis.OnErrorContinue()
   > Ast<ContentsNode>()
	.SetProperty(x => x.Location, AstFrom("locationExp"));

Where inside the custom OnError (or some other neat way)... have this math expressions report a different error than the nested mathPrimaryExpression.

Posted 2 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Josh,

What if you had a mathPrimaryExpressionCore that did not have an ErrorAlias but did have the Production of what is currently in mathPrimaryExpression.  Then mathPrimaryExpression would keep its ErrorAlias and basically call directly into mathPrimaryExpressionCore.  mathExpression would have the other ErrorAlias and call into mathPrimaryExpressionCore. 

Or are there many levels of non-terminals in between the two?  If that is the case then not having an ErrorAlias on mathPrimaryExpression is probably best.  And just put it on other root expression-oriented non-terminals that get called from statement productions.


Actipro Software Support

Posted 2 years ago by Josh
Avatar

I'm a bit confused.  Let me clarify a bit more.

Using the samples provided in the GettingStarted4d. The return statement production is the following:

returnStatement.Production = @return + expression["exp"].OnErrorContinue() + @semiColon.OnErrorContinue()
				> Ast<ReturnStatement>().SetProperty(s => s.Expression, AstFrom("exp"));

If I type:

return 5 + // it says Expression expected.

This is exactly what I want.  However, if I type:

return // this returns Expression expected.

What I'm wanting is a way to configure the message so when nothing is supplied, I can provide a different error message.

So things like this can happen:

return // I want the user to see something different like "Return value expected."
return 5 + // I want the user to see "Expression expected."

So this way, I can get really creative with helping the user out with things like this:

int a = contents(    // i want the user to see "Location name expected."
int a = contents(5 + // i want the user to see "Expression expected." since its now in a math expression
Posted 2 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

It should be using the error alias of the non-terminal being called if a match fails. 

Continung with the return example, the "return " will also indicate "Expression" expected because it's calling the "expression" non-terminal in the "returnStatement" production.  If you make a new non-terminal called "returnValueExpression" with ErrorAlias "Return value" and call that instead of "expression" in the "returnStatement" production, it should give you the result you wanted.  The "returnValueExpression" production would simply call into "expression".


Actipro Software Support

Posted 2 years ago by Josh
Avatar

your suggesting the following?

expression.Production = equalityExpression["exp"] > AstFrom("exp");

var returnExpression= new NonTerminal("ReturnExpression");
returnExpression.Production = expression["exp"] > AstFrom("exp")  { ErrorAlias = "Return Value" };

returnStatement.Production = @return + returnExpression["exp"].OnErrorContinue() + @semiColon.OnErrorContinue()
   > Ast<ReturnStatement>().SetProperty(s => s.Expression, AstFrom("exp"));

I believe I have tried this and it doesn't work.  It uses the following here:

// NOTE: ErrorAlias added so that expressions will report as expected when they error
var primaryExpression = new NonTerminal("PrimaryExpression") { ErrorAlias = "Expression" };

Can you confirm?

Posted 2 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

My apologies... I've been trying this here and it is reporting the error alias of the lowest level place the has an ErrorAlias set, not the highest.  What I suggested trying in the previous reply won't work.  That makes sense since it's reporting the error at the closest place the error occurs that it has an ErrorAlias for. 

What you were originally doing with having a custom error callback on primaryExpression might be what you have to stick with.  Note there is a state.CustomData property you can put any custom data in.  You could put some data in there to say the state.TokenReader.LookAheadToken's start offset at which a return expression starts is, and when the custom error callback for primaryExpression fires, see if the current LookAheadToken's start offset is the same.  If so, you know the expression is for a return statement.  There are many approaches like that you could take.


Actipro Software Support

Posted 2 years ago by Josh
Avatar

Yeah I was hoping for something easier or more baked in.  Right now, I have a OnMathPrimaryExpressionError and tracking statements and functions with the state.CustomData.  

The latest build of this product (v24.1.1) was released 2 months ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.