Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion Src/LexText/ParserCore/HCLoader.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2015-2023 SIL International
// Copyright (c) 2015-2025 SIL International
// This software is licensed under the LGPL, version 2.1 or later
// (http://www.gnu.org/licenses/lgpl-2.1.html)

Expand Down Expand Up @@ -58,6 +58,7 @@ public static Language Load(LcmCache cache, IHCLoadErrorLogger logger)
private readonly Dictionary<string, IPhNaturalClass> m_naturalClassLookup;
private readonly Dictionary<IPhNaturalClass, NaturalClass> m_naturalClasses;
private readonly Dictionary<IPhTerminalUnit, CharacterDefinition> m_charDefs;
private readonly Dictionary<string, int> m_CompoundRuleLookup;

private readonly bool m_noDefaultCompounding;
private readonly bool m_notOnClitics;
Expand Down Expand Up @@ -98,6 +99,17 @@ private HCLoader(LcmCache cache, IHCLoadErrorLogger logger)
m_strataString = (string)hcElem.Element("Strata");
m_strata = ParseStrataString(m_strataString);
}
m_CompoundRuleLookup = new Dictionary<string, int>();
XElement cRulesEelem = parserParamsElem.Element("CompoundRules");
if (cRulesEelem != null)
{
foreach (var cRule in cRulesEelem.Elements())
{
int maxApps = Int32.Parse(cRule.Attribute("maxApps").Value);
m_CompoundRuleLookup[cRule.Attribute("guid").Value] = maxApps;
}
}

m_entryName = new Dictionary<LexEntry, string>();

m_naturalClasses = new Dictionary<IPhNaturalClass, NaturalClass>();
Expand Down Expand Up @@ -1862,6 +1874,10 @@ private CompoundingRule LoadEndoCompoundingRule(IMoEndoCompound compoundRule)
Properties = { { HCParser.CRuleID, compoundRule.Hvo } }
};

int maxApps = 1;
if (m_CompoundRuleLookup.TryGetValue(compoundRule.Guid.ToString(), out maxApps))
hcCompoundRule.MaxApplicationCount = maxApps;

var subrule = new CompoundingSubrule();

if (compoundRule.OverridingMsaOA.InflectionClassRA != null)
Expand Down
9 changes: 8 additions & 1 deletion Src/LexText/ParserCore/HCParser.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2014-2021 SIL International
// Copyright (c) 2014-2025 SIL International
// This software is licensed under the LGPL, version 2.1 or later
// (http://www.gnu.org/licenses/lgpl-2.1.html)

Expand Down Expand Up @@ -143,6 +143,9 @@ private void LoadParser()
m_morpher = null;

int delReapps = 0;
// For Hermit Crab, the maximum number of roots/stems allowed is between one and ten.
// The default is two in order to allow for compounding (which requires there be at least two roots/stems).
int maxStemCount = 2;
string loadErrorsFile = Path.Combine(m_outputDirectory, m_cache.ProjectId.Name + "HCLoadErrors.xml");
using (XmlWriter writer = XmlWriter.Create(loadErrorsFile))
using (new WorkerThreadReadHelper(m_cache.ServiceLocator.GetInstance<IWorkerThreadReadHandler>()))
Expand All @@ -153,12 +156,16 @@ private void LoadParser()
XElement parserParamsElem = XElement.Parse(m_cache.LanguageProject.MorphologicalDataOA.ParserParameters);
XElement delReappsElem = parserParamsElem.Elements("HC").Elements("DelReapps").FirstOrDefault();
XElement guessRootsElem = parserParamsElem.Elements("HC").Elements("GuessRoots").FirstOrDefault();
XElement maxRootsElem = parserParamsElem.Elements("HC").Elements("MaxRoots").FirstOrDefault();
if (delReappsElem != null)
delReapps = (int) delReappsElem;
if (guessRootsElem != null)
m_guessRoots = (bool) guessRootsElem;
if (maxRootsElem != null)
maxStemCount = int.Parse(maxRootsElem.Value);
}
m_morpher = new Morpher(m_traceManager, m_language) { DeletionReapplications = delReapps };
m_morpher.MaxStemCount = maxStemCount;
}

private XDocument ParseToXml(string form, bool tracing, IEnumerable<int> selectTraceMorphs)
Expand Down
116 changes: 116 additions & 0 deletions Src/LexText/ParserUI/HCMaxCompoundRulesDlg.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

179 changes: 179 additions & 0 deletions Src/LexText/ParserUI/HCMaxCompoundRulesDlg.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
// Copyright (c) 2025 SIL International
// This software is licensed under the LGPL, version 2.1 or later
// (http://www.gnu.org/licenses/lgpl-2.1.html)
using SIL.LCModel;
using System;
using System.Data;
using System.Linq;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;
using DataGrid = System.Windows.Forms.DataGrid;
using TextBox = System.Windows.Forms.TextBox;

namespace SIL.FieldWorks.LexText.Controls
{
public partial class HCMaxCompoundRulesDlg : ParserParametersBase
{
private const string m_Name = "Name";
private const string m_Description = "Description";
private const string m_MaxApps = "MaxApps";
private const string m_Guid = "Guid";
private const string m_CompoundRules = "CompoundRules";
private XElement m_ParserParametersElem;

private DataGrid m_dataGrid;
private DataSet m_dsCompoundRules;

public HCMaxCompoundRulesDlg()
{
InitializeComponent();
}

/// <summary>
/// Set up the dlg in preparation to showing it.
/// </summary>
public void SetDlgInfo(string title, string parserParameters, ILcmOwningSequence<IMoCompoundRule> compoundRules)
{
CheckDisposed();

XmlRep = parserParameters;
m_ParserParametersElem = XElement.Parse(parserParameters);
Text = title;

m_dsCompoundRules = new DataSet { DataSetName = m_CompoundRules };

DataTable tblCompoundRules = new DataTable();
tblCompoundRules.TableName = m_CompoundRules;
tblCompoundRules.Columns.Add(m_Name, typeof(string));
tblCompoundRules.Columns.Add(m_Description, typeof(string));
tblCompoundRules.Columns.Add(m_MaxApps, typeof(int));
tblCompoundRules.Columns.Add(m_Guid, typeof(string));
tblCompoundRules.Columns[0].ReadOnly = true;
tblCompoundRules.Columns[1].ReadOnly = true;
tblCompoundRules.Columns[3].ReadOnly = true;
m_dsCompoundRules.Tables.Add(tblCompoundRules);

XElement cRules = new XElement(m_CompoundRules);
foreach (IMoCompoundRule rule in compoundRules)
{
var name = new XElement(m_Name, rule.Name.BestAnalysisAlternative.Text);
var description = new XElement(m_Description, rule.Description.BestAnalysisAlternative.Text);
var sGuid = rule.Guid.ToString();
string sMaxApps = getMaxAppsFromParameters(sGuid);
var maxApps = new XElement(m_MaxApps, sMaxApps);
var guid = new XElement(m_Guid, sGuid);
cRules.Add(name, description, maxApps, guid);
using (XmlReader reader = cRules.CreateReader())
m_dsCompoundRules.ReadXml(reader, XmlReadMode.IgnoreSchema);
cRules.RemoveAll();
}

m_dataGrid.SetDataBinding(m_dsCompoundRules, m_CompoundRules);
DataView view = CreateDataView(m_dsCompoundRules.Tables[m_CompoundRules]);
m_dataGrid.DataSource = view;
m_dataGrid.TableStyles.Add(new DataGridTableStyle { MappingName = m_CompoundRules, RowHeadersVisible = false, AllowSorting = false });
foreach (DataGridTextBoxColumn col in m_dataGrid.TableStyles[0].GridColumnStyles.OfType<DataGridTextBoxColumn>())
{
TextBox textBox1 = col.TextBox;
textBox1.Multiline = true;
textBox1.ScrollBars = ScrollBars.Vertical;
textBox1.WordWrap = true;
m_dataGrid.TableStyles[0].PreferredRowHeight = 25;
}

m_dataGrid.TableStyles[0].GridColumnStyles[0].Width = 200;
m_dataGrid.TableStyles[0].GridColumnStyles[1].Width = 250;
m_dataGrid.TableStyles[0].GridColumnStyles[3].Width = 0;
}

private string getMaxAppsFromParameters(string sGuid)
{
var sMaxApps = "1";
var ruleElem = m_ParserParametersElem.XPathSelectElement("//CompoundRule[@guid='" + sGuid + "']");
if (ruleElem != null)
{
var aMaxApps = ruleElem.Attribute("maxApps");
if (aMaxApps != null)
{
sMaxApps = aMaxApps.Value;
}
}
return sMaxApps;
}

private DataView CreateDataView(DataTable table)
{
return new DataView(table) { AllowNew = false };
}

private void btnOK_Click(object sender, EventArgs e)
{
XElement compoundRulesTopElem = XElement.Parse(m_dsCompoundRules.GetXml());
ValidateValues(compoundRulesTopElem);
XElement oldParserParamsElem = XElement.Parse(XmlRep);
oldParserParamsElem.Element(m_CompoundRules)?.Remove();
// Rework compound rules to show just GUID and max apps
var cRulesElem = CreateCompoundRulesElementToStore(compoundRulesTopElem);
oldParserParamsElem.Add(cRulesElem);
XmlRep = oldParserParamsElem.ToString();
}

private void ValidateValues(XElement elem)
{
var rulesElem = elem.XPathSelectElements(m_CompoundRules);
foreach (var rule in rulesElem)
{
EnforceValidValue(rule, m_MaxApps, 1, 9, true);
}
}

private XElement CreateCompoundRulesElementToStore(XElement elem)
{
XElement cRulesElem = new XElement(m_CompoundRules);
var rulesElem = elem.XPathSelectElements(m_CompoundRules);
foreach (var rule in rulesElem)
{
var sMaxApps = rule.Element(m_MaxApps).Value;
if (sMaxApps != "1")
{
var sGuid = rule.Element(m_Guid).Value;
XElement cRule = new XElement("CompoundRule");
XAttribute guid = new XAttribute("guid", sGuid);
XAttribute maxApps = new XAttribute("maxApps", sMaxApps);
cRule.Add(guid, maxApps);
cRulesElem.Add(cRule);
}
}
return cRulesElem;
}

private void btnHelp_Click(object sender, EventArgs e)
{
MessageBox.Show("Help clicked");
}

protected void EnforceValidValue(XElement elem, string item, int min, int max, bool useMinIfZero)
{
XElement valueElem = elem.Elements(item).FirstOrDefault();
if (valueElem != null)
{
var val = (int)valueElem;
if (val < min || (useMinIfZero && val == 0))
{
valueElem.SetValue(min);
XmlRep = elem.ToString();
ReportChangeOfValue(item, val, min, min, max);
}
else if (val > max)
{
valueElem.SetValue(max);
XmlRep = elem.ToString();
ReportChangeOfValue(item, val, max, min, max);
}
}
}

}
}
Loading
Loading