示例#1
0
文件: LesLexer.cs 项目: bel-uwa/Loyc
        static object ParseIntegerValue(UString source, bool isNegative, int numberBase, Symbol suffix, ref string error)
        {
            if (source.IsEmpty)
            {
                error = Localize.From("Syntax error in integer literal");
                return(CG.Cache(0));
            }
            // Parse the integer
            ulong unsigned;
            bool  overflow = !G.TryParseUInt(ref source, out unsigned, numberBase, G.ParseFlag.SkipUnderscores);

            if (!source.IsEmpty)
            {
                // I'm not sure if this can ever happen
                error = Localize.From("Syntax error in integer literal");
            }

            // If no suffix, automatically choose int, uint, long or ulong
            if (suffix == null)
            {
                if (unsigned > long.MaxValue)
                {
                    suffix = _UL;
                }
                else if (unsigned > uint.MaxValue)
                {
                    suffix = _L;
                }
                else if (unsigned > int.MaxValue)
                {
                    suffix = isNegative ? _L : _U;
                }
            }

            if (isNegative && (suffix == _U || suffix == _UL))
            {
                // Oops, an unsigned number can't be negative, so treat
                // '-' as a separate token and let the number be reparsed.
                return(CodeSymbols.Sub);
            }

            // Create boxed integer of the appropriate type
            object value;

            if (suffix == _UL)
            {
                value = unsigned;
            }
            else if (suffix == _U)
            {
                overflow = overflow || (uint)unsigned != unsigned;
                value    = (uint)unsigned;
            }
            else if (suffix == _L)
            {
                if (isNegative)
                {
                    overflow = overflow || -(long)unsigned > 0;
                    value    = -(long)unsigned;
                }
                else
                {
                    overflow = overflow || (long)unsigned < 0;
                    value    = (long)unsigned;
                }
            }
            else
            {
                value = isNegative ? -(int)unsigned : (int)unsigned;
            }

            if (overflow)
            {
                error = Localize.From("Overflow in integer literal (the number is 0x{0:X} after binary truncation).", value);
            }
            return(value);
        }
示例#2
0
        public static LNode run_LLLPG(LNode node, IMessageSink sink)
        {
            IPGCodeGenHelper helper;
            LNode            body;
            bool             hasBraces = true;

            if (node.ArgCount != 2 ||
                (helper = node.Args[0].Value as IPGCodeGenHelper) == null ||
                !(hasBraces = (body = node.Args[1]).Calls(S.Braces)))
            {
                string msg = Localize.From("Expected run_LLLPG(helper_object, {...}).");
                if (hasBraces)
                {
                    msg = " " + Localize.From("An auxiliary macro is required to supply the helper object.");
                }
                sink.Write(Severity.Note, node, msg);
                return(null);
            }
            helper = helper ?? new GeneralCodeGenHelper();

            var rules = new List <Pair <Rule, LNode> >();
            var stmts = new List <LNode>();

            // Let helper preprocess the code if it wants to
            foreach (var stmt in body.Args)
            {
                var stmt2 = helper.VisitInput(stmt, sink) ?? stmt;
                if (stmt2.Calls(S.Splice))
                {
                    stmts.AddRange(stmt2.Args);
                }
                else
                {
                    stmts.Add(stmt2);
                }
            }

            // Find rule definitions, create Rule objects
            for (int i = 0; i < stmts.Count; i++)
            {
                LNode stmt = stmts[i];
                bool  isToken;
                if ((isToken = stmt.Calls(_hash_token, 4)) || stmt.Calls(_hash_rule, 4))
                {
                    LNode basis      = stmt.WithTarget(S.Fn);
                    LNode methodBody = stmt.Args.Last;

                    // basis has the form #fn(ReturnType, Name, #(Args))
                    var rule = MakeRuleObject(isToken, ref basis, sink);
                    if (rule != null)
                    {
                        var prev = rules.FirstOrDefault(pair => pair.A.Name == rule.Name);
                        if (prev.A != null)
                        {
                            sink.Write(Severity.Error, rule.Basis, "The rule name «{0}» was used before at {1}", rule.Name, prev.A.Basis.Range.Start);
                        }
                        else
                        {
                            rules.Add(Pair.Create(rule, methodBody));
                            stmts[i] = null;                             // remove processed rules from the list
                        }
                    }
                }
                else
                {
                    if (stmt.Calls(_rule) || stmt.Calls(_token))
                    {
                        sink.Write(Severity.Error, stmt, "A rule should have the form rule(Name(Args)::ReturnType, @[...])");
                    }
                }
            }

            if (rules.Count == 0)
            {
                sink.Write(Severity.Warning, node, "No grammar rules were found in LLLPG block");
            }

            // Parse the rule definitions (now that we know the names of all the
            // rules, we can decide if an Id refers to a rule; if not, it's assumed
            // to refer to a terminal).
            new StageTwoParser(helper, sink).Parse(rules);

            // Process the grammar & generate code
            var lllpg = new LLParserGenerator(helper, sink);

            ApplyOptions(node, lllpg, sink);             // Read attributes such as [DefaultK(3)]
            foreach (var pair in rules)
            {
                lllpg.AddRule(pair.A);
            }

            // TODO: change lllpg so we can interleave generated code with other
            // user code, to preserve the order of declarations in the original code.
            var results = lllpg.Run(node.Source);

            return(F.Call(S.Splice, stmts.Where(p => p != null).Concat(results.Args)));
        }
示例#3
0
文件: LesLexer.cs 项目: bel-uwa/Loyc
        /// <summary>Parses a normal or triple-quoted string whose starting quotes
        /// have been stripped out. If triple-quote parsing was requested, stops
        /// parsing at three quote marks; otherwise, stops parsing at a single
        /// end-quote or newline.</summary>
        /// <returns>true if parsing stopped at one or three quote marks, or false
        /// if parsing stopped at the end of the input string or at a newline (in
        /// a string that is not triple-quoted).</returns>
        /// <remarks>This method recognizes LES and EC#-style string syntax.</remarks>
        public static bool UnescapeString(ref UString sourceText, char quoteType, bool isTripleQuoted, Action <int, string> onError, StringBuilder sb, UString indentation = default(UString))
        {
            Debug.Assert(quoteType == '"' || quoteType == '\'' || quoteType == '`');
            bool fail;

            for (;;)
            {
                if (sourceText.IsEmpty)
                {
                    return(false);
                }
                int i0 = sourceText.InternalStart;
                if (!isTripleQuoted)
                {
                    char c = G.UnescapeChar(ref sourceText);
                    if ((c == quoteType || c == '\n') && sourceText.InternalStart == i0 + 1)
                    {
                        return(c == quoteType);                        // end of string
                    }
                    if (c == '\\' && sourceText.InternalStart == i0 + 1)
                    {
                        // This backslash was ignored by UnescapeChar
                        onError(i0, Localize.From(@"Unrecognized escape sequence '\{0}' in string", G.EscapeCStyle(sourceText[0, ' '].ToString(), EscapeC.Control)));
                    }
                    sb.Append(c);
                }
                else
                {
                    // Inside triple-quoted string
                    int c;
                    if (sourceText[2, '\0'] == '/')
                    {
                        c = G.UnescapeChar(ref sourceText);
                        if (sourceText.InternalStart > i0 + 1)
                        {
                            G.Verify(sourceText.PopFront(out fail) == '/');
                        }
                    }
                    else
                    {
                        c = sourceText.PopFront(out fail);
                        if (fail)
                        {
                            return(false);
                        }
                        if (c == quoteType)
                        {
                            if (sourceText[0, '\0'] == quoteType &&
                                sourceText[1, '\0'] == quoteType)
                            {
                                sourceText = sourceText.Substring(2);
                                // end of string
                                return(true);
                            }
                        }
                        if (c == '\r' || c == '\n')
                        {
                            // To ensure platform independency of source code, CR and
                            // CR-LF become LF.
                            if (c == '\r')
                            {
                                c = '\n';
                                var copy = sourceText.Clone();
                                if (sourceText.PopFront(out fail) != '\n')
                                {
                                    sourceText = copy;
                                }
                            }
                            // Inside a triple-quoted string, the indentation following a newline
                            // is ignored, as long as it matches the indentation of the first line.
                            UString src = sourceText.Clone(), ind = indentation;
                            while (src.PopFront(out fail) == ind.PopFront(out fail) && !fail)
                            {
                                sourceText = src;
                            }
                        }
                    }

                    sb.Append((char)c);
                }
            }
        }
示例#4
0
 public KeyAlreadyExistsException() : base(Localize.From("The item or key being added already exists in the collection."))
 {
 }
示例#5
0
 public EmptySequenceException() : base(Localize.From("Failed to access the sequence because it is empty."))
 {
 }
示例#6
0
 protected void AppendMessage(StringBuilder str, MessageHolder.Message mhmsg)
 {
     str.Append(Localize.From(mhmsg.Severity.ToString()));
     str.Append(": ");
     str.AppendFormat(mhmsg.Format, mhmsg.Args);
 }
示例#7
0
 public EnumerationException() : base(Localize.From("The collection was modified after enumeration started."))
 {
 }
示例#8
0
 protected virtual void Error(bool inverted, IEnumerable <MatchType> expected)
 {
     Error(0, Localize.From("'{0}': expected {1}", ToString(LA0Int), ToString(inverted, expected)));
 }
示例#9
0
		protected virtual void Check(bool expectation, string expectedDescr = "")
		{
			if (!expectation)
				Error(0, Localize.From("An expected condition was false: {0}", expectedDescr));
		}
示例#10
0
        public static LNode SetOrCreateMember(LNode fn, IMessageSink sink)
        {
            // Expecting #fn(Type, Name, #(args), {body})
            if (fn.ArgCount < 3 || !fn.Args[2].Calls(S.List))
            {
                return(null);
            }
            var            args        = fn.Args[2].Args;
            LNode          body        = null;
            RVList <LNode> createStmts = RVList <LNode> .Empty;
            RVList <LNode> setStmts    = RVList <LNode> .Empty;

            for (int i = 0; i < args.Count; i++)
            {
                var    arg        = args[i];
                Symbol a          = S.Property;
                Symbol fieldName  = null;
                Symbol paramName  = null;
                LNode  plainArg   = null;
                LNode  createStmt = null;
                if (arg.Calls(S.Property))
                {
                    // #property(Type, Name<T>, {...})
                    var name = arg.Args[1];
                    fieldName  = Ecs.EcsNodePrinter.KeyNameComponentOf(name);
                    paramName  = ChooseArgName(fieldName);
                    plainArg   = F.Var(arg.Args[0], paramName);
                    createStmt = arg;
                }
                else
                {
                    LNode type, defaultValue;
                    if (IsVar(arg, out type, out paramName, out defaultValue))
                    {
                        int a_i = 0;
                        foreach (var attr in arg.Attrs)
                        {
                            if (attr.IsId)
                            {
                                a = attr.Name;
                                if (a == _set ||
                                    a == S.Public || a == S.Internal || a == S.Protected || a == S.Private ||
                                    a == S.ProtectedIn || a == S.Static || a == S.Partial)
                                {
                                    fieldName = paramName;
                                    paramName = ChooseArgName(fieldName);
                                    if (a == _set)
                                    {
                                        plainArg = F.Var(type, paramName, defaultValue).WithAttrs(arg.Attrs.RemoveAt(a_i));
                                    }
                                    else
                                    {
                                        plainArg   = F.Var(type, paramName, defaultValue);
                                        createStmt = arg;
                                        // in case of something like "public T arg = value", assume that
                                        // "= value" represents a default value, not a field initializer.
                                        if (arg.Args[1].Calls(S.Assign, 2))
                                        {
                                            createStmt = arg.WithArgChanged(1,
                                                                            arg.Args[1].Args[0]);
                                        }
                                    }
                                    break;
                                }
                            }
                            a_i++;
                        }
                    }
                }
                if (plainArg != null)
                {
                    if (body == null)
                    {
                        if (fn.ArgCount < 4 || !fn.Args[3].Calls(S.Braces))
                        {
                            return(Reject(sink, arg, Localize.From("'{0}': to set or create a field or property, the method must have a body in braces {{}}.", a)));
                        }
                        body = fn.Args[3];
                    }

                    args[i] = plainArg;
                    LNode assignment;
                    if (fieldName == paramName)
                    {
                        assignment = F.Call(S.Assign, F.Dot(F.@this, F.Id(fieldName)), F.Id(paramName));
                    }
                    else
                    {
                        assignment = F.Call(S.Assign, F.Id(fieldName), F.Id(paramName));
                    }
                    setStmts.Add(assignment);
                    if (createStmt != null)
                    {
                        createStmts.Add(createStmt);
                    }
                }
            }
            if (body != null)             // if this macro has been used...
            {
                var parts = fn.Args;
                parts[2] = parts[2].WithArgs(args);
                parts[3] = body.WithArgs(body.Args.InsertRange(0, setStmts));
                fn       = fn.WithArgs(parts);
                if (createStmts.IsEmpty)
                {
                    return(fn);
                }
                else
                {
                    createStmts.Add(fn);
                    return(F.Call(S.Splice, createStmts));
                }
            }
            return(null);
        }
示例#11
0
 private void ThrowKeyAlreadyExists(long key)
 {
     throw new ArgumentException(Localize.From("Key already exists: ") + key.ToString());
 }
示例#12
0
        protected void ReadNextBlock()
        {
            _decoder.Reset();

            // Read the next block
            int amtRequested = _buf.Length - MaxSeqSize;
            int amtRead      = _stream.Read(_buf, 0, amtRequested);

            if (amtRead < amtRequested)
            {
                _reachedEnd = true;
                if (amtRead > 0)
                {
                    // decode the block
                    _blkStart = _eofIndex;
                    int cc = _decoder.GetCharCount(_buf, 0, amtRead, true);
                    if (_blk.Length < cc)
                    {
                        Array.Resize(ref _blk, cc);
                    }
                    _blkLen = _decoder.GetChars(_buf, 0, amtRead, _blk, 0, true);
                    Debug.Assert(cc == _blkLen);
                    // compute & record location of end of block
                    _eofIndex    += _blkLen;
                    _eofPosition += (uint)amtRead;
                    _blkOffsets.Add(new Pair <int, uint>(_eofIndex, _eofPosition));
                }
            }
            else
            {
                // decode the block...
                int amtProcessed = amtRead - MaxSeqSize;
                int minBlkSize   = _decoder.GetCharCount(_buf, 0, amtProcessed) + 1;
                if (_blk.Length < minBlkSize)
                {
                    Array.Resize(ref _blk, minBlkSize);
                }
                _blkStart = _eofIndex;
                _blkLen   = _decoder.GetChars(_buf, 0, amtProcessed, _blk, 0, false);

                // then 'top it up'
                int n = 1, cc;
                while ((cc = _decoder.GetCharCount(_buf, amtProcessed, n)) == 0)
                {
                    n++;
                    if (amtProcessed + n == _buf.Length)
                    {
                        throw new ArgumentException(Localize.From("StreamCharSource cannot use the supplied decoder because it can produce single characters from byte sequences longer than {0} characters", MaxSeqSize));
                    }
                }
                minBlkSize = _blkLen + cc;
                if (_blk.Length < minBlkSize)
                {
                    Array.Resize(ref _blk, minBlkSize);
                }
                try {
                    _blkLen      += _decoder.GetChars(_buf, amtProcessed, n, _blk, _blkLen, true);
                    amtProcessed += n;
                } catch (Exception exc) {
                    // assume index-out-of-range encountered. Note that this exception
                    // may never happen even if the decoder is incompatible.
                    throw new ArgumentException(Localize.From("StreamCharSource cannot use the supplied decoder because it seems to divide characters on bit boundaries"), exc);
                }
                // compute & record location of end of block
                _eofIndex    += _blkLen;
                _eofPosition += (uint)amtProcessed;
                _blkOffsets.Add(new Pair <int, uint>(_eofIndex, _eofPosition));
                // note: when necessary, the caller will rewind to the last byte
                // actually processed by doing _stream.Position = _eofPosition
            }
        }