This class's main job is to maintain a table of Precedence values for LES operators. When you ask about a new operator, its precedence is cached for future reference.
Beispiel #1
0
        private bool AutoPrintPrefixOrSuffixOp(ILNode node, Precedence context)
        {
            Symbol bareName;

            if (LesPrecedenceMap.IsSuffixOperatorName(node.Name, out bareName, false))
            {
                var prec = GetPrecedenceIfOperator(node, OperatorShape.Suffix, context);
                if (prec == null || prec.Value == LesPrecedence.Other)
                {
                    return(false);
                }
                Print(node[0], prec.Value.LeftContext(context));
                SpaceIf(prec.Value.Lo < _o.SpaceAfterPrefixStopPrecedence);
                WriteOpName(bareName, node.Target, prec.Value);
            }
            else
            {
                var prec = GetPrecedenceIfOperator(node, OperatorShape.Prefix, context);
                if (prec == null)
                {
                    return(false);
                }
                var spaceAfter = prec.Value.Lo < _o.SpaceAfterPrefixStopPrecedence;
                WriteOpName(node.Name, node.Target, prec.Value, spaceAfter);
                Print(node[0], prec.Value.RightContext(context));
            }
            return(true);
        }
Beispiel #2
0
        private Precedence?GetPrecedenceIfOperator(LNode node, OperatorShape shape, Precedence context)
        {
            int ac = node.ArgCount;

            if ((ac == (int)shape || ac == -(int)shape) && HasSimpleTargetWithoutPAttrs(node))
            {
                var  bs        = node.BaseStyle;
                var  op        = node.Name;
                bool naturalOp = LesPrecedenceMap.IsNaturalOperator(op);
                if (bs == NodeStyle.Operator || (naturalOp && bs != NodeStyle.PrefixNotation))
                {
                    var result = _prec.Find(shape, op);
                    if (bs == NodeStyle.Operator && !naturalOp)
                    {
                        result = LesPrecedence.Backtick;
                    }
                    else if (!result.CanAppearIn(context))
                    {
                        result = LesPrecedence.Backtick;
                    }
                    if (!result.CanAppearIn(context) || !result.CanMixWith(context))
                    {
                        return(null);
                    }
                    return(result);
                }
            }
            return(null);
        }
Beispiel #3
0
        private bool AutoPrintPrefixOrSuffixOp(LNode node, Mode mode, Precedence context)
        {
            Symbol bareName;

            if (LesPrecedenceMap.IsSuffixOperatorName(node.Name, out bareName, false))
            {
                var prec = GetPrecedenceIfOperator(node, OperatorShape.Suffix, context);
                if (prec == null || prec.Value == LesPrecedence.Backtick)
                {
                    return(false);
                }
                Print(node.Args[0], mode, prec.Value.LeftContext(context));
                SpaceIf(prec.Value.Lo < SpaceAfterPrefixStopPrecedence);
                WriteOpName(bareName, prec.Value);
            }
            else
            {
                var prec = GetPrecedenceIfOperator(node, OperatorShape.Prefix, context);
                if (prec == null)
                {
                    return(false);
                }
                WriteOpName(node.Name, prec.Value);
                SpaceIf(prec.Value.Lo < SpaceAfterPrefixStopPrecedence);
                Print(node.Args[0], mode, prec.Value.RightContext(context));
            }
            return(true);
        }
Beispiel #4
0
 private void WriteOpName(Symbol op, Precedence prec)
 {
     if (prec == LesPrecedence.Backtick || !LesPrecedenceMap.IsNaturalOperator(op))
     {
         PrintStringCore('`', false, op.Name);
     }
     else
     {
         _out.Write(op.Name, true);
     }
     //else {
     //	_out.Write('\\', false);
     //	_out.Write(op.Name, true);
     //	_out.Space(); // lest the next char to be printed be treated as part of the operator name
     //}
 }
Beispiel #5
0
        private Precedence?GetPrecedenceIfOperator(ILNode node, OperatorShape shape, Precedence context)
        {
            int ac = node.ArgCount();

            if ((ac == (int)shape || ac == -(int)shape) && HasTargetIdWithoutPAttrs(node))
            {
                var  bs        = node.BaseStyle();
                var  op        = node.Name;
                bool naturalOp = LesPrecedenceMap.IsNaturalOperator(op.Name);
                if ((naturalOp && bs != NodeStyle.PrefixNotation) ||
                    (bs == NodeStyle.Operator && node.Name != null))
                {
                    var result = _prec.Find(shape, op);
                    if (!result.CanAppearIn(context) || !result.CanMixWith(context))
                    {
                        return(null);
                    }
                    return(result);
                }
            }
            return(null);
        }
Beispiel #6
0
 private void WriteOpName(Symbol op, ILNode target, Precedence prec, bool spaceAfter = false)
 {
     // Note: if the operator has a space after it, there's a subtle reason why
     // we want to print that space before the trivia and not after. Consider
     // the input "a == //comment\n    b". After trivia injection this becomes
     // (@[#trivia_trailing(#trivia_SLComment("comment"))] @==)(a, @[#trivia_newline] b).
     // Because the injector associates the newline with a different node than the
     // single-line comment, there's no easy way to strip out the newline during
     // the parsing process. So, to make the trivia round-trip, we use
     // _out.Newline(pending: true) when printing a single-line comment, which
     // suppresses the newline if it is followed immediately by another newline.
     // But if we print a space after the trivia, then this suppression does not
     // occur and we end up with two newlines. Therefore, we must print the space first.
     if (target.AttrCount() == 0)
     {
         target = null;                 // optimize the usual case
     }
     if (target != null)
     {
         PrintPrefixTrivia(target);
     }
     if (!LesPrecedenceMap.IsNaturalOperator(op.Name))
     {
         PrintStringCore('`', false, op.Name);
     }
     else
     {
         Debug.Assert(op.Name.StartsWith("'"));
         _out.Write(op.Name.Substring(1), true);
     }
     SpaceIf(spaceAfter);
     if (target != null)
     {
         PrintSuffixTrivia(target, 0, null);
     }
 }