Below is a code snippet from the grammar in your sample application that shows how to define an expression. It is a pattern we've followed for other types of expression in our language.
expression.Production = equalityExpression["exp"] > AstFrom("exp");
// Outputs the resulting node from the AdditiveExpression; or if an equality operator is found,
// outputs a '==' or '!=' node whose children are the left and right child expressions of the operator
equalityExpression.Production = additiveExpression["leftexp"] + (
(
@equality > Ast(OperatorKind.Equality.ToString())
| @inequality > Ast(OperatorKind.Inequality.ToString())
).SetLabel("op") + equalityExpression["rightexp"].OnErrorContinue()).Optional()
> AstLeftAssociativity<Expression, BinaryOperatorExpression>(
AstConditional<BinaryOperatorExpression>(AstFrom("leftexp"), AstFrom("rightexp"))
.SetProperty(e => e.Operator, AstFrom("op"))
.SetProperty(e => e.LeftExpression, AstFrom("leftexp"))
.SetProperty(e => e.RightExpression, AstFrom("rightexp")),
n => n.LeftExpression,
n => n.RightExpression,
(n1, n2) => BinaryOperatorKindCheck(n1, n2, OperatorKind.Equality, OperatorKind.Inequality));
// Outputs the resulting node from the MultiplicativeExpression; or if an additive operator is found,
// outputs a '+' or '-' node whose children are the left and right child expressions of the operator
additiveExpression.Production = multiplicativeExpression["leftexp"] + (
(
@addition > Ast(OperatorKind.Addition.ToString())
| @subtraction > Ast(OperatorKind.Subtraction.ToString())
).SetLabel("op") + additiveExpression["rightexp"].OnErrorContinue()).Optional()
> AstLeftAssociativity<Expression, BinaryOperatorExpression>(
AstConditional<BinaryOperatorExpression>(AstFrom("leftexp"), AstFrom("rightexp"))
.SetProperty(e => e.Operator, AstFrom("op"))
.SetProperty(e => e.LeftExpression, AstFrom("leftexp"))
.SetProperty(e => e.RightExpression, AstFrom("rightexp")),
n => n.LeftExpression,
n => n.RightExpression,
(n1, n2) => BinaryOperatorKindCheck(n1, n2, OperatorKind.Addition, OperatorKind.Subtraction));
// Outputs the resulting node from the PrimaryExpression; or if an multiplicative operator is found,
// outputs a '*' or '/' node whose children are the left and right child expressions of the operator
multiplicativeExpression.Production = primaryExpression["leftexp"] + (
(
@multiplication > Ast(OperatorKind.Multiplication.ToString())
| @division > Ast(OperatorKind.Division.ToString())
).SetLabel("op") + multiplicativeExpression["rightexp"].OnErrorContinue()).Optional()
> AstLeftAssociativity<Expression, BinaryOperatorExpression>(
AstConditional<BinaryOperatorExpression>(AstFrom("leftexp"), AstFrom("rightexp"))
.SetProperty(e => e.Operator, AstFrom("op"))
.SetProperty(e => e.LeftExpression, AstFrom("leftexp"))
.SetProperty(e => e.RightExpression, AstFrom("rightexp")),
n => n.LeftExpression,
n => n.RightExpression,
(n1, n2) => BinaryOperatorKindCheck(n1, n2, OperatorKind.Multiplication, OperatorKind.Division));
primaryExpression.Production = numberExpression["exp"] > AstFrom("exp")
| functionAccessExpression["exp"] > AstFrom("exp")
| simpleName["exp"] > AstFrom("exp")
| parenthesizedExpression["exp"] > AstFrom("exp");
parenthesizedExpression.Production = @openParenthesis + expression["exp"] + @closeParenthesis.OnErrorContinue()
> Ast<ParenthesizedExpression>().SetProperty(e => e.ChildExpression, AstFrom("exp"));
In one of our expressions we have the equivalent of something like this for our primaryExpression production:
primaryExpression.Production = (numberExpression["exp"] > AstFrom("exp")
| functionAccessExpression["exp"] > AstFrom("exp")
| simpleName["exp"] > AstFrom("exp")
| parenthesizedExpression["exp"] > AstFrom("exp")).SetLabel("exp") + @num;
The problem is the @num can't exist outside a parenthesizedExpression, but the numberExpression, functionAccessExpression, and simpleName can all be parenthesized.
So this works:
var a = 1 num
But this expression doesn't, and requires an additional @num:
var d = (1 num)
Do you have any suggestions?