public IBatch Parse(IGetter <string> source, string description = null) { SBD.Clear(); SINS.Clear(); CUR = new ins_variant(); var src = source.Get(); if (string.IsNullOrEmpty(src)) { goto finalize; } // This will store a filepath in order to prevent multiple calls for once-only files if (source is GetterTextFile) { FilesUsed.Add(((GetterTextFile)source).Filepath); } char c; var echr = src.AsEnumerable().GetEnumerator(); while (echr.MoveNext()) { c = echr.Current; this.append(c); } this.append('\r'); // this closes the current value-parsers and any other processing finalize: var ainp = SINS.Select(x => new Input(ref x)).ToArray(SINS.Count); var abab = ainp.Select(x => this.parse(x)).ToArrayR(ainp.Length); var bch = new BatchSequential() { Text = description }; return(bch.Append(abab)); }
void append(char c) { bool isretry = false; retry: // this means that the current instruction will append the current character // and no other processing needed if (CUR.TryAppend(ref c)) { if (c == '\\') { SBD.Append('\\'); } SBD.Append(c); return; } // the current character is not appended to instruction // but the instruction is still active and later might append some characters if (CUR.IsActive) { return; } if (isretry) { throw new InvalidOperationException("Infinite loop while parsing data"); } // the instruction has fullfilled it's mission // and now we need some other instruction if (c == lg.ChComment) { CUR = new ins_comment(); return; } else if (c == lg.ChQuotSim || c == lg.ChQuotCpx) { CUR = new ins_string(c); SBD.Append(c); return; } else if (c == lg.ChLinebrk) { linebreak(); return; } else if (c == lg.ChLineend) { linebreak(); return; } else if (CUR is ins_variant) { throw new InvalidOperationException("We found nonsense: current instruction is ins_variant and we need ins_variant"); } CUR = new ins_variant(); isretry = true; goto retry; void linebreak() { var ins = SBD.ToString(); if (!string.IsNullOrEmpty(ins) && !string.IsNullOrEmpty(ins = ins.Trim())) { SINS.Add(ins); } SBD.Clear(); CUR = new ins_variant(); } }