Exemplo n.º 1
0
        /// <summary>
        /// Decodes an id node using a symbol-to-value mapping.
        /// An error is reported if the node cannot be decoded.
        /// </summary>
        /// <param name="node">A node to decode.</param>
        /// <param name="decodeMap">
        /// A mapping of symbols to values that is used for
        /// decoding the node.
        /// </param>
        /// <param name="enumDescription">
        /// A short description of the type of value that is being
        /// decoded, e.g., "method lookup strategy".
        /// </param>
        /// <param name="result">
        /// The decoded value, if any.
        /// </param>
        /// <returns>
        /// <c>true</c> if the node could be decoded; otherwise, <c>false</c>.
        /// </returns>
        public bool AssertDecodeEnum <T>(
            LNode node,
            IReadOnlyDictionary <Symbol, T> decodeMap,
            string enumDescription,
            out T result)
        {
            if (!node.IsId)
            {
                Log.LogSyntaxError(
                    node,
                    FeedbackHelpers.QuoteEven(
                        "expected " + enumDescription + " (",
                        FeedbackHelpers.SpellNodeKind(LNodeKind.Id),
                        " node) but got ",
                        FeedbackHelpers.SpellNodeKind(node),
                        " node."));
                result = default(T);
                return(false);
            }

            if (decodeMap.TryGetValue(node.Name, out result))
            {
                return(true);
            }
            else
            {
                // Create a sorted list of all admissible values.
                var sortedKeys = new List <string>();
                foreach (var item in decodeMap.Keys)
                {
                    sortedKeys.Add(item.Name);
                }
                sortedKeys.Sort();

                // Generate a lengthy message that details exactly what
                // is admissible.
                var message = new List <MarkupNode>();
                message.Add("unknown " + enumDescription + " ");
                message.Add(node.Name.Name);
                message.Add("; expected ");
                for (int i = 0; i < sortedKeys.Count - 1; i++)
                {
                    message.Add(sortedKeys[i]);
                    if (i < sortedKeys.Count - 2)
                    {
                        message.Add(", ");
                    }
                    else
                    {
                        message.Add(" or ");
                    }
                }
                message.Add(sortedKeys[sortedKeys.Count - 1]);
                message.Add(".");

                Log.LogSyntaxError(
                    node,
                    FeedbackHelpers.QuoteEven(message.ToArray()));

                return(false);
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Decodes an LNode as a constant value.
        /// </summary>
        /// <param name="node">The node to decode.</param>
        /// <param name="state">The decoder state to use.</param>
        /// <returns>A decoded constant.</returns>
        public override Constant Decode(LNode node, DecoderState state)
        {
            // Default-value constants.
            if (node.IsIdNamed(CodeSymbols.Default))
            {
                return(DefaultConstant.Instance);
            }

            // Type/field/method token constants.
            if (node.Calls(CodeSymbols.Typeof, 1))
            {
                return(new TypeTokenConstant(state.DecodeType(node.Args[0])));
            }
            else if (node.Calls(fieldofSymbol, 1))
            {
                return(new FieldTokenConstant(state.DecodeField(node.Args[0])));
            }
            else if (node.Calls(methodofSymbol, 1))
            {
                return(new MethodTokenConstant(state.DecodeMethod(node.Args[0])));
            }

            if (!FeedbackHelpers.AssertIsLiteral(node, state.Log))
            {
                return(null);
            }

            object value;
            Symbol typeMarker;

            // Custom literals.
            if (TryDecomposeCustomLiteral(node, out value, out typeMarker))
            {
                // Arbitrary-width integer literals.
                IntegerSpec spec;
                if (IntegerSpec.TryParse(typeMarker.Name, out spec))
                {
                    BigInteger integerVal;
                    if (BigInteger.TryParse(value.ToString(), out integerVal))
                    {
                        return(new IntegerConstant(integerVal, spec));
                    }
                    else
                    {
                        FeedbackHelpers.LogSyntaxError(
                            state.Log,
                            node,
                            FeedbackHelpers.QuoteEven(
                                "cannot parse ",
                                value.ToString(),
                                " as an integer."));
                        return(null);
                    }
                }
                else
                {
                    FeedbackHelpers.LogSyntaxError(
                        state.Log,
                        node,
                        FeedbackHelpers.QuoteEven(
                            "unknown custom literal type ",
                            typeMarker.Name,
                            "."));
                    return(null);
                }
            }

            value = node.Value;

            // Miscellaneous constants: null, strings, Booleans.
            if (value == null)
            {
                return(NullConstant.Instance);
            }
            else if (value is string)
            {
                return(new StringConstant((string)value));
            }
            else if (value is bool)
            {
                return(BooleanConstant.Create((bool)value));
            }
            // Floating-point numbers.
            else if (value is float)
            {
                return(new Float32Constant((float)value));
            }
            else if (value is double)
            {
                return(new Float64Constant((double)value));
            }
            // Fixed-width integer constants and characters.
            else if (value is char)
            {
                return(new IntegerConstant((char)value));
            }
            else if (value is sbyte)
            {
                return(new IntegerConstant((sbyte)value));
            }
            else if (value is short)
            {
                return(new IntegerConstant((short)value));
            }
            else if (value is int)
            {
                return(new IntegerConstant((int)value));
            }
            else if (value is long)
            {
                return(new IntegerConstant((long)value));
            }
            else if (value is byte)
            {
                return(new IntegerConstant((byte)value));
            }
            else if (value is ushort)
            {
                return(new IntegerConstant((ushort)value));
            }
            else if (value is uint)
            {
                return(new IntegerConstant((uint)value));
            }
            else if (value is ulong)
            {
                return(new IntegerConstant((ulong)value));
            }

            FeedbackHelpers.LogSyntaxError(
                state.Log,
                node,
                new Text("unknown literal type."));
            return(null);
        }