Пример #1
0
        } // TJC: force parenthesis on intersections for readability

        public override bool Equals(Object obj)
        {
            if (obj == null)
            {
                return(false);
            }
            if (obj.GetType() != this.GetType())
            {
                return(false);
            }
            CompositeExpr ce = (CompositeExpr)obj;

            if (!_head.Equals(ce._head))
            {
                return(false);
            }
            if (_args.Length != ce._args.Length)
            {
                return(false);
            }
            for (int i = 0; i < _args.Length; i++)
            {
                if (!_args[i].Equals(ce._args[i]))
                {
                    return(false);
                }
            }
            return(true);
        }
Пример #2
0
        private bool StartsWithNumber(Expr ee)
        {
            if (ee.Annotations.ContainsKey("Force Parentheses"))
            {
                return(false);
            }
            if (ee is Number)
            {
                return(true);
            }
            CompositeExpr ce = ee as CompositeExpr;

            if (ce == null)
            {
                return(false);
            }
            WellKnownSym wks = ce.Head as WellKnownSym;

            if (wks == null)
            {
                return(false);
            }
            if (wks == WellKnownSym.power || wks == WellKnownSym.subscript ||
                Syntax.Fixes.Find(wks).Precedence >= Syntax.Fixes.Find(WellKnownSym.times).Precedence)
            {
                return(StartsWithNumber(ce.Args[0]));
            }
            else
            {
                return(false);
            }
        }
Пример #3
0
        /// <param name="prectoparen">parenthesize stuff w prec ≤ prectoparen</param>
        private bool Needs_paren(Expr e, int prectoparen)
        {
            CompositeExpr ce = e as CompositeExpr;
            int           prec;

            if (ce != null)
            {
                prec = Syntax.Fixes.Find(ce.Head).Precedence;
                if (prec == -1)
                {
                    prec = int.MaxValue;            // function calls, power, subscript, and root have highest precedence
                }
            }
            else
            {
                prec = (e is ComplexNumber) ? Syntax.Fixes.Find(WellKnownSym.plus).Precedence
                : (e is IntegerNumber) && ((IntegerNumber)e).Num < 0 ? Syntax.Fixes.Find(WellKnownSym.minus).Precedence
                : (e is DoubleNumber) && ((DoubleNumber)e).Num < 0 ? Syntax.Fixes.Find(WellKnownSym.minus).Precedence
                : (e is DoubleNumber) && ((DoubleNumber)e).Num.ToString("R").IndexOfAny(new char[] { 'e', 'E' }) >= 0 ? Syntax.Fixes.Find(WellKnownSym.plus).Precedence
                : int.MaxValue; // assuming everything else is an atom of one sort or another. Possibly wrong, for user-defined Exprs
            }
            if (prec <= prectoparen)
            {
                return(true);
            }
            if (ce != null)
            {
                Syntax.OpRelPos orp = Syntax.Fixes.Find(ce.Head);
                if (orp.Precedence != -1 && ce.Args.Length > 0)
                {
                    Syntax.K k = Syntax.Fixes.Table[orp.Precedence].Kind;
                    if (k == Syntax.K.Prefix || k == Syntax.K.PrefixOpt)
                    {
                        return(false);
                    }
                    if (k == Syntax.K.BinPrimaryAndSecondary2)
                    {
                        // might be an operator at the start
                        if (ce.Args[0].Annotations["initial op"] != null)
                        {
                            return(false);
                        }
                        CompositeExpr ce2 = ce.Args[0] as CompositeExpr;
                        if (ce2 != null && Syntax.Fixes.Find(ce2.Head).Precedence == orp.Precedence)
                        {
                            return(false);
                        }
                    }
                    return(Needs_paren(ce.Args[0], prectoparen));
                }
            }
            return(false);
        }
Пример #4
0
        /// <summary>
        /// Parenthesize for something like a function's single argument
        /// </summary>
        private T Translate_maybe_parenfn(Expr e, bool emph)
        {
            CompositeExpr ce = e as CompositeExpr;

            if (ce != null && ce.Head != WellKnownSym.root && ce.Head != WellKnownSym.subscript)
            {
                return(Translate_definite_paren(e, emph));
            }
            else
            {
                if (e.Annotations.ContainsKey("Force Parentheses"))
                {
                    _emph1paren = emph;
                }
                return(Translate(e));
            }
        }
Пример #5
0
        private T _Translate(CompositeExpr e)
        {
            List <T> lt; // for local use because, sigh, c# doesn't handle this case of definitions used or duplicated across switch cases well
            T        t;  // this too, sigh

            Syntax.OpRelPos orp = Syntax.Fixes.Find(e.Head);
            if (orp.Precedence != -1)
            {
                Syntax.OpRel or = Syntax.Fixes.Table[orp.Precedence];
                Syntax.WOrC  op = or.Ops[orp.Position];
                Syntax.TType tt = or.Types[orp.Position];
                switch (or.Kind)
                {
                case Syntax.K.BinLeft:
                case Syntax.K.BinRight:
                case Syntax.K.BinAlone:
                    Trace.Assert(e.Args.Length == 2);
                    return(__WrapTranslatedExpr(e, Translate_thing(e.Head, e.Args, op, tt, orp.Precedence, or.Kind)));

                case Syntax.K.BinAllOfLike:
                    Trace.Assert(e.Args.Length >= 2);
                    return(__WrapTranslatedExpr(e, Translate_multithing(e, e.Args, op, tt, orp.Precedence)));

                case Syntax.K.BinPrimaryAndSecondary:
                    if (e.Head != or.Heads[0])
                    {
                        Trace.Assert(e.Args.Length == 1);
                        // Division is a special case because it can be represented as the vertical fraction representation, which is not dealt with
                        // in our syntax table.
                        if (e.Head == WellKnownSym.divide && !e.Annotations.ContainsKey("inline"))
                        {
                            return(__TranslateVerticalFraction(e, Translate(IntegerNumber.One), Translate(e.Args[0])));
                        }
                        else
                        {
                            lt = new List <T>();
                            if (or.Kind == Syntax.K.BinPrimaryAndSecondary)
                            {
                                lt.Add(Translate_maybe_paren(or.Identity, orp.Precedence));
                            }
                            lt.Add(__TranslateOperator(e.Head, op, tt));
                            lt.Add(Translate_maybe_paren(e.Args[0], orp.Precedence));
                            return(__WrapTranslatedExpr(e, lt));
                        }
                    }
                    else
                    {
                        // FIXME!!!! currently this only works for times and divide; ignores Syntax! Ideally ought to be merged w BinPriAndSec2
                        Trace.Assert(e.Args.Length > 0);
                        if (e.Args.Length == 1)
                        {
                            return(Translate(e.Args[0]));
                        }
                        else
                        {
                            List <Expr>          num         = new List <Expr>();
                            List <CompositeExpr> denom       = new List <CompositeExpr>();
                            List <CompositeExpr> denominline = new List <CompositeExpr>();
                            foreach (Expr ee in e.Args)
                            {
                                CompositeExpr ce = ee as CompositeExpr;
                                if (ce != null && ce.Head == WellKnownSym.divide)
                                {
                                    Trace.Assert(ce.Args.Length == 1);
                                    if (ce.Annotations.ContainsKey("inline"))
                                    {
                                        denominline.Add(ce);
                                    }
                                    else
                                    {
                                        denom.Add(ce);
                                    }
                                }
                                else
                                {
                                    num.Add(ee);
                                }
                            }
                            lt = new List <T>();
                            if (num.Count > 1 || (denom.Count == 0 && denominline.Count > 0))
                            {
                                AddTimes(lt, num);
                            }
                            else
                            {
                                lt.Add(Translate(num[0]));
                            }
                            if (denom.Count != 0)
                            {
                                if (num.Count == 0)
                                {
                                    lt.Add(Translate(IntegerNumber.One));
                                }
                                T nt = __WrapTranslatedExpr(null, lt);
                                lt = new List <T>();
                                if (denom.Count > 1)
                                {
                                    List <Expr> denomraw = new List <Expr>();
                                    foreach (CompositeExpr ce in denom)
                                    {
                                        denomraw.Add(ce.Args[0]);
                                    }
                                    AddTimes(lt, denomraw);
                                }
                                else
                                {
                                    lt.Add(Translate(denom[0].Args[0]));
                                }
                                T dt = __WrapTranslatedExpr(null, lt);
                                t = __TranslateVerticalFraction(e, denom[0].Head, nt, dt);
                            }
                            else
                            {
                                if (num.Count == 0)
                                {
                                    t = Translate(IntegerNumber.One);
                                }
                                else
                                {
                                    t = __WrapTranslatedExpr(e, lt);
                                }
                            }
                            if (denominline.Count > 0)
                            {
                                lt = new List <T>();
                                lt.Add(t);
                                foreach (CompositeExpr division in denominline)
                                {
                                    lt.Add(__TranslateOperator(division.Head, '/', Syntax.TType.Ord));
                                    lt.Add(Translate(division.Args[0]));
                                }
                                return(__WrapTranslatedExpr(e, lt));
                            }
                            else
                            {
                                return(t);
                            }
                        }
                    }

                case Syntax.K.BinPrimaryAndSecondary2:
                    if (e.Head != or.Heads[0])
                    {
                        Trace.Assert(e.Args.Length == 1);
                        return(__TranslateOperatorApplication(e, __TranslateOperator(e.Head, op, tt), Translate_maybe_paren(e.Args[0], orp.Precedence)));
                    }
                    else
                    {
                        Trace.Assert(e.Args.Length > 0);
                        lt = new List <T>();
                        if (e.Annotations["initial op"] != null)
                        {
                            lt.Add(__TranslateOperator(e, 0, (char)e.Annotations["initial op"], tt));
                        }
                        lt.Add(Translate_maybe_paren(e.Args[0], orp.Precedence - 1));
                        bool checkminus = (Syntax.Fixes.Find(WellKnownSym.minus).Precedence == orp.Precedence);
                        for (int i = 1; i < e.Args.Length; i++)
                        {
                            CompositeExpr   ce   = e.Args[i] as CompositeExpr;
                            Syntax.OpRelPos orp2 = new Syntax.OpRelPos(-1, -1);
                            if (ce != null)
                            {
                                orp2 = Syntax.Fixes.Find(ce.Head);
                            }
                            if (checkminus && NumberStartsWithMinus(e.Args[i]))
                            {
                                lt.Add(Translate(e.Args[i]));
                            }
                            else if (ce != null && orp2.Precedence == orp.Precedence &&
                                     or.Heads[orp.Position] != or.Heads[orp2.Position])
                            {
                                Trace.Assert(ce.Args.Length == 1);
                                lt.Add(__TranslateOperator(e, i, or.Ops[orp2.Position], tt));
                                lt.Add(Translate_maybe_paren(ce.Args[0], orp.Precedence));
                            }
                            else
                            {
                                lt.Add(__TranslateOperator(e, i, op, tt));
                                lt.Add(Translate_maybe_paren(e.Args[i], orp.Precedence - 1));
                            }
                        }
                        return(__WrapTranslatedExpr(e, lt));
                    }

                case Syntax.K.PrefixOpt:
                case Syntax.K.Prefix:
                    if (tt == Syntax.TType.LargeOp && op.Word == null)      // Only summation? This seems oddly hard-coded.
                    {
                        Trace.Assert(0 < e.Args.Length && e.Args.Length < 4);
                        return(__TranslateBigOp(e, e.Head, op.Character, e.Args.Length > 1 ? Translate(e.Args[0]) : null, e.Args.Length > 2 ? Translate(e.Args[1]) : null,
                                                Translate_maybe_paren(e.Args[e.Args.Length - 1], orp.Precedence - 1)));
                    }
                    else if (or.Kind == Syntax.K.PrefixOpt && e.Args.Length == 0)
                    {
                        return(__TranslateOperator(e.Head, op, tt));
                    }
                    else
                    {
                        //Trace.Assert(e.Args.Length == 1);//CJ disabled temporarily for site visit demo
                        return(__WrapTranslatedExpr(e, Translate_prepostfix(e.Head, e.Args[0], op, tt, orp.Precedence, or.Kind)));
                    }

                case Syntax.K.Postfix:
                    Trace.Assert(e.Args.Length == 1);
                    return(__WrapTranslatedExpr(e, Translate_prepostfix(e.Head, e.Args[0], op, tt, orp.Precedence, or.Kind)));
                }
            }
            if (e.Head is WellKnownSym)
            {
                WellKnownSym wks = (WellKnownSym)e.Head;
                WKSID        id  = wks.ID;
                switch (id)
                {
                case WKSID.im:
                    Trace.Assert(e.Args.Length == 1);
                    return(__TranslateFunctionApplication(e, __TranslateOperator(e.Head, Unicode.B.BLACK_LETTER_CAPITAL_I, Syntax.TType.Ord),
                                                          Translate_maybe_parenfn(e.Args[0], _showInvisibles)));

#if false
                case WKSID.magnitude:
                    Trace.Assert(e.Args.Length == 1);
                    return(__TranslateDelims(e, false, 0, '|', Translate(e.Args[0]), 1, '|'));
#endif
                case WKSID.magnitude:
                    if (e.Args.Length == 1)
                    {
                        return(__TranslateDelims(e, false, "|l", '|',
                                                 __WrapTranslatedExpr(null, Translate(e.Args[0])),
                                                 "|r", '|'));
                    }
                    break;

                case WKSID.power:
                    Trace.Assert(e.Args.Length == 2);
                    if (e.Args[0] is CompositeExpr && ((CompositeExpr)e.Args[0]).Head == WellKnownSym.power)
                    {
                        t = Translate_definite_paren(e.Args[0]);
                    }
                    else
                    {
                        t = Translate_maybe_parenfn(e.Args[0]);
                    }
                    return(__AddSuperscript(e, t, Translate(e.Args[1])));

                case WKSID.subscript:
                    Trace.Assert(e.Args.Length == 2);
                    if (e.Args[0] is CompositeExpr && (((CompositeExpr)e.Args[0]).Head == WellKnownSym.power ||
                                                       ((CompositeExpr)e.Args[0]).Head == WellKnownSym.subscript))
                    {
                        t = Translate_definite_paren(e.Args[0]);
                    }
                    else
                    {
                        t = Translate_maybe_parenfn(e.Args[0]);
                    }
                    return(__AddSubscript(e, t, Translate(e.Args[1])));

                case WKSID.re:
                    Trace.Assert(e.Args.Length == 1);
                    return(__TranslateFunctionApplication(e, __TranslateOperator(e.Head, Unicode.B.BLACK_LETTER_CAPITAL_R, Syntax.TType.Ord),
                                                          Translate_maybe_parenfn(e.Args[0], _showInvisibles)));

                case WKSID.root:
                    if (e.Args[0] is IntegerNumber && (e.Args[0] as IntegerNumber).Num == 2)
                    {
                        return(__TranslateRadical(e, Translate(e.Args[1]), null));
                    }
                    else
                    {
                        return(__TranslateRadical(e, Translate(e.Args[1]), Translate(e.Args[0])));
                    }

                case WKSID.differentiald:
                case WKSID.partiald:
                    Trace.Assert(e.Args.Length == 1);
                    if (e.Args[0] is Sym)
                    {
                        return(__TranslateOperatorApplication(e, Translate(e.Head), Translate(e.Args[0])));
                    }
                    else
                    {
                        return(__TranslateOperatorApplication(e, Translate(e.Head), Translate_definite_paren(e.Args[0])));
                    }

                case WKSID.integral:
                    Trace.Assert(e.Args.Length >= 2 && e.Args.Length <= 4);
                    return(__TranslateBigOp(e, e.Head, Unicode.I.INTEGRAL, e.Args.Length > 2 ? Translate(e.Args[2]) : null,
                                            e.Args.Length > 3 ? Translate(e.Args[3]) : null,
                                            __TranslateIntegralInternals(Translate(e.Args[0]), Translate(e.Args[1]))));

                case WKSID.log:
                    if (e.Args.Length == 2)
                    {
                        T f = __TranslateWord(wks, wks.ID.ToString(), Syntax.TType.LargeOp);
                        f = __AddSubscript(null, f, Translate(e.Args[0]));
                        f = ParenAround(e.Head, false, f);
                        return(__TranslateFunctionApplication(e, f, Translate_maybe_parenfn(e.Args[1], _showInvisibles)));
                    }
                    break;

                case WKSID.floor:
                    if (e.Args.Length == 1)
                    {
                        return(__TranslateDelims(e, false, Unicode.L.LEFT_FLOOR.ToString(), Unicode.L.LEFT_FLOOR,
                                                 __WrapTranslatedExpr(null, Translate(e.Args[0])),
                                                 Unicode.R.RIGHT_FLOOR.ToString(), Unicode.R.RIGHT_FLOOR));
                    }
                    break;

                case WKSID.ceiling:
                    if (e.Args.Length == 1)
                    {
                        return(__TranslateDelims(e, false, Unicode.L.LEFT_CEILING.ToString(), Unicode.L.LEFT_CEILING,
                                                 __WrapTranslatedExpr(null, Translate(e.Args[0])),
                                                 Unicode.R.RIGHT_CEILING.ToString(), Unicode.R.RIGHT_CEILING));
                    }
                    break;
                }
            }
            else if (e.Head == new LetterSym('→') || e.Head == new LetterSym(Unicode.R.RIGHTWARDS_DOUBLE_ARROW))
            {
                T arrow = __TranslateOperator(e.Head, ((LetterSym)e.Head).Letter, Syntax.TType.Rel);
                if (e.Args.Length == 1)
                {
                    return(__WrapTranslatedExpr(e, Translate(e.Args[0]), arrow));
                }
                else
                {
                    Trace.Assert(e.Args.Length == 2);
                    return(__WrapTranslatedExpr(e, Translate(e.Args[0]), arrow, Translate(e.Args[1])));
                }
            }
            else if (e.Head == new WordSym("brace"))
            {
                return(__TranslateDelims(e, false, "{", '{', __WrapTranslatedExpr(null, Translate_arglist(e, e.Args)), "}", '}'));
            }
            else if (e.Head == new WordSym("bracket"))
            {
                return(__TranslateDelims(e, false, "[", '[', __WrapTranslatedExpr(null, Translate_arglist(e, e.Args)), "]", ']'));
            }
            // FIXME: probably both branches here should use la and ra...
            if (e.Args.Length == 1)
            {
                if (e.Head is WellKnownSym)
                {
                    return(__TranslateFunctionApplication(e, Translate(e.Head), Translate_maybe_parenfn(e.Args[0], _showInvisibles)));
                }
                else
                {
                    return(__TranslateFunctionApplication(e, Translate_maybe_parenfn(e.Head), Translate_definite_paren(e.Args[0], _showInvisibles)));
                }
            }
            else
            {
                return(__TranslateFunctionApplication(e, Translate_maybe_parenfn(e.Head),
                                                      __TranslateDelims(e, _showInvisibles, "la", '(', __WrapTranslatedExpr(null, Translate_arglist(e, e.Args)), "ra", ')')));
            }
        }
Пример #6
0
 public TwoArgExpr(Expr head)
 {
     _twoArg = (head != null && head is CompositeExpr && (head as CompositeExpr).Args.Length == 2) ? head as CompositeExpr : null;
 }
Пример #7
0
 public OneArgExpr(Expr head)
 {
     _oneArg = (head != null && head is CompositeExpr && (head as CompositeExpr).Args.Length == 1) ? head as CompositeExpr : null;
 }