Skip to content

Commit 9f4a532

Browse files
authored
LT-18767 yellow box crash in HC for bad XAmple-style reduplication (#381)
* LT-18767 yellow box crash in HC for bad XAmple-style reduplication
1 parent 44071d6 commit 9f4a532

File tree

6 files changed

+97
-9
lines changed

6 files changed

+97
-9
lines changed

Src/GenerateHCConfig/ConsoleLogger.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,5 +118,10 @@ public void OutOfScopeSlot(IMoInflAffixSlot slot, IMoInflAffixTemplate template,
118118
{
119119
Console.WriteLine(reason);
120120
}
121+
122+
void IHCLoadErrorLogger.UnmatchedReduplicationIndexedClass(IMoForm form, string reason, string environment)
123+
{
124+
throw new NotImplementedException();
125+
}
121126
}
122127
}

Src/LexText/ParserCore/HCLoader.cs

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1471,16 +1471,17 @@ private AffixProcessAllomorph LoadFormAffixProcessAllomorph(IMoForm allo, IPhEnv
14711471
case MoMorphTypeTags.kMorphSuffixingInterfix:
14721472
case MoMorphTypeTags.kMorphEnclitic:
14731473
hcAllo.Lhs.Add(stemPattern);
1474-
hcAllo.Lhs.AddRange(LoadReduplicationPatterns(contexts.Item1));
1474+
var lhsPatterns = LoadReduplicationPatterns(contexts.Item1);
1475+
hcAllo.Lhs.AddRange(lhsPatterns);
14751476
var suffixNull = new Pattern<Word, ShapeNode>("suffixNull", SuffixNull());
14761477
suffixNull.Freeze();
14771478
hcAllo.Lhs.Add(suffixNull);
14781479

14791480
hcAllo.Rhs.Add(new CopyFromInput("stem"));
1480-
hcAllo.Rhs.AddRange(LoadReduplicationOutputActions(contexts.Item1));
1481+
hcAllo.Rhs.AddRange(LoadReduplicationOutputActions(contexts.Item1, lhsPatterns, allo));
14811482
hcAllo.Rhs.Add(new CopyFromInput("suffixNull"));
14821483
hcAllo.Rhs.Add(new InsertSegments(Segments("+")));
1483-
hcAllo.Rhs.AddRange(LoadReduplicationOutputActions(form));
1484+
hcAllo.Rhs.AddRange(LoadReduplicationOutputActions(form, lhsPatterns, allo));
14841485
break;
14851486

14861487
case MoMorphTypeTags.kMorphPrefix:
@@ -1489,13 +1490,14 @@ private AffixProcessAllomorph LoadFormAffixProcessAllomorph(IMoForm allo, IPhEnv
14891490
var prefixNull = new Pattern<Word, ShapeNode>("prefixNull", PrefixNull());
14901491
prefixNull.Freeze();
14911492
hcAllo.Lhs.Add(prefixNull);
1492-
hcAllo.Lhs.AddRange(LoadReduplicationPatterns(contexts.Item2));
1493+
lhsPatterns = LoadReduplicationPatterns(contexts.Item2);
1494+
hcAllo.Lhs.AddRange(lhsPatterns);
14931495
hcAllo.Lhs.Add(stemPattern);
14941496

1495-
hcAllo.Rhs.AddRange(LoadReduplicationOutputActions(form));
1497+
hcAllo.Rhs.AddRange(LoadReduplicationOutputActions(form, lhsPatterns, allo));
14961498
hcAllo.Rhs.Add(new InsertSegments(Segments("+")));
14971499
hcAllo.Rhs.Add(new CopyFromInput("prefixNull"));
1498-
hcAllo.Rhs.AddRange(LoadReduplicationOutputActions(contexts.Item2));
1500+
hcAllo.Rhs.AddRange(LoadReduplicationOutputActions(contexts.Item2, lhsPatterns, allo));
14991501
hcAllo.Rhs.Add(new CopyFromInput("stem"));
15001502
break;
15011503
}
@@ -1611,13 +1613,38 @@ private IEnumerable<Pattern<Word, ShapeNode>> LoadReduplicationPatterns(string p
16111613
}
16121614
}
16131615

1614-
private IEnumerable<MorphologicalOutputAction> LoadReduplicationOutputActions(string patternStr)
1616+
private IEnumerable<MorphologicalOutputAction> LoadReduplicationOutputActions(string patternStr, IEnumerable<Pattern<Word, ShapeNode>> patterns, IMoForm form)
16151617
{
16161618
foreach (string token in TokenizeContext(patternStr))
16171619
{
16181620
if (token.StartsWith("["))
16191621
{
1620-
yield return new CopyFromInput(XmlConvert.EncodeName(token.Substring(1, token.Length - 2).Trim()));
1622+
bool isValid = true;
1623+
if (token.Contains("^"))
1624+
{
1625+
// The ^ gets replaced by _x005E_ so we need to do it here to match in patterns
1626+
string indexedToken = token.Substring(1, token.Length - 2).Trim().Replace("^", "_x005E_");
1627+
isValid = patterns.Any(p => p.Name == indexedToken);
1628+
if (!isValid)
1629+
{
1630+
// add error message to logger
1631+
string envs = "";
1632+
var environments = form.AllomorphEnvironments;
1633+
if (environments != null)
1634+
{
1635+
StringBuilder sb = new StringBuilder();
1636+
foreach (IPhEnvironment env in environments)
1637+
{
1638+
sb.Append(env.ShortName);
1639+
sb.Append(" ");
1640+
}
1641+
envs = sb.ToString();
1642+
}
1643+
m_logger.UnmatchedReduplicationIndexedClass(form, "Ill-formed index:" + token, envs);
1644+
}
1645+
}
1646+
if (isValid)
1647+
yield return new CopyFromInput(XmlConvert.EncodeName(token.Substring(1, token.Length - 2).Trim()));
16211648
}
16221649
else
16231650
{

Src/LexText/ParserCore/HCParser.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,16 @@ public void OutOfScopeSlot(IMoInflAffixSlot slot, IMoInflAffixTemplate template,
669669
m_xmlWriter.WriteElementString("Reason", reason);
670670
m_xmlWriter.WriteEndElement();
671671
}
672+
public void UnmatchedReduplicationIndexedClass(IMoForm form, string reason, string pattern)
673+
{
674+
m_xmlWriter.WriteStartElement("LoadError");
675+
m_xmlWriter.WriteAttributeString("type", "unmatched-redup-indexed-class");
676+
m_xmlWriter.WriteElementString("Form", form.Form.VernacularDefaultWritingSystem.Text);
677+
m_xmlWriter.WriteElementString("Pattern", pattern);
678+
m_xmlWriter.WriteElementString("Reason", reason);
679+
m_xmlWriter.WriteElementString("Hvo", form.Hvo.ToString(CultureInfo.InvariantCulture));
680+
m_xmlWriter.WriteEndElement();
681+
}
672682
}
673683
}
674684
}

Src/LexText/ParserCore/IHCLoadErrorLogger.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@ public interface IHCLoadErrorLogger
1313
void InvalidRewriteRule(IPhRegularRule prule, string reason);
1414
void InvalidStrata(string strata, string reason);
1515
void OutOfScopeSlot(IMoInflAffixSlot slot, IMoInflAffixTemplate template, string reason);
16+
void UnmatchedReduplicationIndexedClass(IMoForm form, string reason, string environment);
1617
}
1718
}

Src/LexText/ParserCore/ParserCoreTests/HCLoaderTests.cs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ private enum LoadErrorType
4343
InvalidEnvironment,
4444
InvalidRedupForm,
4545
InvalidRewriteRule,
46-
InvalidStrata
46+
InvalidStrata,
47+
UnmatchedReduplicationIndexedClass
4748
}
4849

4950
private class TestHCLoadErrorLogger : IHCLoadErrorLogger
@@ -99,6 +100,11 @@ public void OutOfScopeSlot(IMoInflAffixSlot slot, IMoInflAffixTemplate template,
99100
{
100101
throw new NotImplementedException();
101102
}
103+
public void UnmatchedReduplicationIndexedClass(IMoForm form, string reason, string patterns)
104+
{
105+
m_loadErrors.Add(Tuple.Create(LoadErrorType.UnmatchedReduplicationIndexedClass, (ICmObject)form));
106+
}
107+
102108
}
103109

104110
private readonly List<Tuple<LoadErrorType, ICmObject>> m_loadErrors = new List<Tuple<LoadErrorType, ICmObject>>();
@@ -596,6 +602,30 @@ public void InvalidPartialReduplicationEnvironment()
596602
LoadLanguage();
597603

598604
Assert.That(m_lang.Strata[0].MorphologicalRules.Count, Is.EqualTo(0));
605+
606+
// now check for missing indexed class which is removed but with an logged error message
607+
// LT-18767
608+
// case 1: the form has the indexed class, but the environment does not
609+
var env = allo.PhoneEnvRC.ElementAt(0);
610+
allo.PhoneEnvRC.Remove(env);
611+
allo.PhoneEnvRC.Add(AddEnvironment("/_[C^1]"));
612+
LoadLanguage();
613+
614+
Assert.That(m_lang.Strata[0].MorphologicalRules.Count, Is.EqualTo(1));
615+
Assert.That(m_loadErrors.Count == 1);
616+
var err = m_loadErrors.ElementAt(0);
617+
Assert.That(err.Item1 == LoadErrorType.UnmatchedReduplicationIndexedClass);
618+
619+
// case 2: the environment has the indexed class, but the form does not
620+
env = allo.PhoneEnvRC.ElementAt(0);
621+
allo.PhoneEnvRC.Remove(env);
622+
allo.PhoneEnvRC.Add(AddEnvironment("/_[C^2][V^1]"));
623+
LoadLanguage();
624+
625+
Assert.That(m_lang.Strata[0].MorphologicalRules.Count, Is.EqualTo(1));
626+
Assert.That(m_loadErrors.Count == 1);
627+
err = m_loadErrors.ElementAt(0);
628+
Assert.That(err.Item1 == LoadErrorType.UnmatchedReduplicationIndexedClass);
599629
}
600630

601631
[Test]

Src/Transforms/Presentation/FormatCommon.xsl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,21 @@
127127
<xsl:text> </xsl:text>
128128
</li>
129129
</xsl:when>
130+
<xsl:when test="@type = 'unmatched-redup-indexed-class'">
131+
<li>
132+
<xsl:text>The reduplication form "</xsl:text>
133+
<xsl:value-of select="Form" />
134+
<xsl:text>" is invalid. Reason: </xsl:text>
135+
<xsl:value-of select="Reason" />
136+
<xsl:text> </xsl:text>
137+
<span style="cursor:pointer; text-decoration:underline">
138+
<xsl:attribute name="id">
139+
<xsl:value-of select="Hvo"/>
140+
</xsl:attribute>
141+
<xsl:text>(Click here to see the entry.)</xsl:text>
142+
</span>
143+
</li>
144+
</xsl:when>
130145
<xsl:otherwise>
131146
<!-- Do not expect any others to happen, but just in case, we show them in all their HC glory -->
132147
<li><xsl:value-of select="."/></li>

0 commit comments

Comments
 (0)