/
ChipParser.cs
108 lines (99 loc) · 4.08 KB
/
ChipParser.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Linq;
namespace Logically;
public class ChipParser
{
private static readonly Regex ChipRegex = new(@"@(?<ChipName>\w+)\n?
(?<IOB>(?:.*:[^:;]*;?\n?)*)
(?<Wires>(?:[^@](?!\n+@))*.?)", RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace);
private static readonly Regex IOBRegex = new(@"(?<Type>\w*):[ \t]*(?<Value>[^:;]*)");
private static readonly Regex ConnectionRegex = new(@"(?<Chip>\w+)[ \t]*
\((?<InputWires>[^)]*)\)\s*
\((?<OutputWires>[^)]*)\)", RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace);
private static readonly Regex WireNames = new(@"\w+");
public static ChipDefinition ParseChips(string s)
{
s = s.Replace("\r", ""); // Remove all \r characters, as they are not needed
ChipDefinition mainByName = null;
ChipDefinition last = null;
foreach (Match chipMatch in ChipRegex.Matches(s).Cast<Match>())
{
ChipDefinition chipDef = new(chipMatch.Groups["ChipName"].Value);
List<string> Inputs = null;
List<string> Outputs = null;
List<string> BusLines = null;
List<List<string>> AllLines = new();
if (chipMatch.Groups.ContainsKey("IOB"))
{
foreach (Match iobMatch in IOBRegex.Matches(chipMatch.Groups["IOB"].Value).Cast<Match>())
{
string type = iobMatch.Groups["Type"].Value.ToLower();
List<string> wires = ParseWireGroup(iobMatch.Groups["Value"].Value);
if (type.StartsWith("i")) Inputs = wires;
else if (type.StartsWith("o")) Outputs = wires;
else if (type.StartsWith("b")) BusLines = wires;
else AllLines.Add(wires);
}
}
foreach (var wires in AllLines)
{
if (Inputs == null) Inputs = wires;
else if (Outputs == null) Outputs = wires;
else BusLines ??= wires;
}
chipDef.Inputs = Inputs ?? new();
chipDef.Outputs = Outputs ?? new();
chipDef.Buslines = BusLines ?? new();
chipDef.Connections = ParseConnections(chipMatch.Groups["Wires"].Value);
last = chipDef;
if (mainByName == null && chipDef.Name.ToLower().StartsWith("main")) mainByName = chipDef;
}
// Find the Main chip!
// It'll either be the Last chip defined, or one called "Main" or "main"
ChipDefinition main = mainByName ?? last;
if (main is null)
{
throw new System.Exception("No chips detected. Nothing to run!");
}
return main;
}
private static readonly Regex ManyWire = new(@"^(?<Count>\d+)(?<Name>\w+)");
public static List<string> ParseWireGroup(string s)
{
List<string> wires = new();
foreach (Match wireMatch in WireNames.Matches(s).Cast<Match>())
{
string wireName = wireMatch.Value;
if (ManyWire.IsMatch(wireName))
{
Match manyMatch = ManyWire.Match(wireName);
int count = int.Parse(manyMatch.Groups["Count"].Value);
string name = manyMatch.Groups["Name"].Value;
for (int i = 0; i < count; i++)
{
wires.Add(name + i);
}
}
else
{
wires.Add(wireMatch.Value);
}
}
return wires;
}
public static HashSet<ChipConnection> ParseConnections(string s)
{
HashSet<ChipConnection> connections = new();
foreach (Match connMatch in ConnectionRegex.Matches(s).Cast<Match>())
{
connections.Add(new ChipConnection()
{
TargetChip = connMatch.Groups["Chip"].Value,
InputWires = ParseWireGroup(connMatch.Groups["InputWires"].Value),
OutputWires = ParseWireGroup(connMatch.Groups["OutputWires"].Value),
});
}
return connections;
}
}