I keep thinking I understand Sprache parsing the more I use it, but then I come across a new syntax that baffles me, and there are not a lot of examples online. At this time, I'm trying to allow my string to have conditional syntax (like C#) such as:
(A > B ? A : B)
A+2 > 7 ? (A + 2) : -1
(A*B) < 12 ? "Real" : "Fake"
I have the regular operators working fine (>,<,!,=,etc.) using the following parse:
private Parser<ExpressionType> Operator(string op, ExpressionType opType)
=> Parse.String(op).Token().Return(opType);
But of course the regular operators all use a single string (eg: "<") as the operator string, whereas the conditional operator requires something more complex like:
{Expression} ? {Expression} : {Expression}
So I've tried cobbling together a Parser ExpressionType like this, but of course I can't get the syntax quite right:
Parser<ExpressionType> Conditional = Parse.Ref(() => Expr)
.Parse.String("?")
.Parse.Ref(() => Expr)
.Parse.String(":")
.Parse.Ref(() => Expr)
.Token().Return(ExpressionType.Conditional);
And then once I figure it out, do I pass this Conditional into the Parse.ChainOperator method along with the other operators? None of the other operators references Expressions on either side of their definition, so I think probably not.
I also tried creating a separate Parser Expression like this (but I don't this will work in a way that would allow the Conditional syntax to be used anywhere in the string (not just as the top-level-once-only expression):
Parser<Expression> Conditional = from test in Expr
from q in Parse.String("?")
from ifTrue in Expr
from c in Parse.String(":")
from ifFalse in Expr
select (Expression)Expression.Condition(test, ifTrue, ifFalse, typeof(RawResult));
[One additional problem with this solution is that it claims that "test" is not boolean]
This all points to the Conditional operator being special in so many ways. Suggestions welcome. Thanks for any input you can provide.
Update#1 Here's the code for my Expr. I wasn't sure how deep to go down the rabbit hole, in this post...
Parser<Expression> Expr = Parse.ChainOperator(LessThanEq.Or(GreaterThanEq)
.Or(EqualTo2).Or(EqualTo1)
.Or(NotEqualTo1).Or(NotEqualTo2)
.Or(LessThan).Or(GreaterThan)
.Or(And1).Or(And2).Or(Or1).Or(Or2)
.Or(Plus).Or(Minus)
.Or(Multiply).Or(Divide),
Operand, Expression.MakeBinary);