Skip to content

Commit 8c8b962

Browse files
authored
Merge pull request #106 from linksplatform/issue-105-b29688eb
Fix C# parser to handle indented ID syntax - Fixes #105
2 parents a2cee22 + 58b6a1c commit 8c8b962

File tree

10 files changed

+675
-21
lines changed

10 files changed

+675
-21
lines changed
Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
using System;
2+
using Xunit;
3+
4+
namespace Platform.Protocols.Lino.Tests
5+
{
6+
public static class MixedIndentationModesTests
7+
{
8+
[Fact]
9+
public static void HeroExampleMixedModesTest()
10+
{
11+
var input = @"empInfo
12+
employees:
13+
(
14+
name (James Kirk)
15+
age 40
16+
)
17+
(
18+
name (Jean-Luc Picard)
19+
age 45
20+
)
21+
(
22+
name (Wesley Crusher)
23+
age 27
24+
)";
25+
26+
var parser = new Parser();
27+
var result = parser.Parse(input);
28+
29+
Assert.NotEmpty(result);
30+
var formatted = result.Format();
31+
Assert.Contains("empInfo", formatted);
32+
Assert.Contains("employees", formatted);
33+
Assert.Contains("James Kirk", formatted);
34+
Assert.Contains("Jean-Luc Picard", formatted);
35+
Assert.Contains("Wesley Crusher", formatted);
36+
}
37+
38+
[Fact]
39+
public static void HeroExampleAlternativeFormatTest()
40+
{
41+
var input = @"empInfo
42+
(
43+
employees:
44+
(
45+
name (James Kirk)
46+
age 40
47+
)
48+
(
49+
name (Jean-Luc Picard)
50+
age 45
51+
)
52+
(
53+
name (Wesley Crusher)
54+
age 27
55+
)
56+
)";
57+
58+
var parser = new Parser();
59+
var result = parser.Parse(input);
60+
61+
Assert.NotEmpty(result);
62+
var formatted = result.Format();
63+
Assert.Contains("empInfo", formatted);
64+
Assert.Contains("employees:", formatted);
65+
Assert.Contains("James Kirk", formatted);
66+
Assert.Contains("Jean-Luc Picard", formatted);
67+
Assert.Contains("Wesley Crusher", formatted);
68+
}
69+
70+
[Fact]
71+
public static void HeroExampleEquivalenceTest()
72+
{
73+
var version1 = @"empInfo
74+
employees:
75+
(
76+
name (James Kirk)
77+
age 40
78+
)
79+
(
80+
name (Jean-Luc Picard)
81+
age 45
82+
)
83+
(
84+
name (Wesley Crusher)
85+
age 27
86+
)";
87+
88+
var version2 = @"empInfo
89+
(
90+
employees:
91+
(
92+
name (James Kirk)
93+
age 40
94+
)
95+
(
96+
name (Jean-Luc Picard)
97+
age 45
98+
)
99+
(
100+
name (Wesley Crusher)
101+
age 27
102+
)
103+
)";
104+
105+
var parser = new Parser();
106+
var result1 = parser.Parse(version1);
107+
var result2 = parser.Parse(version2);
108+
109+
Assert.NotEmpty(result1);
110+
Assert.NotEmpty(result2);
111+
112+
var formatted1 = result1.Format();
113+
var formatted2 = result2.Format();
114+
115+
Assert.Equal(formatted1, formatted2);
116+
}
117+
118+
[Fact]
119+
public static void SetContextWithoutColonTest()
120+
{
121+
var input = @"empInfo
122+
employees";
123+
124+
var parser = new Parser();
125+
var result = parser.Parse(input);
126+
127+
Assert.NotEmpty(result);
128+
var formatted = result.Format();
129+
Assert.Contains("empInfo", formatted);
130+
Assert.Contains("employees", formatted);
131+
}
132+
133+
[Fact]
134+
public static void SequenceContextWithColonTest()
135+
{
136+
var input = @"employees:
137+
James Kirk
138+
Jean-Luc Picard
139+
Wesley Crusher";
140+
141+
var parser = new Parser();
142+
var result = parser.Parse(input);
143+
144+
Assert.NotEmpty(result);
145+
Assert.Single(result);
146+
var formatted = result.Format();
147+
Assert.Contains("employees:", formatted);
148+
Assert.Contains("James Kirk", formatted);
149+
Assert.Contains("Jean-Luc Picard", formatted);
150+
Assert.Contains("Wesley Crusher", formatted);
151+
}
152+
153+
[Fact]
154+
public static void SequenceContextWithComplexValuesTest()
155+
{
156+
var input = @"employees:
157+
(
158+
name (James Kirk)
159+
age 40
160+
)
161+
(
162+
name (Jean-Luc Picard)
163+
age 45
164+
)";
165+
166+
var parser = new Parser();
167+
var result = parser.Parse(input);
168+
169+
Assert.NotEmpty(result);
170+
Assert.Single(result);
171+
var formatted = result.Format();
172+
Assert.Contains("employees:", formatted);
173+
Assert.Contains("James Kirk", formatted);
174+
Assert.Contains("Jean-Luc Picard", formatted);
175+
}
176+
177+
[Fact]
178+
public static void NestedSetAndSequenceContextsTest()
179+
{
180+
var input = @"company
181+
departments:
182+
engineering
183+
sales
184+
employees:
185+
(name John)
186+
(name Jane)";
187+
188+
var parser = new Parser();
189+
var result = parser.Parse(input);
190+
191+
Assert.NotEmpty(result);
192+
var formatted = result.Format();
193+
Assert.Contains("company", formatted);
194+
Assert.Contains("departments:", formatted);
195+
Assert.Contains("employees:", formatted);
196+
}
197+
198+
[Fact]
199+
public static void DeeplyNestedMixedModesTest()
200+
{
201+
var input = @"root
202+
level1
203+
level2:
204+
value1
205+
value2
206+
level2b
207+
level3";
208+
209+
var parser = new Parser();
210+
var result = parser.Parse(input);
211+
212+
Assert.NotEmpty(result);
213+
var formatted = result.Format();
214+
Assert.Contains("root", formatted);
215+
Assert.Contains("level2:", formatted);
216+
}
217+
}
218+
}

csharp/Platform.Protocols.Lino/ILinksGroupListExtensions.cs

Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,42 +33,48 @@ private static void CollectLinksWithIndentedIdSyntaxSupport<TLinkAddress>(List<L
3333
if (groups != null && groups.Count > 0)
3434
{
3535
bool isIndentedIdSyntax = link.Id != null &&
36-
(link.Values == null || link.Values.Count == 0) &&
37-
!parentDependency.HasValue;
36+
(link.Values == null || link.Values.Count == 0);
3837

39-
if (isIndentedIdSyntax)
38+
if (isIndentedIdSyntax && !parentDependency.HasValue)
4039
{
4140
var childValues = new List<Link<TLinkAddress>>();
4241
for (int i = 0; i < groups.Count; i++)
4342
{
44-
var innerGroup = groups[i];
45-
var innerLink = innerGroup.Link;
46-
47-
if (innerLink.Values != null && innerLink.Values.Count == 1)
48-
{
49-
childValues.Add(innerLink.Values[0]);
50-
}
51-
else if (innerLink.Values != null && innerLink.Values.Count > 1)
52-
{
53-
childValues.Add(innerLink);
54-
}
55-
else if (innerLink.Id != null)
56-
{
57-
childValues.Add(new Link<TLinkAddress>(innerLink.Id));
58-
}
43+
var transformedLink = TransformIndentedIdLink(groups[i]);
44+
childValues.Add(transformedLink);
5945
}
6046

6147
var linkWithChildren = new Link<TLinkAddress>(link.Id, childValues);
6248
list.Add(linkWithChildren);
6349
}
6450
else
6551
{
52+
var transformedGroups = new List<LinksGroup<TLinkAddress>>();
53+
for (int i = 0; i < groups.Count; i++)
54+
{
55+
var childGroup = groups[i];
56+
var childLink = childGroup.Link;
57+
var childGroups = childGroup.Groups;
58+
59+
if (childLink.Id != null &&
60+
(childLink.Values == null || childLink.Values.Count == 0) &&
61+
childGroups != null && childGroups.Count > 0)
62+
{
63+
var transformedLink = TransformIndentedIdLink(childGroup);
64+
transformedGroups.Add(new LinksGroup<TLinkAddress>(transformedLink));
65+
}
66+
else
67+
{
68+
transformedGroups.Add(childGroup);
69+
}
70+
}
71+
6672
var currentDependency = parentDependency.HasValue ? parentDependency.Value.Combine(link) : link;
6773
list.Add(currentDependency);
6874

69-
for (int i = 0; i < groups.Count; i++)
75+
for (int i = 0; i < transformedGroups.Count; i++)
7076
{
71-
CollectLinksWithIndentedIdSyntaxSupport(list, groups[i], currentDependency);
77+
CollectLinksWithIndentedIdSyntaxSupport(list, transformedGroups[i], currentDependency);
7278
}
7379
}
7480
}
@@ -78,5 +84,32 @@ private static void CollectLinksWithIndentedIdSyntaxSupport<TLinkAddress>(List<L
7884
list.Add(currentLink);
7985
}
8086
}
87+
88+
private static Link<TLinkAddress> TransformIndentedIdLink<TLinkAddress>(LinksGroup<TLinkAddress> group)
89+
{
90+
var link = group.Link;
91+
var groups = group.Groups;
92+
93+
if (groups != null && groups.Count > 0 &&
94+
link.Id != null &&
95+
(link.Values == null || link.Values.Count == 0))
96+
{
97+
var childValues = new List<Link<TLinkAddress>>();
98+
for (int i = 0; i < groups.Count; i++)
99+
{
100+
var transformedChild = TransformIndentedIdLink(groups[i]);
101+
childValues.Add(transformedChild);
102+
}
103+
return new Link<TLinkAddress>(link.Id, childValues);
104+
}
105+
else if (link.Values != null && link.Values.Count == 1)
106+
{
107+
return link.Values[0];
108+
}
109+
else
110+
{
111+
return link;
112+
}
113+
}
81114
}
82115
}

experiments/Cargo.lock

Lines changed: 32 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

experiments/Cargo.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[package]
2+
name = "debug_rust"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[[bin]]
7+
name = "debug_equivalence"
8+
path = "debug_rust_equivalence.rs"
9+
10+
[dependencies]
11+
platform-lino = { path = "../rust" }

experiments/Program.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using System;
2+
using Platform.Protocols.Lino;
3+
4+
var version1 = @"empInfo
5+
employees:
6+
(
7+
name (James Kirk)
8+
age 40
9+
)
10+
(
11+
name (Jean-Luc Picard)
12+
age 45
13+
)";
14+
15+
var parser = new Parser();
16+
var result1 = parser.Parse(version1);
17+
18+
Console.WriteLine("=== BEFORE TRANSFORM ===");
19+
Console.WriteLine(result1.Format());
20+
21+
var transformed = result1.TransformIndentedIdSyntax();
22+
23+
Console.WriteLine("\n=== AFTER TRANSFORM ===");
24+
Console.WriteLine(transformed.Format());

0 commit comments

Comments
 (0)