summaryrefslogtreecommitdiff
path: root/Compiler
diff options
context:
space:
mode:
Diffstat (limited to 'Compiler')
-rw-r--r--Compiler/Preprocessor.cs59
-rw-r--r--Compiler/Program.cs24
-rw-r--r--Compiler/visitors/Main.cs2
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);