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 chosen by this class and cached for future reference.
예제 #1
0
        private bool AutoPrintPrefixOrSuffixOp(ILNode node, Precedence context)
        {
            Symbol bareName;

            if (Les2PrecedenceMap.IsSuffixOperatorName(node.Name, out bareName))
            {
                var prec = GetPrecedenceIfOperator(node, bareName, 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, bareName, 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);
        }
예제 #2
0
        private Precedence?GetPrecedenceIfOperator(ILNode node, Symbol opName, OperatorShape shape, Precedence context)
        {
            int ac = node.ArgCount();

            if ((ac == (int)shape || ac == -(int)shape) && HasTargetIdWithoutPAttrs(node))
            {
                var  bs        = node.BaseStyle();
                bool naturalOp = Les2PrecedenceMap.IsNaturalOperator(opName.Name);
                if ((naturalOp && bs != NodeStyle.PrefixNotation) ||
                    (bs == NodeStyle.Operator && node.Name != null))
                {
                    var result = _prec.Find(shape, opName);
                    if (!result.CanAppearIn(context) || !result.CanMixWith(context))
                    {
                        return(null);
                    }
                    return(result);
                }
            }
            return(null);
        }
예제 #3
0
        private void WriteOpName(Symbol op, ILNode target, Precedence prec, bool spaceAfter = false)
        {
            _out.BeginNode(target);

            // 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
            // (@[@%trailing(@%SLComment("comment"))] @==)(a, @[@%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 (!Les2PrecedenceMap.IsNaturalOperator(op.Name))
            {
                PrintStringCore('`', false, op.Name);
            }
            else
            {
                Debug.Assert(op.Name.StartsWith("'"));
                _out.Write(op.Name.Substring(1));
            }
            SpaceIf(spaceAfter);
            if (target != null)
            {
                PrintSuffixTrivia(target, 0, null);
            }

            _out.EndNode();
        }