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); }
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))); }
/// <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); } } }
public KeyAlreadyExistsException() : base(Localize.From("The item or key being added already exists in the collection.")) { }
public EmptySequenceException() : base(Localize.From("Failed to access the sequence because it is empty.")) { }
protected void AppendMessage(StringBuilder str, MessageHolder.Message mhmsg) { str.Append(Localize.From(mhmsg.Severity.ToString())); str.Append(": "); str.AppendFormat(mhmsg.Format, mhmsg.Args); }
public EnumerationException() : base(Localize.From("The collection was modified after enumeration started.")) { }
protected virtual void Error(bool inverted, IEnumerable <MatchType> expected) { Error(0, Localize.From("'{0}': expected {1}", ToString(LA0Int), ToString(inverted, expected))); }
protected virtual void Check(bool expectation, string expectedDescr = "") { if (!expectation) Error(0, Localize.From("An expected condition was false: {0}", expectedDescr)); }
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); }
private void ThrowKeyAlreadyExists(long key) { throw new ArgumentException(Localize.From("Key already exists: ") + key.ToString()); }
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 } }