<commit_before>using System;
using Pidgin.Expression;
using Xunit;
using static Pidgin.Parser;
using static Pidgin.Parser<char>;

namespace Pidgin.Tests
{
    public class ExpressionParserTests : ParserTestBase
    {
        private abstract class Expr : IEquatable<Expr>
        {
            public override bool Equals(object other)
                => other is Expr && this.Equals((Expr)other);
            public abstract bool Equals(Expr other);

            public override int GetHashCode() => 0;  // doesn't matter
        }
        private class Lit : Expr
        {
            public int Value { get; }
            public Lit(int value)
            {
                Value = value;
            }
            public override bool Equals(Expr other)
                => other is Lit
                && ((Lit)other).Value == this.Value;
        }
        private class Plus : Expr
        {
            public Expr Left { get; }
            public Expr Right { get; }
            public Plus(Expr left, Expr right)
            {
                Left = left;
                Right = right;
            }
            public override bool Equals(Expr other)
                => other is Plus
                && ((Plus)other).Left.Equals(this.Left)
                && ((Plus)other).Right.Equals(this.Right);
        }
        private class Minus : Expr
        {
            public Expr Left { get; }
            public Expr Right { get; }
            public Minus(Expr left, Expr right)
            {
                Left = left;
                Right = right;
            }
            public override bool Equals(Expr other)
                => other is Minus
                && ((Minus)other).Left.Equals(this.Left)
                && ((Minus)other).Right.Equals(this.Right);
        }
        private class Times : Expr
        {
            public Expr Left { get; }
            public Expr Right { get; }
            public Times(Expr left, Expr right)
            {
                Left = left;
                Right = right;
            }
            public override bool Equals(Expr other)
                => other is Times
                && ((Times)other).Left.Equals(this.Left)
                && ((Times)other).Right.Equals(this.Right);
        }

        [Fact]
        public void TestInfixL()
        {
            Parser<char, Expr> parser = null;
            var termParser = Digit.Select<Expr>(x => new Lit((int)char.GetNumericValue(x)));
            parser = ExpressionParser.Build(
                termParser,
                new[]
                {
                    Operator.InfixL(
                        Char('*').Then(Return<Func<Expr, Expr, Expr>>((x, y) => new Times(x, y)))
                    ),

                    Operator.InfixL(
                        Char('+').Then(Return<Func<Expr, Expr, Expr>>((x, y) => new Plus(x, y)))
                    ).And(Operator.InfixL(
                        Char('-').Then(Return<Func<Expr, Expr, Expr>>((x, y) => new Minus(x, y)))
                    ))
                }
            );

            AssertSuccess(
                parser.Parse("1+2+3+4"),
                new Plus(new Plus(new Plus(new Lit(1), new Lit(2)), new Lit(3)), new Lit(4)),
                true
            );
            AssertSuccess(
                parser.Parse("1+2-3+4"),
                new Plus(new Minus(new Plus(new Lit(1), new Lit(2)), new Lit(3)), new Lit(4)),
                true
            );
            AssertSuccess(
                parser.Parse("1*2*3+4*5"),
                new Plus(new Times(new Times(new Lit(1), new Lit(2)), new Lit(3)), new Times(new Lit(4), new Lit(5))),
                true
            );
        }

        [Fact]
        public void TestInfixR()
        {
            Parser<char, Expr> parser = null;
            var termParser = Digit.Select<Expr>(x => new Lit((int)char.GetNumericValue(x)));
            parser = ExpressionParser.Build(
                termParser,
                new[]
                {
                    new[]
                    {
                        Operator.InfixR(
                            Char('*').Then(Return<Func<Expr, Expr, Expr>>((x, y) => new Times(x, y)))
                        )
                    },
                    new[]
                    {
                        Operator.InfixR(
                            Char('+').Then(Return<Func<Expr, Expr, Expr>>((x, y) => new Plus(x, y)))
                        ),
                        Operator.InfixR(
                            Char('-').Then(Return<Func<Expr, Expr, Expr>>((x, y) => new Minus(x, y)))
                        )
                    }
                }
            );

            AssertSuccess(
                parser.Parse("1+2+3+4"),
                new Plus(new Lit(1), new Plus(new Lit(2), new Plus(new Lit(3), new Lit(4)))),
                true
            );
            // yeah it's not mathematically accurate but who cares, it's a test
            AssertSuccess(
                parser.Parse("1+2-3+4"),
                new Plus(new Lit(1), new Minus(new Lit(2), new Plus(new Lit(3), new Lit(4)))),
                true
            );
            AssertSuccess(
                parser.Parse("1*2*3+4*5"),
                new Plus(new Times(new Lit(1), new Times(new Lit(2), new Lit(3))), new Times(new Lit(4), new Lit(5))),
                true
            );
        }

        [Fact]
        public void TestPrefix()
        {
            Parser<char, bool> parser = null;
            var termParser =
                String("false").Select(_ => false)
                    .Or(String("true").Select(_ => true))
                    .Or(Rec(() => parser).Between(Char('('), Char(')')));
            parser = ExpressionParser.Build(
                termParser,
                new[]
                {
                    new[]
                    {
                        Operator.Prefix(
                            Char('!').Select<Func<bool, bool>>(_ => b => !b)
                        )
                    }
                }
            );

            AssertSuccess(parser.Parse("true"), true, true);
            AssertSuccess(parser.Parse("!true"), false, true);
            AssertSuccess(parser.Parse("!(!true)"), true, true);
        }

        [Fact]
        public void TestPostfix()
        {
            Func<dynamic> f = () => true;

            Parser<char, dynamic> parser = null;
            var termParser = String("f").Select<dynamic>(_ => f);
            parser = ExpressionParser.Build(
                termParser,
                new[]
                {
                    new[]
                    {
                        Operator.Postfix(String("()").Select<Func<dynamic, dynamic>>(_ => g => g()))
                    }
                }
            );

            AssertSuccess(parser.Parse("f"), f, true);
            AssertSuccess(parser.Parse("f()"), f(), true);
        }
    }
}<commit_msg>Changed tests to talk to new implementation<commit_after>using System;
using Pidgin.Expression;
using Xunit;
using static Pidgin.Parser;
using static Pidgin.Parser<char>;

namespace Pidgin.Tests
{
    public class ExpressionParserTests : ParserTestBase
    {
        private abstract class Expr : IEquatable<Expr>
        {
            public override bool Equals(object other)
                => other is Expr && this.Equals((Expr)other);
            public abstract bool Equals(Expr other);

            public override int GetHashCode() => 0;  // doesn't matter
        }
        private class Lit : Expr
        {
            public int Value { get; }
            public Lit(int value)
            {
                Value = value;
            }
            public override bool Equals(Expr other)
                => other is Lit
                && ((Lit)other).Value == this.Value;
        }
        private class Plus : Expr
        {
            public Expr Left { get; }
            public Expr Right { get; }
            public Plus(Expr left, Expr right)
            {
                Left = left;
                Right = right;
            }
            public override bool Equals(Expr other)
                => other is Plus
                && ((Plus)other).Left.Equals(this.Left)
                && ((Plus)other).Right.Equals(this.Right);
        }
        private class Minus : Expr
        {
            public Expr Left { get; }
            public Expr Right { get; }
            public Minus(Expr left, Expr right)
            {
                Left = left;
                Right = right;
            }
            public override bool Equals(Expr other)
                => other is Minus
                && ((Minus)other).Left.Equals(this.Left)
                && ((Minus)other).Right.Equals(this.Right);
        }
        private class Times : Expr
        {
            public Expr Left { get; }
            public Expr Right { get; }
            public Times(Expr left, Expr right)
            {
                Left = left;
                Right = right;
            }
            public override bool Equals(Expr other)
                => other is Times
                && ((Times)other).Left.Equals(this.Left)
                && ((Times)other).Right.Equals(this.Right);
        }

        [Fact]
        public void TestInfixL()
        {
            Parser<char, Expr> parser = null;
            var termParser = Digit.Select<Expr>(x => new Lit((int)char.GetNumericValue(x)));
            parser = ExpressionParser.Build2(
                termParser,
                new[]
                {
                    Operator.InfixL(
                        Char('*').Then(Return<Func<Expr, Expr, Expr>>((x, y) => new Times(x, y)))
                    ),

                    Operator.InfixL(
                        Char('+').Then(Return<Func<Expr, Expr, Expr>>((x, y) => new Plus(x, y)))
                    ).And(Operator.InfixL(
                        Char('-').Then(Return<Func<Expr, Expr, Expr>>((x, y) => new Minus(x, y)))
                    ))
                }
            );

            AssertSuccess(
                parser.Parse("1+2+3+4"),
                new Plus(new Plus(new Plus(new Lit(1), new Lit(2)), new Lit(3)), new Lit(4)),
                true
            );
            AssertSuccess(
                parser.Parse("1+2-3+4"),
                new Plus(new Minus(new Plus(new Lit(1), new Lit(2)), new Lit(3)), new Lit(4)),
                true
            );
            AssertSuccess(
                parser.Parse("1*2*3+4*5"),
                new Plus(new Times(new Times(new Lit(1), new Lit(2)), new Lit(3)), new Times(new Lit(4), new Lit(5))),
                true
            );
        }

        [Fact]
        public void TestInfixR()
        {
            Parser<char, Expr> parser = null;
            var termParser = Digit.Select<Expr>(x => new Lit((int)char.GetNumericValue(x)));
            parser = ExpressionParser.Build2(
                termParser,
                new[]
                {
                    new[]
                    {
                        Operator.InfixR(
                            Char('*').Then(Return<Func<Expr, Expr, Expr>>((x, y) => new Times(x, y)))
                        )
                    },
                    new[]
                    {
                        Operator.InfixR(
                            Char('+').Then(Return<Func<Expr, Expr, Expr>>((x, y) => new Plus(x, y)))
                        ),
                        Operator.InfixR(
                            Char('-').Then(Return<Func<Expr, Expr, Expr>>((x, y) => new Minus(x, y)))
                        )
                    }
                }
            );

            AssertSuccess(
                parser.Parse("1+2+3+4"),
                new Plus(new Lit(1), new Plus(new Lit(2), new Plus(new Lit(3), new Lit(4)))),
                true
            );
            // yeah it's not mathematically accurate but who cares, it's a test
            AssertSuccess(
                parser.Parse("1+2-3+4"),
                new Plus(new Lit(1), new Minus(new Lit(2), new Plus(new Lit(3), new Lit(4)))),
                true
            );
            AssertSuccess(
                parser.Parse("1*2*3+4*5"),
                new Plus(new Times(new Lit(1), new Times(new Lit(2), new Lit(3))), new Times(new Lit(4), new Lit(5))),
                true
            );
        }

        [Fact]
        public void TestPrefix()
        {
            Parser<char, bool> parser = null;
            var termParser =
                String("false").Select(_ => false)
                    .Or(String("true").Select(_ => true))
                    .Or(Rec(() => parser).Between(Char('('), Char(')')));
            parser = ExpressionParser.Build2(
                termParser,
                new[]
                {
                    new[]
                    {
                        Operator.Prefix(
                            Char('!').Select<Func<bool, bool>>(_ => b => !b)
                        )
                    }
                }
            );

            AssertSuccess(parser.Parse("true"), true, true);
            AssertSuccess(parser.Parse("!true"), false, true);
            AssertSuccess(parser.Parse("!(!true)"), true, true);
        }

        [Fact]
        public void TestPostfix()
        {
            Func<dynamic> f = () => true;

            Parser<char, dynamic> parser = null;
            var termParser = String("f").Select<dynamic>(_ => f);
            parser = ExpressionParser.Build2(
                termParser,
                new[]
                {
                    new[]
                    {
                        Operator.Postfix(String("()").Select<Func<dynamic, dynamic>>(_ => g => g()))
                    }
                }
            );

            AssertSuccess(parser.Parse("f"), f, true);
            AssertSuccess(parser.Parse("f()"), f(), true);
        }
    }
}
{'fraction_non_alphanumeric': 0.12560940636650417, 'fraction_numerical': 0.007886435331230283, 'mean_word_length': 1.1299435028248588, 'pattern_counts': {'":': 0, '<': 55, '<?xml version=': 0, '>': 101, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '958247', 'n_tokens_mistral': 3779, 'n_tokens_neox': 3543, 'n_words': 828}