From eec842e863901f607d7e34018163cb9737e46429 Mon Sep 17 00:00:00 2001 From: Andy Black Date: Thu, 9 Jul 2026 12:24:14 -0700 Subject: [PATCH 1/2] LT-22607 TonePars use XAmpleParser code for result processing Change-Id: Id4eabbcd70df8b594d26ee2fba777783f518f070 --- Src/LexText/ParserCore/XAmpleParser.cs | 7 + .../ToneParsFLExDll/ToneParsFLExForm.cs | 6 +- .../ToneParsFLExDll/ToneParsInvoker.cs | 180 +----------------- 3 files changed, 21 insertions(+), 172 deletions(-) diff --git a/Src/LexText/ParserCore/XAmpleParser.cs b/Src/LexText/ParserCore/XAmpleParser.cs index 57bde6cbe2..dd432ac8f3 100644 --- a/Src/LexText/ParserCore/XAmpleParser.cs +++ b/Src/LexText/ParserCore/XAmpleParser.cs @@ -169,6 +169,13 @@ public ParseResult ParseWord(string word) CheckDisposed(); var results = new StringBuilder(m_xample.ParseWord(word)); + ParseResult result = ProcessParseResults(ref results); + + return result; + } + + public ParseResult ProcessParseResults(ref StringBuilder results) + { results = results.Replace("DB_REF_HERE", "'0'"); results = results.Replace("<...>", "[...]"); var wordformElem = XElement.Parse(results.ToString()); diff --git a/Src/Utilities/pcpatrflex/ToneParsFLExDll/ToneParsFLExForm.cs b/Src/Utilities/pcpatrflex/ToneParsFLExDll/ToneParsFLExForm.cs index 7495ff65cd..17e6a5536c 100644 --- a/Src/Utilities/pcpatrflex/ToneParsFLExDll/ToneParsFLExForm.cs +++ b/Src/Utilities/pcpatrflex/ToneParsFLExDll/ToneParsFLExForm.cs @@ -481,7 +481,8 @@ private void InvokeToneParser(string inputFile) tbIntxCtlFile.Text, inputFile, GetDecompSeparationCharacter(), - Cache + Cache, + m_XAmpleParser ); invoker.Extractor = Extractor; invoker.ParsingStatus = lblParsingStatus; @@ -786,7 +787,8 @@ private void ShowLog_Click(object sender, EventArgs e) tbIntxCtlFile.Text, "", ' ', - Cache + Cache, + m_XAmpleParser ); if (File.Exists(invoker.ToneParsLogFile)) { diff --git a/Src/Utilities/pcpatrflex/ToneParsFLExDll/ToneParsInvoker.cs b/Src/Utilities/pcpatrflex/ToneParsFLExDll/ToneParsInvoker.cs index 5785886240..b97d676cee 100644 --- a/Src/Utilities/pcpatrflex/ToneParsFLExDll/ToneParsInvoker.cs +++ b/Src/Utilities/pcpatrflex/ToneParsFLExDll/ToneParsInvoker.cs @@ -56,13 +56,15 @@ public class ToneParsInvoker public const string kTPLexicon = "TPlex.txt"; public FLExDBExtractor Extractor { get; set; } + protected XAmpleParser XAmpleParser { get; set; } public ToneParsInvoker( string toneParsRuleFile, string intxCtlFile, string inputFile, char decomp, - LcmCache cache + LcmCache cache, + XAmpleParser xAmpleParser ) { ToneParsRuleFile = toneParsRuleFile; @@ -73,6 +75,11 @@ LcmCache cache DatabaseName = ConvertNameToUseAnsiCharacters(cache.ProjectId.Name); InitFileNames(); Queue = new IdleQueue { IsPaused = true }; + XAmpleParser = xAmpleParser; + if ( XAmpleParser == null ) + { + XAmpleParser = new XAmpleParser(Cache, null); + } } private void InitFileNames() @@ -684,9 +691,8 @@ public void SaveResultsInDatabase() IWfiWordform thiswf = GetWordformFromString(wordform); if (thiswf != null) { - var parseResult = ConvertParserFilerResultXmlToParseResult( - ParserFilerXMLString - ); + var sb = new StringBuilder(ParserFilerXMLString); + var parseResult = XAmpleParser.ProcessParseResults(ref sb); m_parseFiler.ProcessParse(thiswf, ParserPriority.Low, parseResult); } i++; @@ -724,171 +730,5 @@ protected void ExecuteIdleQueue(IdleQueue idleQueue) task.Delegate(task.Parameter); idleQueue.Clear(); } - - //----------------------- - // ConvertParserFilerResultXmlToParseResult(), TryCreateParseMorph(), and ProcessMsaHvo() are from XAmpleParser.cs - // (I renamed ParseWord() to ConvertParserFilerResultXmlToParseResult() to avoid confusion.) - // Ideally, we'd expose them from XAmpleParser.cs - public ParseResult ConvertParserFilerResultXmlToParseResult(string results) - { - //TODO: fix! CheckDisposed(); - results = results.Replace("DB_REF_HERE", "'0'"); - results = results.Replace("<...>", "[...]"); - var wordformElem = XElement.Parse(results.ToString()); - string errorMessage = null; - var exceptionElem = wordformElem.Element("Exception"); - if (exceptionElem != null) - { - var totalAnalysesValue = (string)exceptionElem.Attribute("totalAnalyses"); - switch ((string)exceptionElem.Attribute("code")) - { - case "ReachedMaxAnalyses": - errorMessage = String.Format( - "Maximum permitted analyses ({0}) reached." /*ParserCoreStrings.ksReachedMaxAnalysesAllowed*/ - , - totalAnalysesValue - ); - break; - case "ReachedMaxBufferSize": - errorMessage = String.Format( - "Maximum internal buffer size ({0}) reached." /*ParserCoreStrings.ksReachedMaxInternalBufferSize*/ - , - totalAnalysesValue - ); - break; - } - } - else - { - errorMessage = (string)wordformElem.Element("Error"); - } - - ParseResult result; - using ( - new WorkerThreadReadHelper( - Cache.ServiceLocator.GetInstance() - ) - ) - { - var analyses = new List(); - foreach (XElement analysisElem in wordformElem.Descendants("WfiAnalysis")) - { - var morphs = new List(); - bool skip = false; - foreach (XElement morphElem in analysisElem.Descendants("Morph")) - { - ParseMorph morph; - if (!TryCreateParseMorph(Cache, morphElem, out morph)) - { - skip = true; - break; - } - if (morph != null) - morphs.Add(morph); - } - - if (!skip && morphs.Count > 0) - analyses.Add(new ParseAnalysis(morphs)); - } - result = new ParseResult(analyses, errorMessage); - } - - return result; - } - - private static bool TryCreateParseMorph( - LcmCache cache, - XElement morphElem, - out ParseMorph morph - ) - { - XElement formElement = morphElem.Element("MoForm"); - Debug.Assert(formElement != null); - var formHvo = (string)formElement.Attribute("DbRef"); - - XElement msiElement = morphElem.Element("MSI"); - Debug.Assert(msiElement != null); - var msaHvo = (string)msiElement.Attribute("DbRef"); - - // Normally, the hvo for MoForm is a MoForm and the hvo for MSI is an MSA - // There are four exceptions, though, when an irregularly inflected form is involved: - // 1. () - .TryGetObject(int.Parse(formHvo), out objForm) - ) - { - morph = null; - return false; - } - var form = objForm as IMoForm; - if (form == null) - { - morph = null; - return true; - } - - // Irregulary inflected forms can have a combination MSA hvo: the LexEntry hvo, a period, and an index to the LexEntryRef - Tuple msaTuple = ProcessMsaHvo(msaHvo); - ICmObject objMsa; - if ( - !cache.ServiceLocator - .GetInstance() - .TryGetObject(msaTuple.Item1, out objMsa) - ) - { - morph = null; - return false; - } - var msa = objMsa as IMoMorphSynAnalysis; - if (msa != null) - { - morph = new ParseMorph(form, msa); - return true; - } - - var msaAsLexEntry = objMsa as ILexEntry; - if (msaAsLexEntry != null) - { - // is an irregularly inflected form - // get the MoStemMsa of its variant - if (msaAsLexEntry.EntryRefsOS.Count > 0) - { - ILexEntryRef lexEntryRef = msaAsLexEntry.EntryRefsOS[msaTuple.Item2]; - ILexSense sense = MorphServices.GetMainOrFirstSenseOfVariant(lexEntryRef); - var inflType = lexEntryRef.VariantEntryTypesRS[0] as ILexEntryInflType; - morph = new ParseMorph(form, sense.MorphoSyntaxAnalysisRA, inflType); - return true; - } - } - - // if it is anything else, we ignore it - morph = null; - return true; - } - - private static Tuple ProcessMsaHvo(string msaHvo) - { - string[] msaHvoParts = msaHvo.Split('.'); - return Tuple.Create( - int.Parse(msaHvoParts[0]), - msaHvoParts.Length == 2 ? int.Parse(msaHvoParts[1]) : 0 - ); - } - // ----------------------- } } From 7251cf8d6a1992a1fd903abea15eb571f524648d Mon Sep 17 00:00:00 2001 From: Andy Black Date: Thu, 9 Jul 2026 12:30:11 -0700 Subject: [PATCH 2/2] Add ToneParsInvoker test fix Change-Id: I89db58bf48ffb14b8c8edcaed8ae26549a7a522a --- .../DisambiguateInFLExDBTests/ToneParsInvokerTests.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Src/Utilities/pcpatrflex/DisambiguateInFLExDB/DisambiguateInFLExDBTests/ToneParsInvokerTests.cs b/Src/Utilities/pcpatrflex/DisambiguateInFLExDB/DisambiguateInFLExDBTests/ToneParsInvokerTests.cs index cd171ab425..762362eb38 100644 --- a/Src/Utilities/pcpatrflex/DisambiguateInFLExDB/DisambiguateInFLExDBTests/ToneParsInvokerTests.cs +++ b/Src/Utilities/pcpatrflex/DisambiguateInFLExDB/DisambiguateInFLExDBTests/ToneParsInvokerTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2019 SIL International +// Copyright (c) 2019 SIL International // This software is licensed under the LGPL, version 2.1 or later // (http://www.gnu.org/licenses/lgpl-2.1.html) @@ -6,6 +6,7 @@ using PtxUtils; using SIL.DisambiguateInFLExDB; using SIL.FieldWorks.Common.FwUtils; +using SIL.FieldWorks.WordWorks.Parser; using SIL.LCModel; using SIL.ToneParsFLEx; using System; @@ -117,7 +118,8 @@ public void ToneParsInvokerTest() string toneParsRuleFile = Path.Combine(TestDataDir, "KvgTP.ctl"); string intxCtlFile = Path.Combine(TestDataDir, "KVGintx.ctl"); string inputFile = Path.Combine(TestDataDir, "KVGinput.txt"); - invoker = new ToneParsInvoker(toneParsRuleFile, intxCtlFile, inputFile, '+', MyCache); + XAmpleParser xampleParser = new XAmpleParser(MyCache, null); + invoker = new ToneParsInvoker(toneParsRuleFile, intxCtlFile, inputFile, '+', MyCache, xampleParser); CreateExpectedFileStrings(); File.Copy(Path.Combine(TestDataDir, "ToneParsInvoker.ana"), Path.Combine(Path.GetTempPath(), "ToneParsInvoker.ana"), true); ToneParsInvokerOptions.Instance.VerifyInformation = true;