private IEnumerable <FileLine> Prepocess() { string s; newLine: while ((s = reader.ReadLine()) != null) { var ss = s; lineNumber++; if (!insideComment) { var idx = s.IndexOf("/*"); if (idx > -1) { ss = s.Substring(0, idx); insideComment = true; } } else { var idx = s.IndexOf("*/"); if (idx > -1) { ss = s.Substring(idx + 2); insideComment = false; } else { continue; } } var commentIdx = ss.IndexOf("//"); if (commentIdx > -1) { ss = ss.Substring(0, commentIdx); } if (ss.Trim().StartsWith("#")) { ss = ss.TrimStart(); //Parse preprocessor if (ss.Trim() == "#endif") { supress = false; wasIf = false; } if (ss.Trim() == "#else") { if (wasIf) { supress = !supress; } else { throw new FormatException(string.Format("Unmatched #else in {0} line {1}", fileName, lineNumber)); } } if (supress) { goto newLine; } if (ss.StartsWith("#ifdef")) { var m = s.Substring("#ifdef".Length + 1); supress = !macros.ContainsKey(m); wasIf = true; } if (ss.StartsWith("#ifndef")) { var m = s.Substring("#ifndef".Length + 1); supress = macros.ContainsKey(m); wasIf = true; } if (ss.StartsWith("#undef")) { var m = s.Substring("#undef".Length + 1); macros.Remove(m); } if (ss.StartsWith("#define")) { var macro = new MacroDef { Line = lineNumber, File = fileName }; var block = ss.Substring("#define".Length + 1); while (block.EndsWith("\\")) { ss = reader.ReadLine(); block = block.TrimEnd('\\') + ss; lineNumber++; } var m = defineParser.Match(block); if (!m.Success) { throw new FormatException(string.Format("Error parsing define at {0} line {1}", fileName, lineNumber)); } macro.Name = m.Groups["name"].Value; macro.Body = m.Groups["body"].Value; macro.Parameters = m.Groups["params"].Value.Split(',').Select(p => p.Trim()).Where(p => !string.IsNullOrEmpty(p)).ToArray(); macro.Prepare(); macros[macro.Name] = macro; } if (ss.StartsWith("#include")) { var f = ss.Substring("#include".Length + 1).Trim('"', ' ', '<', '>'); var l = lookupFile(fileName, f); var p = new Preprocessor(l.Item1, l.Item2, lookupFile, macros); foreach (var x in p.Prepocess()) { yield return(x); } } continue; } if (supress) { goto newLine; } if (s.Length > 0) { yield return(new FileLine(fileName, lineNumber, PreprocessLine(s))); } } }
public static IEnumerable <FileLine> Prepocess(string fileName, TextReader reader, Func <string, string, Tuple <string, TextReader> > lookupFile) { var p = new Preprocessor(fileName, reader, lookupFile, new Dictionary <string, MacroDef>()); return(p.Prepocess()); }