Как разобрать условный троичный синтаксис (a> b? A: b) с помощью Sprache - PullRequest
2 голосов
/ 11 июля 2019

Я продолжаю думать, что понимаю синтаксический анализ Sprache, чем больше я его использую, но потом я сталкиваюсь с новым синтаксисом, который сбивает меня с толку, и примеров в Интернете не так много.В настоящее время я пытаюсь разрешить моей строке иметь условный синтаксис (например, C #), такой как:

(A > B ? A : B)
A+2 > 7 ? (A + 2) : -1
(A*B) < 12 ? "Real" : "Fake"

У меня нормально работают обычные операторы (>, <,!, = И т. Д.).) используя следующий синтаксический анализ: </p>

private Parser<ExpressionType> Operator(string op, ExpressionType opType)
        => Parse.String(op).Token().Return(opType);

Но, конечно, все обычные операторы используют одну строку (например: "<") в качестве строки оператора, тогда как условный оператор требует чего-то более сложного, например: </p>

{Expression} ? {Expression} : {Expression}

Итак, я попытался объединить Parser ExpressionType вот так, но, конечно, я не могу получить правильный синтаксис:

Parser<ExpressionType> Conditional = Parse.Ref(() => Expr)
                  .Parse.String("?")
                  .Parse.Ref(() => Expr)
                  .Parse.String(":")
                  .Parse.Ref(() => Expr)
                  .Token().Return(ExpressionType.Conditional);

А потомКак только я это выясню, передам ли я это Условие в метод Parse.ChainOperator вместе с другими операторами?Ни один из других операторов не ссылается на выражения по обе стороны от их определения, поэтому я думаю, что нет.

Я также пытался создать отдельное выражение синтаксического анализатора , как это (но я не думаю, что это будет работать таким образом, чтобы можно было использовать условный синтаксис в любом месте строки (не тольков качестве выражения верхнего уровня, предназначенного только для одного раза):

    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));

[Еще одна проблема, связанная с этим решением, заключается в том, что в нем утверждается, что «test» не является логическим значением]

Это все указывает на то, что оператор Условие является специальным во многих отношениях. Предложения приветствуются. Спасибо за любой вклад, который вы можете предоставить.

Обновление # 1 Вот код для моего Expr. Я не был уверен, как глубоко зайти в кроличью нору, в этом посте ...

    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);
...