diff options
| author | Melodi <62381002+Melodi17@users.noreply.github.com> | 2025-08-28 14:44:51 +1000 |
|---|---|---|
| committer | Melodi <62381002+Melodi17@users.noreply.github.com> | 2025-08-28 14:44:51 +1000 |
| commit | cf7e621c104cb4aea801392585d2dcc9335bc013 (patch) | |
| tree | ee4aef401c399995968afe217d06557587707c51 /Compiler | |
| parent | 7f96fc5e7f412a66d460dcaa82bbdbcaea08f360 (diff) | |
added preprocessor (wip)
Diffstat (limited to 'Compiler')
| -rw-r--r-- | Compiler/Preprocessor.cs | 59 | ||||
| -rw-r--r-- | Compiler/Program.cs | 24 | ||||
| -rw-r--r-- | Compiler/visitors/Main.cs | 2 |
3 files changed, 83 insertions, 2 deletions
diff --git a/Compiler/Preprocessor.cs b/Compiler/Preprocessor.cs new file mode 100644 index 0000000..01c14ab --- /dev/null +++ b/Compiler/Preprocessor.cs @@ -0,0 +1,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) + line = line.Replace(kvp.Key, kvp.Value); + + output.Add(line); + } + } +}
\ No newline at end of file diff --git a/Compiler/Program.cs b/Compiler/Program.cs index 3a277a1..09f7127 100644 --- a/Compiler/Program.cs +++ b/Compiler/Program.cs @@ -2,6 +2,7 @@ using System.Text; using Antlr4.Runtime; +using Antlr4.Runtime.Misc; using CommandLine; using visitors; using Parser = CommandLine.Parser; @@ -26,7 +27,7 @@ public class Program try { - AntlrFileStream inputStream = new(options.InputFile); + ICharStream inputStream = new PreprocessingCharStream(options.InputFile); CGrammarLexer lexer = new(inputStream); lexer.RemoveErrorListeners(); @@ -48,4 +49,25 @@ public class Program Console.WriteLine($"{ex.Message}"); } } +} + +public class PreprocessingCharStream : ICharStream +{ + private readonly AntlrInputStream inner; + + public PreprocessingCharStream(string filePath) + { + string preprocessed = Preprocessor.Process(filePath); + inner = new AntlrInputStream(preprocessed); + } + + public int Index => inner.Index; + public int Size => inner.Size; + public string SourceName => inner.SourceName; + public void Consume() => inner.Consume(); + public int LA(int i) => inner.LA(i); + public int Mark() => inner.Mark(); + public void Release(int marker) => inner.Release(marker); + public void Seek(int index) => inner.Seek(index); + public string GetText(Interval interval) => inner.GetText(interval); }
\ No newline at end of file diff --git a/Compiler/visitors/Main.cs b/Compiler/visitors/Main.cs index cbd468f..3b32399 100644 --- a/Compiler/visitors/Main.cs +++ b/Compiler/visitors/Main.cs @@ -152,7 +152,7 @@ public partial class CCompilerVisitor : CGrammarBaseVisitor<object?> .TrimEnd('\n') .Trim(); - this.Instruction("." + directive); + this.Instruction(directive); } return base.VisitErrorNode(node); |
