protected void Parse(StringReader rdr, DepthScanner scanner, Globals globals) { int currentLine = 0; ParseNamespace(rdr, globals, scanner, ref currentLine, false); // Resolve incomplete names foreach (string key in globals.GetPropertyNames()) { TypeInfo t = globals.GetProperty(key, true) as TypeInfo; if (t != null) { if (!t.IsComplete) { globals.AddProperty(key, globals.GetTypeInfo(t.Name), -1, ""); } if (t is TemplateInst) { TemplateInst ti = t as TemplateInst; if (!ti.WrappedType.IsComplete) { ti.WrappedType = globals.GetTypeInfo(ti.WrappedType.Name); } } } } foreach (FunctionInfo f in globals.GetFunctions(null, true)) { f.ResolveIncompletion(globals); } foreach (TypeInfo type in globals.TypeInfo) { type.ResolveIncompletion(globals); } }
protected void ParseNamespace(StringReader rdr, Globals globals, DepthScanner scanner, ref int currentLine, bool asNamespace) { string l = ""; int depth = scanner.GetBraceDepth(currentLine); bool hitDeeper = false; while ((l = rdr.ReadLine()) != null) { string defName = ""; int lineNumber = 0; ExtractLineInfo(ref l, out defName, out lineNumber); ++currentLine; if (l.Trim().StartsWith("//")) { continue; } if (l.Trim().StartsWith("#")) { continue; } int curDepth = scanner.GetBraceDepth(currentLine - 1); if (!asNamespace) { if (curDepth < depth) // Left our namespace depth { return; } else if (curDepth > depth) // Outside of the desired scanning depth (namespace level) { continue; } } else { if (curDepth > depth) { hitDeeper = true; } if (curDepth == depth && hitDeeper) { return; } else if (curDepth > depth + 1) //We do not go deeper than the namespace { continue; } } string line = l.Trim(); if (line.Length == 0) { continue; } string[] tokens = line.Split(BREAKCHARS); // Class / Interface/ Template type if (ResemblesClass(line)) { int abstractIdx = Array.IndexOf(tokens, "abstract"); int sharedIdx = Array.IndexOf(tokens, "shared"); int templateIdx = Array.IndexOf(tokens, "template"); int mixinIdx = Array.IndexOf(tokens, "mixin"); int finalIdx = Array.IndexOf(tokens, "final"); int classTermIdx = Math.Max(abstractIdx, Math.Max(sharedIdx, Math.Max(templateIdx, Math.Max(mixinIdx, finalIdx)))) + 1; bool isInterface = tokens[classTermIdx].Equals("interface"); if (templateIdx != -1) { //Resolve template type? } string className = tokens[classTermIdx + 1]; TypeInfo ti = new TypeInfo { Name = className, IsTemplate = templateIdx != -1, IsShared = sharedIdx != -1, IsAbstract = abstractIdx != -1, IsMixin = mixinIdx != -1, IsInterface = isInterface, SourceLine = lineNumber, SourceFile = defName }; // Get any baseclasses, baseclass must appear first for (int i = classTermIdx + 2; i < tokens.Length; ++i) { string baseName = tokens[i]; if (globals.ContainsTypeInfo(baseName.Replace(",", ""))) { ti.BaseTypes.Add(globals.GetTypeInfo(baseName.Replace(",", ""))); } } ParseClass(rdr, globals, scanner, ti, ref currentLine); globals.AddTypeInfo(className, ti); } else if (tokens[0].ToLower().Equals("namespace")) // Namespace { string nsName = tokens[1]; Globals namespaceGlobals = null; if (globals.ContainsNamespace(nsName)) // Check if the namespace has been encountered before { namespaceGlobals = globals.GetNamespace(nsName); } else { namespaceGlobals = new Globals(false); } namespaceGlobals.Parent = globals; ParseNamespace(rdr, namespaceGlobals, scanner, ref currentLine, true); namespaceGlobals.Name = nsName; globals.AddNamespace(nsName, namespaceGlobals); } else if (tokens[0].ToLower().Equals("enum")) // Enumeration { ParseEnum(line, rdr, globals, ref currentLine); } else { if (ResemblesFunction(line)) // Global/namespace function { try { FunctionInfo fi = _parseFunction(rdr, line, globals, lineNumber, defName); if (fi != null) { globals.AddFunction(fi); } } catch (Exception ex) { } } else if (ResemblesProperty(line, globals)) // Global/namespace property { string[] parts = l.Replace(";", "").Split(BREAKCHARS); // Globals can't be private/protected int constIdx = Array.IndexOf(parts, "const"); int uniformIdx = Array.IndexOf(parts, "uniform"); int termIdx = Math.Max(constIdx, uniformIdx) + 1; if (parts[termIdx].Contains('<')) { string templateType = parts[termIdx].Substring(0, parts[termIdx].IndexOf('<')); string containedType = parts[termIdx].Extract('<', '>'); TypeInfo wrapped = globals.GetTypeInfo(containedType); TemplateInst ti = new TemplateInst() { Name = templateType, IsTemplate = true, WrappedType = wrapped != null ? wrapped : new TypeInfo { Name = containedType, IsComplete = false, SourceLine = lineNumber, SourceFile = defName } }; globals.AddProperty(parts[termIdx + 1], ti, lineNumber, defName); //if (constIdx != -1) // globals.ReadonlyProperties.Add(tokens[termIdx + 1]); } else { string pname = parts[termIdx].EndsWith("@") ? parts[termIdx].Substring(0, parts[termIdx].Length - 1) : parts[termIdx]; //handle if (pname.Length == 0) { continue; } TypeInfo pType = null; if (globals.ContainsTypeInfo(pname)) { pType = globals.GetTypeInfo(pname); } if (pType == null) { //create temp type to resolve later pType = new TypeInfo() { Name = pname, IsComplete = false, SourceLine = lineNumber, SourceFile = defName }; } globals.AddProperty(parts[termIdx + 1], pType, lineNumber, defName); //if (constIdx != -1) // globals.ReadonlyProperties.Add(tokens[termIdx + 1]); } } } } }
protected FunctionInfo _parseFunction(StringReader rdr, string line, Globals globals, int lineNumber, string defName) { int firstParen = line.IndexOf('('); int lastParen = line.LastIndexOf(')'); while (lastParen == -1) { string l = rdr.ReadLine(); string d = ""; int ln = 0; ExtractLineInfo(ref l, out d, out ln); l = l.Trim(); if (l.StartsWith("#")) //#if's in shaders { continue; } line += l; lastParen = line.LastIndexOf(')'); } string baseDecl = line.Substring(0, firstParen); string paramDecl = line.Substring(firstParen, lastParen - firstParen + 1); //-1 for the ; string[] nameParts = baseDecl.Split(SPACECHAR, StringSplitOptions.RemoveEmptyEntries); TypeInfo retType = null; int sharedIdx = Array.IndexOf(nameParts, "shared"); int importIdx = Array.IndexOf(nameParts, "import"); int funcdefIdx = Array.IndexOf(nameParts, "funcdef"); int privateIdx = Array.IndexOf(nameParts, "private"); int protectedIdx = Array.IndexOf(nameParts, "protected"); // Return type is at this index int startIdx = Math.Max(sharedIdx, Math.Max(importIdx, Math.Max(funcdefIdx, Math.Max(privateIdx, protectedIdx)))) + 1; //TODO: split the name parts if (globals.ContainsTypeInfo(nameParts[startIdx])) { retType = globals.GetTypeInfo(nameParts[startIdx]); } else if (nameParts[startIdx].Contains('<')) { string wrappedType = nameParts[startIdx].Extract('<', '>'); string templateType = nameParts[startIdx].Replace(string.Format("<{0}>", wrappedType), ""); TypeInfo wrapped = globals.GetTypeInfo(wrappedType); TemplateInst ti = new TemplateInst() { Name = nameParts[startIdx], IsTemplate = true, WrappedType = wrapped != null ? wrapped : new TypeInfo { Name = wrappedType, IsComplete = false, SourceLine = lineNumber, SourceFile = defName } }; retType = ti; } else { retType = new TypeInfo() { Name = nameParts[startIdx], IsPrimitive = false, SourceLine = lineNumber, SourceFile = defName }; } if (funcdefIdx == -1) { if (nameParts.Length - 1 < startIdx + 1) { return(null); } return(new FunctionInfo { Name = nameParts[startIdx + 1], ReturnType = retType, Inner = paramDecl, IsImport = importIdx != -1, IsShared = sharedIdx != -1, SourceLine = lineNumber, SourceFile = defName, IsPrivate = privateIdx != -1, IsProtected = protectedIdx != -1 }); } else { if (nameParts.Length - 1 < startIdx + 1) { return(null); } return(new FuncDefInfo { Name = nameParts[startIdx + 1], ReturnType = retType, Inner = paramDecl, IsImport = importIdx != -1, IsShared = sharedIdx != -1, SourceLine = lineNumber, SourceFile = defName }); } }
protected void ParseClass(StringReader rdr, Globals targetGlobals, DepthScanner scanner, TypeInfo targetType, ref int currentLine) { int depth = scanner.GetBraceDepth(currentLine); string l = ""; bool hitDeeper = false; while ((l = rdr.ReadLine()) != null) { string defName = ""; int lineNumber = 0; ExtractLineInfo(ref l, out defName, out lineNumber); l = l.Trim(); ++currentLine; int curDepth = scanner.GetBraceDepth(currentLine - 1); if (curDepth > depth) { hitDeeper = true; } if (curDepth == depth && hitDeeper) { return; } else if (curDepth > depth + 1) //We do not go deeper than class { continue; } if (ResemblesFunction(l)) { FunctionInfo fi = _parseFunction(rdr, l, targetGlobals, lineNumber, defName); if (fi != null) { targetType.Functions.Add(fi); } } else if (ResemblesProperty(l, targetGlobals)) { string[] tokens = l.Replace(";", "").Split(BREAKCHARS); int constIdx = Array.IndexOf(tokens, "const"); int privateIdx = Array.IndexOf(tokens, "private"); int protectedIdx = Array.IndexOf(tokens, "protected"); int termIdx = Math.Max(constIdx, Math.Max(privateIdx, protectedIdx)) + 1; if (tokens[termIdx].Contains('<')) { string templateType = tokens[termIdx].Substring(0, tokens[termIdx].IndexOf('<')); string containedType = tokens[termIdx].Extract('<', '>'); TypeInfo wrapped = targetGlobals.GetTypeInfo(containedType); TemplateInst ti = new TemplateInst() { Name = templateType, IsTemplate = true, WrappedType = wrapped != null ? wrapped : new TypeInfo { Name = containedType, IsComplete = false, SourceLine = lineNumber, SourceFile = defName } }; targetType.Properties[tokens[termIdx + 1]] = ti; targetType.PropertyLines[tokens[termIdx + 1]] = lineNumber; if (constIdx != -1) { targetType.ReadonlyProperties.Add(tokens[termIdx + 1]); } if (protectedIdx != -1) { targetType.ProtectedProperties.Add(tokens[termIdx + 1]); } else if (privateIdx != -1) { targetType.PrivateProperties.Add(tokens[termIdx + 1]); } } else { string pname = tokens[termIdx].EndsWith("@") ? tokens[termIdx].Substring(0, tokens[termIdx].Length - 1) : tokens[termIdx]; //handle TypeInfo pType = null; if (targetGlobals.ContainsTypeInfo(pname)) { pType = targetGlobals.GetTypeInfo(pname); } if (pType == null) { //create temp type to resolve later pType = new TypeInfo() { Name = pname, IsComplete = false, SourceLine = lineNumber, SourceFile = defName }; } targetType.Properties[tokens[termIdx + 1]] = pType; targetType.PropertyLines[tokens[termIdx + 1]] = lineNumber; if (constIdx != -1) { targetType.ReadonlyProperties.Add(tokens[termIdx + 1]); } if (protectedIdx != -1) { targetType.ProtectedProperties.Add(tokens[termIdx + 1]); } else if (privateIdx != -1) { targetType.PrivateProperties.Add(tokens[termIdx + 1]); } } } } }
public override BaseTypeInfo ResolvePropertyPath(Globals globals, params string[] path) { string str = path[0]; if (str.Contains('(')) { string content = str.Substring(0, str.IndexOf('(')); FunctionInfo fi = Functions.FirstOrDefault(f => f.Name.Equals(content)); if (fi != null) { if (str.Contains('[') && fi.ReturnType is TemplateInst) { return(((TemplateInst)fi.ReturnType).WrappedType); } else if (fi.ReturnType is TemplateInst) { return(globals.GetTypeInfo(fi.ReturnType.Name.Substring(0, fi.ReturnType.Name.IndexOf('<')))); } return(fi.ReturnType); } } else if (str.Contains('[')) { string content = str.Extract('[', ']'); str = str.Replace(string.Format("[{0}]", content), ""); if (!Properties.ContainsKey(str)) { return(null); } TemplateInst ti = Properties[str] as TemplateInst; if (ti != null && path.Length > 1) { TypeInfo t = ti.WrappedType; return(t.ResolvePropertyPath(globals, path.SubArray(1, path.Length - 1))); } if (ti == null) { return(null); } else if (ti.WrappedType == null) { return(ti); } return(globals.GetTypeInfo(ti.WrappedType.Name)); } else if (Properties.ContainsKey(path[0])) { BaseTypeInfo ti = Properties[path[0]]; if (ti is TemplateInst) { ti = globals.GetTypeInfo(((TemplateInst)ti).Name); } if (path.Length > 1) { ti = ti.ResolvePropertyPath(globals, path.SubArray(1, path.Length - 1)); } return(ti); } else if (BaseTypes.Count > 0) // Check our base classes { foreach (TypeInfo t in BaseTypes) { BaseTypeInfo ti = t.ResolvePropertyPath(globals, path); if (ti != null) { return(ti); } } } return(null); }