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
|
namespace Q1.Compiler;
using System.Text.RegularExpressions;
public static class Preprocessor
{
private static readonly Dictionary<string, string> Defines = new();
public static string Process(string filePath)
{
List<string> lines = [];
ProcessFile(filePath, lines, []);
return string.Join(Environment.NewLine, lines);
}
private static void ProcessFile(string filePath, List<string> output, HashSet<string> includeGuard)
{
if (includeGuard.Contains(Path.GetFullPath(filePath)))
return; // prevent recursive includes
includeGuard.Add(Path.GetFullPath(filePath));
foreach (string rawLine in File.ReadAllLines(filePath))
{
string line = rawLine.Trim();
if (line.StartsWith("#include"))
{
// simple format: #include "file"
Match match = Regex.Match(line, "#include\\s+\"([^\"]+)\"");
if (match.Success)
{
string includePath = Path.Combine(Path.GetDirectoryName(filePath)!, match.Groups[1].Value);
ProcessFile(includePath, output, includeGuard);
}
continue;
}
else if (line.StartsWith("#define"))
{
// simple format: #define NAME VALUE
Match match = Regex.Match(line, "#define\\s+(\\w+)\\s+(.*)");
if (match.Success)
Defines[match.Groups[1].Value] = match.Groups[2].Value;
continue;
}
else if (line.StartsWith("#load"))
{
output.Add(line.Replace("#load", "#.include"));
continue;
}
// expand macros
foreach (KeyValuePair<string, string> kvp in Defines.OrderByDescending(k => k.Key.Length))
line = line.Replace(kvp.Key, kvp.Value);
output.Add(line);
}
}
}
|