public void Parse() { int curLine = 1; using (var reader = new StreamReader(Stream)) { while (!reader.EndOfStream) { var line = reader.ReadLine(); if (line.StartsWith("#define")) { var parser = new LineParser(line, curLine); parser.IsSymbol('#'); if (parser.ReadToken() != "define") { throw new Exception("Invalid definition"); } var def = parser.ReadToken(); if (!Registry.Defines.Contains(def)) { Registry.Defines.Add(def); } } else if (line.StartsWith("typedef") && line.Contains("APIENTRYP PFN")) { ReadFuncType(line, curLine); } else if (line.StartsWith("GLAPI PFN")) { var parser = new LineParser(line, curLine); // Skip GLAPI parser.SkipNextToken(); var typeName = parser.ReadToken(); var funcName = parser.ReadToken(); if (!funcName.StartsWith("glad_gl")) { Console.Error.WriteLine($"Failed to read function of type {typeName} at line {curLine} - invallid name"); continue; } funcName = funcName.Substring("glad_".Length); var type = FunctionTypes[typeName]; var func = new FunctionEntry(); func.Type = type; func.Name = funcName; Functions.Add(funcName, func); } ++curLine; } } }
private FunctionDeclaration ReadFuncType(string line, int curLine) { var parser = new LineParser(line, curLine); // Skip the typedef parser.SkipNextToken(); // Read the return type var returnType = parser.ReadUntil('('); if (!parser.IsSymbol('(')) { Console.Error.WriteLine($"Failed to parse function type declaration at line {curLine}:{parser.CurIdx} - Expected (, got {parser.ReadChar()}"); return(null); } var apiEntry = parser.ReadToken(); if (apiEntry != "APIENTRYP") { return(null); } var typedefName = parser.ReadToken(); if (!parser.IsSymbol(')')) { Console.Error.WriteLine($"Failed to parse function type declaration for declaration {typedefName} at line {curLine}:{parser.CurIdx} - Expected ), got {parser.ReadChar()}"); return(null); } if (!parser.IsSymbol('(')) { Console.Error.WriteLine($"Failed to parse function type declaration for declaration {typedefName} at line {curLine}:{parser.CurIdx} - Expected (, got {parser.ReadChar()}"); return(null); } var funcType = new FunctionDeclaration(); funcType.TypedefName = typedefName; funcType.ReturnType = returnType; while (!parser.IsSymbol(')')) { var argString = parser.ReadUntil(',', ')'); var arg = new FunctionArgument(argString); if (arg.Name != null && arg.Type != null && arg.Name.Length > 0 && arg.Type.Length > 0) { funcType.Arguments.Add(arg); } parser.IsSymbol(','); } FunctionTypes.Add(funcType.TypedefName, funcType); return(funcType); }
public FunctionArgument(string argString) { for (int i = argString.Length - 1; i >= 0; --i) { if (!LineParser.IsValidIdentifierCharacter(argString[i])) { Type = argString.Substring(0, i + 1).Trim(); Name = argString.Substring(i + 1).Trim(); return; } } }
public string SCREAMING_SNAKE_ToPascalCase(string snake) { const int offset = 'a' - 'A'; var build = new StringBuilder(snake.Length); bool cap = true; for (int i = 0; i < snake.Length; ++i) { char c = snake[i]; if (c == '_') { cap = true; continue; } if (c < 'A' || c > 'Z') { cap = true; } build.Append((char)(c + (cap ? 0 : offset))); cap = false; if (LineParser.IsNumeric(c)) { cap = true; } } // This is terrible, but we don't need to be super efficient here. var val = build.ToString(); foreach (var rep in _HardcodedPascalReplacements) { val = val.Replace(rep.Key, rep.Value); } return(val); }