/// <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); }
/// <summary>Handles Syntax.K.{BinLeft,BinRight,BinAlone}</summary> /// <param name="prec">precedence of operator</param> /// <param name="assoc">BinLeft, BinRight, or BinAlone</param> private List <T> Translate_thing(Expr head, Expr[] args, Syntax.WOrC op, Syntax.TType type, int prec, Syntax.K assoc) { Trace.Assert(args.Length == 2); List <T> lt = new List <T>(); lt.Add(Translate_maybe_paren(args[0], prec - ((assoc == Syntax.K.BinLeft) ? 1 : 0))); lt.Add(__TranslateOperator(head, op, type)); lt.Add(Translate_maybe_paren(args[1], prec - ((assoc == Syntax.K.BinRight) ? 1 : 0))); return(lt); }
/// <summary> /// Handles Syntax.K.{Prefix,Postfix} /// </summary> /// <param name="side">Prefix or Postfix</param> /// <returns></returns> private List <T> Translate_prepostfix(Expr head, Expr arg, Syntax.WOrC op, Syntax.TType type, int prec, Syntax.K side) { List <T> lt = new List <T>(); if (side == Syntax.K.Prefix || side == Syntax.K.PrefixOpt) { lt.Add(__TranslateOperator(head, op, type)); } lt.Add(Translate_maybe_paren(arg, prec - 1)); if (side == Syntax.K.Postfix) { lt.Add(__TranslateOperator(head, op, type)); } return(lt); }