コード例 #1
0
ファイル: Resolver.cs プロジェクト: geofrey/crayon
		private Dictionary<string, Executable> CreateFullyQualifiedLookup(IList<Executable> code)
		{
			HashSet<string> namespaces = new HashSet<string>();

			Dictionary<string, Executable> lookup = new Dictionary<string, Executable>();
			bool mainFound = false;
			foreach (Executable 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
				{
					throw new Exception();
				}

				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;

				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)
			{
				lookup[ns] = new Namespace(null, ns, null);
			}

			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 Exception("No main(args) function was defined.");
			}

			return lookup;
		}
コード例 #2
0
ファイル: ExecutableParser.cs プロジェクト: geofrey/crayon
		private static Executable ParseNamespace(Parser parser, TokenStream tokens, Executable owner)
		{
			Token namespaceToken = tokens.PopExpected("namespace");
			Token first = tokens.Pop();
			Parser.VerifyIdentifier(first);
			List<Token> namespacePieces = new List<Token>() { first };
			while (tokens.PopIfPresent("."))
			{
				Token nsToken = tokens.Pop();
				Parser.VerifyIdentifier(nsToken);
				namespacePieces.Add(nsToken);
			}

			string name = string.Join(".", namespacePieces.Select<Token, string>(t => t.Value));
			parser.PushNamespacePrefix(name);

			Namespace namespaceInstance = new Namespace(namespaceToken, name, owner);

			tokens.PopExpected("{");
			List<Executable> namespaceMembers = new List<Executable>();
			while (!tokens.PopIfPresent("}"))
			{
				Executable executable = ExecutableParser.Parse(parser, tokens, false, false, true, namespaceInstance);
				if (executable is FunctionDefinition ||
					executable is ClassDefinition ||
					executable is Namespace)
				{
					namespaceMembers.Add(executable);
				}
				else
				{
					throw new ParserException(executable.FirstToken, "Only function, class, and nested namespace declarations may exist as direct members of a namespace.");
				}
			}

			namespaceInstance.Code = namespaceMembers.ToArray();

			parser.PopNamespacePrefix();

			return namespaceInstance;
		}