public override void PostCheck(GEDCommon rec) { var me = rec as IndiRecord; if (string.IsNullOrWhiteSpace(me.Ident)) { UnkRec err = new UnkRec(); err.Error = UnkRec.ErrorCode.MissIdent; // TODO "INDI missing identifier"; // TODO assign one? err.Beg = err.End = me.BegLine; err.Tag = rec.Tag; me.Errors.Add(err); } // TODO should this be checked in the SEX routine so line # points at the actual line??? // Make sure sex is set if (me.Sex != '\0') { if (!"MFUmfu".Contains(me.Sex.ToString(CultureInfo.InvariantCulture))) { me.Sex = 'U'; UnkRec err = new UnkRec(); err.Error = UnkRec.ErrorCode.InvSex; // "Non-standard SEX value corrected to U"; err.Beg = err.End = me.BegLine; me.Errors.Add(err); // TODO as warning } } CheckRestriction(me, me.Restriction); // TODO check restriction value on events }
public static void ChanProc(ParseContext2 ctx) { ChangeRec chan = ctx.Parent.CHAN; if (chan.Date != null) { UnkRec err = new UnkRec(); err.Error = UnkRec.ErrorCode.MultChan; GedRecParse.LookAhead(ctx); err.Beg = ctx.Begline + ctx.Parent.BegLine; err.End = ctx.Endline + ctx.Parent.BegLine; ctx.Parent.Errors.Add(err); return; } ChanParse(ctx, chan); if (chan.Date == null) { UnkRec err = new UnkRec(); err.Error = UnkRec.ErrorCode.ChanDate; err.Beg = ctx.Begline + ctx.Parent.BegLine; err.End = ctx.Endline + ctx.Parent.BegLine; ctx.Parent.Errors.Add(err); } }
public override void PostCheck(GEDCommon rec) { MediaRecord me = rec as MediaRecord; if (string.IsNullOrWhiteSpace(me.Ident)) { UnkRec err = new UnkRec(); err.Error = UnkRec.ErrorCode.MissIdent; // TODO "Missing identifier"; // TODO assign one? err.Beg = err.End = me.BegLine; me.Errors.Add(err); } // A FILE record is required if (me.Files.Count < 1) { UnkRec err = new UnkRec(); err.Error = UnkRec.ErrorCode.MissFile; // "Missing FILE"; err.Beg = err.End = me.BegLine; me.Errors.Add(err); } // Each FILE record must have a FORM foreach (var mediaFile in me.Files) { if (string.IsNullOrWhiteSpace(mediaFile.Form)) { UnkRec err = new UnkRec(); err.Error = UnkRec.ErrorCode.MissForm; // "Missing FORM"; err.Beg = err.End = me.BegLine; me.Errors.Add(err); } } }
private void nchiProc(ParseContext2 context) { // TODO Data loss: The Master Genealogist (TMG) treats NCHI as a text field. // NCHI in TMG can have CONC, CONT, and other sub-tags. Here, these sub-tags // are not correctly connected to the NCHI tag, nor am I preserving the NCHI // data as entered. var fam = (context.Parent as FamRecord); int childCount; if (!int.TryParse(context.Remain, out childCount)) { UnkRec err = new UnkRec(); err.Error = UnkRec.ErrorCode.InvNCHI; //"Invalid child count"; err.Beg = err.End = context.Begline + context.Parent.BegLine; fam.Errors.Add(err); } else if (fam.ChildCount != -1) // has been specified once already { UnkRec err = new UnkRec(); err.Error = UnkRec.ErrorCode.MultNCHI; //err.Error = "Child count specified more than once"; err.Beg = err.End = context.Begline + context.Parent.BegLine; fam.Errors.Add(err); } else { fam.ChildCount = childCount; } }
public static AssoRec AssoParse(ParseContext2 ctx) { var asso = new AssoRec(); string xref; string extra; parseXrefExtra(ctx.Remain, out xref, out extra); if (string.IsNullOrEmpty(xref)) { UnkRec err = new UnkRec(); err.Error = UnkRec.ErrorCode.UntermIdent; // TODO err.Error = "Missing/unterminated identifier: " + ctx.Tag; err.Beg = err.End = ctx.Begline + ctx.Parent.BegLine; err.Tag = ctx.Tag; ctx.Parent.Errors.Add(err); // TODO parent level or structure level? } else { asso.Ident = xref; } //StructParseContext ctx2 = new StructParseContext(ctx, asso); StructParseContext ctx2 = PContextFactory.Alloc(ctx, asso); StructParse(ctx2, tagDict); ctx.Endline = ctx2.Endline; PContextFactory.Free(ctx2); return(asso); // TODO validate relation specified // TODO validate ident existance }
public override void PostCheck(GEDCommon rec) { var me = rec as NoteRecord; if (string.IsNullOrWhiteSpace(me.Ident)) { UnkRec err = new UnkRec(); err.Error = UnkRec.ErrorCode.MissIdent; // TODO {Error = "Missing identifier"}; err.Beg = err.End = me.BegLine; me.Errors.Add(err); } if (me.Builder.Length > 0) { // Store an in-line note to the database string text = me.Builder.ToString().Replace("@@", "@"); #if SQLITE me.Key = SQLite.Instance.StoreNote(text); #elif LITEDB me.Key = LiteDB.Instance.StoreNote(text); #elif NOTESTREAM me.Key = NoteStream.Instance.StoreNote(text); #else me.Text = text; #endif } else { me.Text = ""; } //me.Text = me.Builder.ToString().Replace("@@", "@"); // TODO faster replace me.Builder = null; }
// Common method for unit testing (instream != null) or file reading (gedPath != null) /// <summary> /// Read GEDCOM data into memory. /// </summary> /// <param name="gedPath">The path to the file. If null, will attempt to read from instream instead.</param> /// <param name="instream">An input stream to read from instead of a file path.</param> public void ReadGed(string gedPath, StreamReader instream = null) { _emptyLineSeen = 0; FilePath = gedPath; Errors = new List <UnkRec>(); GedReader _reader = new GedReader(); _reader.BufferSize = _bufferSize; _reader.ProcessALine = ProcessLine; _reader.ErrorTracker = DoError; // Processor context Parser = new GedParser(FilePath); Data = new List <GEDCommon>(); if (Errors == null) { Errors = new List <UnkRec>(); } _currRec = new GedRecord(); #if SQLITE var foo = SQLite.Instance; #elif LITEDB var foo = SharpGEDParser.Parser.LiteDB.Instance; #elif NOTESTREAM var foo = NoteStream.Instance; #endif #if XREFTRACK var bar = XrefTrack.Instance; #endif try { if (gedPath == null) { _reader.ReadFile(instream); } else { _reader.ReadFile(gedPath); } EndOfFile(); } catch (Exception) { UnkRec err = new UnkRec(); err.Error = UnkRec.ErrorCode.Exception; err.Beg = _lineNum; // TODO err.Error = string.Format("Exception: {0} line {1} | {2}", ex.Message, _lineNum, ex.StackTrace); Errors.Add(err); } Parser.FinishUp(); GatherRecords(); GatherErrors(); _lineNum = _reader._lineNum; _currRec = null; }
private void DoError(UnkRec.ErrorCode msg, int lineNum) { var err = new UnkRec(); err.Error = msg; err.Beg = lineNum; err.End = lineNum; Errors.Add(err); }
private StringPlus CheckAndMakeId(ParseContext2 ctx, StringPlus who) { if (who != null) { var rec = new UnkRec(ctx.Tag, ctx.Begline + ctx.Lines.Beg, ctx.Endline + ctx.Lines.Beg); rec.Error = UnkRec.ErrorCode.MultId; ctx.Parent.Errors.Add(rec); return(who); } return(makeId(ctx)); }
private static SourceCit CommonParser(ParseContextCommon ctx, int linedex, char level, List <UnkRec> errs) { SourceCit cit = new SourceCit(); StructParseContext ctx2 = new StructParseContext(ctx, linedex, level, cit); // TODO no record for context! string extra; string xref; parseXrefExtra(ctx.Remain, out xref, out extra); cit.Xref = xref; if (xref != null && (xref.Trim().Length == 0 || cit.Xref.Contains("@"))) // No xref is valid but not if empty/illegal { var unk = new UnkRec(); unk.Error = UnkRec.ErrorCode.InvXref; // TODO {Error = "Invalid source citation xref id"}; unk.Beg = ctx.Begline + ctx.Lines.Beg; unk.End = ctx.Endline + ctx.Lines.Beg; errs.Add(unk); } if (!string.IsNullOrEmpty(extra)) { cit.Desc = extra; } StructParse(ctx2, tagDict); ctx.Endline = ctx2.Endline; if (!cit.Data && cit.Xref != null && cit.AnyText) { var unk = new UnkRec(); unk.Error = UnkRec.ErrorCode.RefSourText; // TODO { Error = "TEXT tag used for reference source citation" }; unk.Beg = ctx.Begline + ctx.Lines.Beg; unk.End = ctx2.Endline + ctx.Lines.Beg; errs.Add(unk); } if (cit.Xref == null && cit.Event != null) { var unk = new UnkRec(); unk.Error = UnkRec.ErrorCode.EmbSourEven; // TODO { Error = "EVEN tag used for embedded source citation" }; unk.Beg = ctx.Begline + ctx.Lines.Beg; unk.End = ctx2.Endline + ctx.Lines.Beg; errs.Add(unk); } if (cit.Xref == null && cit.Page != null) { var unk = new UnkRec(); unk.Error = UnkRec.ErrorCode.EmbSourPage; // TODO { Error = "PAGE tag used for embedded source citation" }; unk.Beg = ctx.Begline + ctx.Lines.Beg; unk.End = ctx.Endline + ctx.Lines.Beg; errs.Add(unk); } return(cit); }
private void PopulateLineList(int type, object data) { listBox2.SuspendLayout(); listBox2.Items.Clear(); // TODO delay update? richTextBox1.ResetText(); if (type != ISS) { var foo = data as List <atup2>; atup2 first = foo[0]; if (type == ERR) { textBox1.Text = string.Format("Error: {0}{2}, Count:{1}", first.Item1.Error, foo.Count, string.IsNullOrEmpty(first.Item1.Tag) ? "" : ", Tag:" + first.Item1.Tag); } else { textBox1.Text = string.Format("Unknown: {0}, Count:{1}", first.Item1.Tag, foo.Count); } foreach (var tuple in foo) { UnkRec unk = tuple.Item1; string val = string.Format("Lines:{0}-{1}", unk.Beg, unk.End); ListBoxItem2 lbi2 = new ListBoxItem2(); lbi2.txt = val; lbi2.err = unk; lbi2.rec = tuple.Item2; listBox2.Items.Add(lbi2); } } else { var foo = data as List <Issue>; Issue first = foo[0]; textBox1.Text = string.Format("Issue: {0}, Count:{1}", first.IssueId, foo.Count); foreach (var iss in foo) { string val = iss.Message(); ListBoxItem2 lbi2 = new ListBoxItem2(); lbi2.txt = val; lbi2.rec = null; // TODO need record link lbi2.iss = iss; listBox2.Items.Add(lbi2); } } if (listBox2.Items.Count > 0) { listBox2.SelectedIndex = 0; } listBox2.ResumeLayout(); }
public override void PostCheck(GEDCommon rec) { SourceRecord me = rec as SourceRecord; if (string.IsNullOrWhiteSpace(me.Ident)) // TODO common? { UnkRec err = new UnkRec(); err.Error = UnkRec.ErrorCode.MissIdent; // TODO {Error = "Missing identifier"}; err.Beg = err.End = rec.BegLine; me.Errors.Add(err); } // No required data except Xref id? // TODO Warning: no data provide }
public static IndiLink LinkParse(ParseContext2 ctx) { UnkRec err = null; IndiLink link = new IndiLink(); // Can't get here for values other than FAMC/FAMS [unless caller changes!] link.Type = ctx.Tag == "FAMC" ? IndiLink.FAMC_TYPE : IndiLink.FAMS_TYPE; string xref; string extra; parseXrefExtra(ctx.Remain, out xref, out extra); if (string.IsNullOrEmpty(xref)) { err = new UnkRec(); err.Error = UnkRec.ErrorCode.MissIdent; err.Beg = err.End = ctx.Begline + ctx.Parent.BegLine; err.Tag = ctx.Tag; ctx.Parent.Errors.Add(err); } else { link.Xref = xref; } if (!string.IsNullOrEmpty(extra)) { link.Extra = extra; } //StructParseContext ctx2 = new StructParseContext(ctx, link); StructParseContext ctx2 = PContextFactory.Alloc(ctx, link); StructParse(ctx2, tagDict); ctx.Endline = ctx2.Endline; PContextFactory.Free(ctx2); if (err != null) { // Fallout from GedValid: an error in the link should not create an IndiLink err.End = ctx.Endline + ctx.Parent.BegLine; // entire structure in error return(null); } return(link); }
private void resnProc(ParseContext2 context) { var fam = (context.Parent as FamRecord); if (string.IsNullOrEmpty(fam.Restriction)) { fam.Restriction = context.Remain.Trim(); } else { UnkRec err = new UnkRec(); err.Error = UnkRec.ErrorCode.MultRESN; // TODO "RESN specified more than once"; err.Beg = err.End = context.Begline + context.Parent.BegLine; fam.Errors.Add(err); } }
protected static string parseForXref(ParseContext2 context, UnkRec.ErrorCode errVal = UnkRec.ErrorCode.MissIdent) { string xref; string extra; StructParser.parseXrefExtra(context.Remain, out xref, out extra); if (string.IsNullOrEmpty(xref)) { UnkRec err = new UnkRec(); err.Error = errVal; err.Beg = err.End = context.Begline + context.Parent.BegLine; err.Tag = context.Tag; context.Parent.Errors.Add(err); } return(xref); }
private void resnProc(ParseContext2 context) { var indi = (context.Parent as IndiRecord); if (string.IsNullOrEmpty(indi.Restriction)) { indi.Restriction = context.Remain.Trim(); } else { UnkRec err = new UnkRec(); err.Error = UnkRec.ErrorCode.MultRESN; // "RESN specified more than once"; err.Beg = err.End = context.Begline; indi.Errors.Add(err); } }
protected void UidProc(ParseContext2 ctx) { if (ctx.Parent._uid != null) { var rec = new UnkRec(ctx.Tag, ctx.Begline + ctx.Lines.Beg, ctx.Endline + ctx.Lines.Beg); rec.Error = UnkRec.ErrorCode.MultId; ctx.Parent.Errors.Add(rec); return; } int len = ctx.Remain1.Length; ctx.Parent._uid = new byte[len]; for (int i = 0; i < len; i++) { ctx.Parent._uid[i] = (byte)ctx.Remain1[i]; } }
public static void NonStandardRemain(string remain, GEDCommon rec) { // Extra text on the record line (e.g. "0 @R1@ REPO blah blah blah") is not standard for // most record types. Preserve it as a note if possible. if (!string.IsNullOrWhiteSpace(remain)) { UnkRec err = new UnkRec(); err.Beg = err.End = rec.BegLine; err.Error = UnkRec.ErrorCode.InvExtra; rec.Errors.Add(err); if (rec is NoteHold) { Note not = new Note(); not.Text = remain; (rec as NoteHold).Notes.Add(not); } } }
public override void PostCheck(GEDCommon rec) { var me = rec as FamRecord; if (string.IsNullOrWhiteSpace(me.Ident)) { UnkRec err = new UnkRec(); err.Error = UnkRec.ErrorCode.MissIdent; // "Missing identifier"; // TODO assign one? err.Beg = err.End = me.BegLine; err.Tag = rec.Tag; me.Errors.Add(err); } // TODO NCHI value doesn't match # of CHIL refs? CheckRestriction(me, me.Restriction); // TODO check restriction value on events }
public static NameRec Parse(ParseContext2 ctx) { // TODO can this be shortcut when context length is only 1 line? var name = new NameRec(); if (!parseName(name, ctx.Remain1, ctx.Begline, ctx.Parent.Errors)) { UnkRec err = new UnkRec(); err.Error = UnkRec.ErrorCode.EmptyName; err.Beg = err.End = ctx.Begline; ctx.Parent.Errors.Add(err); } //StructParseContext ctx2 = new StructParseContext(ctx, name); var ctx2 = PContextFactory.Alloc(ctx, name); StructParse(ctx2, tagDict); ctx.Endline = ctx2.Endline; PContextFactory.Free(ctx2); return(name); }
public override void PostCheck(GEDCommon rec) { Repository me = rec as Repository; if (string.IsNullOrWhiteSpace(me.Ident)) { UnkRec err = new UnkRec(); err.Error = UnkRec.ErrorCode.MissIdent; // TODO {Error = "REPO missing identifier"}; err.Beg = err.End = me.BegLine; me.Errors.Add(err); } // A NAME record is required if (string.IsNullOrWhiteSpace(me.Name)) { UnkRec err = new UnkRec(); err.Error = UnkRec.ErrorCode.MissName; // TODO {Error = "REPO missing identifier"}; err.Beg = err.End = me.BegLine; me.Errors.Add(err); } }
private static void xrefproc(StructParseContext context, int linedex, char level) { var me = (context.Parent as LDSEvent); // TODO copy-pasta from IndiParse string xref; string extra; parseXrefExtra(context.Remain, out xref, out extra); if (string.IsNullOrEmpty(xref)) { UnkRec err = new UnkRec(); err.Error = UnkRec.ErrorCode.UntermIdent; // TODO "Missing/unterminated identifier: " + context.Tag; err.Beg = err.End = context.Begline; context.Record.Errors.Add(err); // TODO is Record only for errors? } else { me.FamilyXref = xref; } }
// Common processing for SUBM, HUSB, WIFE private void xrefProc(ParseContext2 context) { // TODO how are sub-tags handled? E.g. _PREF on HUSB, WIFE string xref = parseForXref(context); var fam = (context.Parent as FamRecord); if (!string.IsNullOrEmpty(xref)) { switch (context.Tag) { case "HUSB": if (fam.Dads.Count != 0) // HUSB already specified { UnkRec err = new UnkRec(); err.Error = UnkRec.ErrorCode.MultHUSB; //"HUSB line used more than once"; err.Beg = err.End = context.Begline + context.Parent.BegLine; fam.Errors.Add(err); } fam.Dads.Add(xref); break; case "WIFE": if (fam.Moms.Count != 0) // WIFE already specified { UnkRec err = new UnkRec(); err.Error = UnkRec.ErrorCode.MultWIFE; //"WIFE line used more than once"; err.Beg = err.End = context.Begline + context.Parent.BegLine; fam.Errors.Add(err); } fam.Moms.Add(xref); break; case "SUBM": fam.FamSubm.Add(xref); // TODO check if xref specified more than once break; } } }
public void CheckRestriction(GEDCommon rec, string restrict) { // Common post-processing restriction checking if (string.IsNullOrWhiteSpace(restrict)) // nothing specified, nothing to do { return; } switch (restrict.ToLowerInvariant()) { case "confidential": case "locked": case "privacy": break; default: UnkRec err = new UnkRec(); err.Error = UnkRec.ErrorCode.InvRestrict; err.Beg = err.End = rec.BegLine; rec.Errors.Add(err); break; } }
public static RepoCit CitParser(ParseContext2 ctx) { RepoCit cit = new RepoCit(); //StructParseContext ctx2 = new StructParseContext(ctx, cit); var ctx2 = PContextFactory.Alloc(ctx, cit); string extra; string xref; parseXrefExtra(ctx.Remain, out xref, out extra); if (string.IsNullOrEmpty(xref)) { cit.Xref = null; } else { cit.Xref = xref; } if (xref != null && (xref.Trim().Length == 0 || cit.Xref.Contains("@"))) // NOTE: missing xref is valid, but NOT empty one! { UnkRec unk = new UnkRec(); unk.Error = UnkRec.ErrorCode.InvXref; ctx.Parent.Errors.Add(unk); // TODO ctx.Parent.Errors.Add(new UnkRec { Error = "Invalid repository citation xref id" }); // TODO not yet reproduced in the field // TODO error line #s } if (!string.IsNullOrEmpty(extra)) { addNote(cit, extra); } StructParse(ctx2, tagDict); ctx.Endline = ctx2.Endline; PContextFactory.Free(ctx2); return(cit); }
// CHIL processing pulled out for _FREL/_MREL private void childProc(ParseContext2 context) { var fam = (context.Parent as FamRecord); LookAhead(context); // Any sub-lines (e.g. _FREL/_MREL)? string xref; string extra; StructParser.parseXrefExtra(context.Remain, out xref, out extra); if (string.IsNullOrEmpty(xref)) { UnkRec err = new UnkRec(); err.Error = UnkRec.ErrorCode.MissIdent; // TODO "Missing/unterminated identifier: " + context.Tag; err.Beg = context.Begline + context.Parent.BegLine; err.End = context.Endline + context.Parent.BegLine; err.Tag = context.Tag; fam.Errors.Add(err); return; } #if XREFTRACK int key = XrefTrack.Instance.StoreXref(xref); #endif foreach (var child in fam.Childs) { #if XREFTRACK if (child.Key == key) #else if (child.Xref == xref) #endif { UnkRec err = new UnkRec(); err.Error = UnkRec.ErrorCode.MultCHIL; // TODO "CHIL ident used more than once (one person cannot be two children)"; err.Beg = context.Begline + context.Parent.BegLine; err.End = context.Endline + context.Parent.BegLine; fam.Errors.Add(err); return; } } string mrel = null; string frel = null; if (context.Endline > context.Begline) { LineUtil.LineData ld = new LineUtil.LineData(); //var gs = new GEDSplitter(); //ParseContext2 ctx = new ParseContext2(); int i = context.Begline + 1; while (i <= context.Endline) { //LineUtil.LevelTagAndRemain(ld, context.Lines.GetLine(i)); context.gs.LevelTagAndRemain(context.Lines.GetLine(i), ld); switch (ld.Tag) { case "_MREL": if (!string.IsNullOrWhiteSpace(ld.Remain)) // FTA expects 'Natural' and I canna see why not && ld.Remain != "Natural") { mrel = ld.Remain; } break; case "_FREL": if (!string.IsNullOrWhiteSpace(ld.Remain)) // FTA expects 'Natural' and I canna see why not && ld.Remain != "Natural") { frel = ld.Remain; } break; case "_PREF": case "_STAT": // TODO temporarily ignore: see 2524482.ged break; default: UnkRec unk = new UnkRec(ld.Tag, i + context.Parent.BegLine, i + context.Parent.BegLine); fam.Unknowns.Add(unk); break; } i++; } //gs = null; } fam.AddChild(xref, frel, mrel); }
private static bool parseName(NameRec rec, char[] line, int linenum, List <UnkRec> errors) { int max = line.Length; // BOULDER_CEM_02212009b.GED had a "1 NAME" with nothing else int startName = LineUtil.FirstChar(line, 0, max); if (startName < 0) { return(false); } // Deal with slashes in the surname int startSur = LineUtil.AllCharsUntil(line, max, startName, '/'); int endSur = LineUtil.ReverseSearch(line, max, startSur + 1, '/'); var suffix = ""; if (endSur + 1 < max) { //suffix = string.Join(" ", line.Substring(endSur + 1).Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)); // Remove extra spaces int newlen = 0; var tmp = LineUtil.RemoveExtraSpaces(line, endSur + 1, max, ref newlen); //suffix = _nameCache.GetFromCache(tmp, 0, newlen).Trim(); // TODO trim suffix = new string(tmp, 0, newlen).Trim(); } { int a = 0; int b = max; if (startSur < max) { a = startName; b = startSur - startName; } int newlen = 0; var tmp = LineUtil.RemoveExtraSpaces(line, a, b, ref newlen); //rec.Names = _nameCache.GetFromCache(tmp, a, newlen).Trim(); // TODO trim rec.Names = new string(tmp, a, newlen).Trim(); } // Observed bug from ege.ged: empty surname was not parsed properly int surnameLen = endSur - startSur - 2; // Will be zero if empty, e.g. "1 NAME Liz //" if (startSur < max && surnameLen > 0) // e.g. "1 NAME LIVING" { //rec.Surname = line.Substring(startSur + 1, endSur - startSur - 1).Trim(); //rec.Surname = _surnameCache.GetFromCache(line, startSur + 1, endSur - startSur - 1).Trim();// TODO trim rec.Surname = new string(line, startSur + 1, endSur - startSur - 1).Trim(); if (rec.Surname.Contains("/")) { UnkRec err = new UnkRec(); err.Beg = err.End = linenum; err.Error = UnkRec.ErrorCode.SlashInName; errors.Add(err); } if (endSur == max && startSur < max) { UnkRec err = new UnkRec(); err.Beg = err.End = linenum; err.Error = UnkRec.ErrorCode.UntermSurname; errors.Add(err); } } if (suffix.Length > 0) { rec.Suffix = suffix; } return(true); }
protected static void StructParse(StructParseContext ctx, Dictionary <string, TagProc> tagSet) { LineUtil.LineData ld = new LineUtil.LineData(); //GEDSplitter gs = new GEDSplitter(); int i = ctx.Begline + 1; int max = ctx.Lines.Max; for (; i < max; i++) { try { ctx.gs.LevelTagAndRemain(ctx.Lines.GetLine(i), ld); //LineUtil.LevelTagAndRemain(ld, ctx.Lines.GetLine(i)); } catch (Exception) { UnkRec exc = new UnkRec(); exc.Beg = exc.End = i; exc.Error = UnkRec.ErrorCode.Exception; // TODO exc.Error = "Exception during parse, skipping line"; ctx.Record.Errors.Add(exc); // TODO is Record only for errors? continue; } if (ld.Level <= ctx.Level) { break; // end of sub-record } ctx.Remain1 = ld.Remain1; if (ld.Tag == null) { UnkRec exc = new UnkRec(); exc.Beg = exc.End = i; exc.Error = UnkRec.ErrorCode.MissTag; // TODO exc.Error = "Exception during parse, skipping line"; // TODO not exception - missing tag / invalid linebreak ctx.Record.Errors.Add(exc); // TODO is Record only for errors? continue; } TagProc tagproc; if (tagSet.TryGetValue(ld.Tag, out tagproc)) { ctx.Begline = i; ctx.Tag = ld.Tag; tagproc(ctx, i, ld.Level); } else { LineSet extra = new LineSet(); char oldLevel = ctx.Level; ctx.Begline = i; ctx.Level = ld.Level; GedRecParse.LookAhead(ctx); extra.Beg = ctx.Begline + ctx.Lines.Beg; // Make line #s relative to file extra.End = ctx.Endline + ctx.Lines.Beg; ctx.Parent.OtherLines.Add(extra); ctx.Level = oldLevel; } i = Math.Max(ctx.Endline, i); // HACK: extendedText() may have advanced ctx.Endline further } ctx.Endline = i - 1; ld = null; //gs = null; }