4

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);
Jarvis
  • 681
  • 8
  • 33
  • 1
    can you post the code for your parser `Expr`? – jtate Jul 19 '19 at 18:08
  • Added (above) as an Update – Jarvis Jul 22 '19 at 12:02
  • 2
    yea, I can see this may be a very deep rabbit hole...it may be beneficial to create a github repo with all your code so that I or someone else could play around with a full example. from what I see here, your approach and code seems fine, but without seeing all your parsers it's hard to tell why it isn't working. – jtate Jul 25 '19 at 13:27
  • I guess the biggest question is how to use a Conditional along with other Operators. If I say that an Expr is a bunch of Chained Operands, then where would a Conditional (which parses three Expressions together) end up? as one of the Operands, or as a _special_ Operator? – Jarvis Jul 25 '19 at 13:31
  • Did you eventually figure it out? – Sergey Kucher Jul 26 '20 at 07:09
  • 1
    I’m afraid not. I am living without that syntax. – Jarvis Jul 26 '20 at 10:03
  • You just have to decide on the precedence of the operators. Is `a < b ? c : d` an expression that evaluates to c if a is less than b and d otherwise, or one that always asks whether a is less than something, and that something is either c or d depending on the value of b? Then you must construct your productions accordingly. You may want to consult https://stackoverflow.com/questions/51713763/recursive-expression-parsing-in-sprache. – Mark Reed Mar 31 '23 at 16:28

0 Answers0