private Dictionary <string, TopLevelConstruct> CreateFullyQualifiedLookup(IList <TopLevelConstruct> code) { using (new PerformanceSection("")) { HashSet <string> namespaces = new HashSet <string>(); Dictionary <string, TopLevelConstruct> lookup = new Dictionary <string, TopLevelConstruct>(); bool mainFound = false; foreach (TopLevelConstruct item in code) { string ns; string memberName; if (item is FunctionDefinition) { FunctionDefinition fd = (FunctionDefinition)item; ns = fd.Namespace; memberName = fd.NameToken.Value; if (memberName == "main") { if (mainFound) { throw new ParserException(item.FirstToken, "Multiple main methods found."); } mainFound = true; lookup["~"] = item; } } else if (item is ClassDefinition) { ClassDefinition cd = (ClassDefinition)item; ns = cd.Namespace; memberName = cd.NameToken.Value; // TODO: nested classes, constants, and enums. } else if (item is EnumDefinition) { EnumDefinition ed = (EnumDefinition)item; ns = ed.Namespace; memberName = ed.Name; } else if (item is ConstStatement) { ConstStatement cs = (ConstStatement)item; ns = cs.Namespace; memberName = cs.Name; } else { string error = "This sort of expression cannot exist outside of function or field definitions."; throw new ParserException(item.FirstToken, error); } if (ns.Length > 0) { string accumulator = ""; foreach (string nsPart in ns.Split('.')) { if (accumulator.Length > 0) { accumulator += "."; } accumulator += nsPart; namespaces.Add(accumulator); } } string fullyQualifiedName = (ns.Length > 0 ? (ns + ".") : "") + memberName; if (lookup.ContainsKey(fullyQualifiedName)) { // TODO: token information from two locations throw new ParserException(item.FirstToken, "Two items have identical fully-qualified names: '" + fullyQualifiedName + "'"); } lookup[fullyQualifiedName] = item; } foreach (string key in lookup.Keys) { if (namespaces.Contains(key)) { throw new ParserException(lookup[key].FirstToken, "This name collides with a namespace definition."); } } // Go through and fill in all the partially qualified namespace names. foreach (string ns in namespaces) { Namespace nsInstance = new Namespace(null, ns, null, null, null); string possibleLibraryName = ns.Split('.')[0]; TODO.EnglishLocaleAssumed(); Library library = this.parser.LibraryManager.GetLibraryFromName(possibleLibraryName); if (library != null) { // TODO: once you get rid of this line, make the Library setter protected nsInstance.Library = library; } lookup[ns] = nsInstance; } if (lookup.ContainsKey("~")) { FunctionDefinition mainFunc = (FunctionDefinition)lookup["~"]; if (mainFunc.ArgNames.Length > 1) { throw new ParserException(mainFunc.FirstToken, "The main function must accept 0 or 1 arguments."); } } else { throw new InvalidOperationException("No main(args) function was defined."); } return(lookup); } }