Ejemplo n.º 1
0
	static bool ParseMembers (MemberInfo parent, Tokenizer tokenizer)
	{
		Annotations properties = new Annotations ();
		TypeInfo parent_type = parent as TypeInfo;
		string accessibility;
		TypeReference returntype;
		bool is_dtor;
		bool is_ctor;
		bool is_virtual;
		bool is_static;
		bool is_const;
		bool is_extern;
		string name;

		//Console.WriteLine ("ParseMembers ({0})", type.Name);

		do {
			returntype = null;
			is_dtor = is_ctor = is_virtual = is_static = false;
			is_extern = is_const = false;
			name = null;
			properties = new Annotations ();

			if (parent_type != null)
				accessibility = parent_type.IsStruct ? "public" : "private";
			else
				accessibility = "public";

			try {
				if (tokenizer.Accept (Token2Type.Punctuation, ";"))
					continue;
			} catch {
				return false;
			}

			if (tokenizer.CurrentToken.value == "}")
				return true;

			while (tokenizer.CurrentToken.type == Token2Type.CommentProperty) {
				properties.Add (tokenizer.CurrentToken.value);
				tokenizer.Advance (true);
			}

			//Console.WriteLine ("ParseMembers: Current token: {0}", tokenizer.CurrentToken);

			if (tokenizer.CurrentToken.type == Token2Type.Identifier) {
				string v = tokenizer.CurrentToken.value;
				switch (v) {
				case "public":
				case "protected":
				case "private":
					accessibility = v;
					tokenizer.Advance (true);
					tokenizer.Accept (Token2Type.Punctuation, ":");
					continue;
				case "enum":
					ParseEnum (properties, parent, tokenizer);
					continue;
				case "friend":
					while (!tokenizer.Accept (Token2Type.Punctuation, ";")) {
						tokenizer.Advance (true);
					}
					continue;
				case "struct":
				case "class":
				case "union":
					if (!ParseClassOrStruct (properties, parent, tokenizer))
						return false;
					continue;
				case "typedef":
					StringBuilder requisite = new StringBuilder ();
					requisite.Append (tokenizer.CurrentToken.value);
					requisite.Append (' ');
					tokenizer.Advance (true);
					while (!tokenizer.Accept (Token2Type.Punctuation, ";")) {
						requisite.Append (tokenizer.CurrentToken.value);
						requisite.Append (' ');
						if (tokenizer.CurrentToken.value == "{") {
							tokenizer.Advance (true);
							while (!tokenizer.Accept (Token2Type.Punctuation, "}")) {
								requisite.Append (tokenizer.CurrentToken.value);
								requisite.Append (' ');
								tokenizer.Advance (true);
							}
							requisite.Append (tokenizer.CurrentToken.value);
							requisite.Append (' ');
						}
						tokenizer.Advance (true);
					}
					requisite.Append (";");
					if (properties.ContainsKey ("CBindingRequisite"))
						cbinding_requisites.AppendLine (requisite.ToString ());

					continue;
				case "EVENTHANDLER":
					while (!tokenizer.Accept (Token2Type.Punctuation, ";"))
						tokenizer.Advance (true);
					continue;
				case "template":
					tokenizer.Advance (true);
					tokenizer.AcceptOrThrow (Token2Type.Punctuation, "<");
					tokenizer.AcceptOrThrow (Token2Type.Identifier, "typename");
					tokenizer.GetIdentifier ();
					tokenizer.AcceptOrThrow (Token2Type.Punctuation, ">");
					continue;
				case "using":
					tokenizer.Advance (true);
					continue;
				case "namespace":
					tokenizer.Advance (true);
					tokenizer.GetIdentifier ();
					tokenizer.Accept (Token2Type.Punctuation, "{");
					continue;
				case "mutable":
					tokenizer.Advance (true);
					continue;
				}
			}

			do {
				if (tokenizer.Accept (Token2Type.Identifier, "virtual")) {
					is_virtual = true;
					continue;
				}

				if (tokenizer.Accept (Token2Type.Identifier, "static")) {
					is_static = true;
					continue;
				}

				if (tokenizer.Accept (Token2Type.Identifier, "const")) {
					is_const = true;
					continue;
				}

				if (tokenizer.Accept (Token2Type.Identifier, "extern")) {
					is_extern = true;
					continue;
				}

				if (tokenizer.Accept (Token2Type.Identifier, "volatile")) {
					continue;
				}

				if (tokenizer.Accept (Token2Type.Identifier, "G_GNUC_INTERNAL")) {
					continue;
				}

			    break;
			} while (true);

			if (is_extern && tokenizer.Accept (Token2Type.Literal, "C")) {
				tokenizer.SyncWithEndBrace ();
				continue;
			}

			if (tokenizer.Accept (Token2Type.Punctuation, "~")) {
				is_dtor = true;
				if (!is_virtual) {
					TypeInfo ti = parent as TypeInfo;
					if (ti != null && ti.Base != null)
						Console.WriteLine ("The class {0} has a non-virtual destructor, and it's base class is {2} ({1}).", parent.Name, parent.Header, ti != null && ti.Base != null ? ti.Base.Value : "<none>");
				}
			}

			if (is_dtor) {
				name = "~" + tokenizer.GetIdentifier ();
				returntype = new TypeReference ("void");
			} else {
				returntype = ParseTypeReference (tokenizer);

				if (tokenizer.CurrentToken.value == "<") {
					tokenizer.Advance (true);
					while (!tokenizer.Accept (Token2Type.Punctuation, ">"))
						tokenizer.Advance (true);
				}

				if (returntype.Value == parent.Name && tokenizer.CurrentToken.value == "(") {
					is_ctor = true;
					name = returntype.Value;
					returntype.Value += "*";
				} else {
					name = tokenizer.GetIdentifier ();
				}
			}
			returntype.IsConst = is_const;
			returntype.IsReturnType = true;

			//Console.WriteLine ("ParseMembers: found member '{0}' is_ctor: {1}", name, is_ctor);

			if (tokenizer.Accept (Token2Type.Punctuation, "(")) {
				// Method
				MethodInfo method = new MethodInfo ();
				method.Header = tokenizer.CurrentFile;
				method.Parent = parent;
				method.Annotations = properties;
				method.Name = name;
				method.IsConstructor = is_ctor;
				method.IsDestructor = is_dtor;
				method.IsVirtual = is_virtual;
				method.IsStatic = is_static;
				method.IsPublic = accessibility == "public";
				method.IsPrivate = accessibility == "private";
				method.IsProtected = accessibility == "protected";
				method.ReturnType = returntype;

				//Console.WriteLine ("ParseMembers: found method '{0}' is_ctor: {1}", name, is_ctor);

				if (!tokenizer.Accept (Token2Type.Punctuation, ")")) {
					string param_value = null;
					do {
						ParameterInfo parameter = new ParameterInfo (method);

						while (tokenizer.CurrentToken.type == Token2Type.CommentProperty) {
							parameter.Annotations.Add (tokenizer.CurrentToken.value);
							tokenizer.Advance (true);
						}

						if (tokenizer.Accept (Token2Type.Punctuation, ".") && tokenizer.Accept (Token2Type.Punctuation, ".") && tokenizer.Accept (Token2Type.Punctuation, ".")) {
							// ... variable argument declaration
							parameter.ParameterType = new TypeReference ("...");
						} else {
							if (tokenizer.CurrentToken.type == Token2Type.Identifier) {
								if (tokenizer.Accept (Token2Type.Identifier, "Moonlight")) {
									tokenizer.Accept (Token2Type.Punctuation, ":");
									tokenizer.Accept (Token2Type.Punctuation, ":");
								}
							}
							parameter.ParameterType = ParseTypeReference (tokenizer);
						}

						if (tokenizer.CurrentToken.value != "," && tokenizer.CurrentToken.value != ")") {
							parameter.Name = tokenizer.GetIdentifier ();
							if (tokenizer.Accept (Token2Type.Punctuation, "[")) {
								if (tokenizer.CurrentToken.type == Token2Type.Identifier)
									tokenizer.Advance (true);
								tokenizer.AcceptOrThrow (Token2Type.Punctuation, "]");
							}
							if (tokenizer.Accept (Token2Type.Punctuation, "=")) {
								param_value = string.Empty;
								if (tokenizer.Accept (Token2Type.Punctuation, "-"))
									param_value = "-";
								param_value += tokenizer.GetIdentifier ();
								if (tokenizer.Accept (Token2Type.Punctuation, ":")) {
									tokenizer.AcceptOrThrow (Token2Type.Punctuation, ":");
									param_value += "::" + tokenizer.GetIdentifier ();
								}
							}
						}
						method.Parameters.Add (parameter);
						//Console.WriteLine ("ParseMember: got parameter, type: '{0}' name: '{1}' value: '{2}'", parameter.ParameterType.Value, parameter.Name, param_value);
					} while (tokenizer.Accept (Token2Type.Punctuation, ","));
					tokenizer.AcceptOrThrow (Token2Type.Punctuation, ")");
				}

				parent.Children.Add (method);

				//Allow const member functions, ignore the const keyword
				tokenizer.Accept (Token2Type.Identifier, "const");

				if (tokenizer.CurrentToken.value == "{") {
					//Console.WriteLine ("ParseMember: member has body, skipping it");
					tokenizer.SyncWithEndBrace ();
				} else if (is_ctor && tokenizer.Accept (Token2Type.Punctuation, ":")) {
					// ctor method implemented in header with field initializers and/or base class ctor call
					tokenizer.FindStartBrace ();
					tokenizer.SyncWithEndBrace ();
					//Console.WriteLine ("ParseMember: skipped ctor method implementation");
				} else if (tokenizer.Accept (Token2Type.Punctuation, "=")) {
					// pure virtual method
					tokenizer.AcceptOrThrow (Token2Type.Identifier, "0");
					tokenizer.AcceptOrThrow (Token2Type.Punctuation, ";");
					method.IsAbstract = true;
				} else {
					if (tokenizer.Accept (Token2Type.Identifier,  "__attribute__")) {
						tokenizer.AcceptOrThrow (Token2Type.Punctuation, "(");
						tokenizer.AcceptOrThrow (Token2Type.Punctuation, "(");
						if (tokenizer.CurrentToken.type == Token2Type.Identifier)
							tokenizer.Advance (true);
						tokenizer.AcceptOrThrow (Token2Type.Punctuation, ")");
						tokenizer.AcceptOrThrow (Token2Type.Punctuation, ")");
					}
					tokenizer.AcceptOrThrow (Token2Type.Punctuation, ";");
				}
			} else {
				if (is_ctor || is_dtor)
					throw new Exception (string.Format ("Expected '(', not '{0}'", tokenizer.CurrentToken.value));

				if (name == "operator") {
					while (true) {
						if (tokenizer.CurrentToken.value == ";") {
							// End of operator
							break;
						} else if (tokenizer.CurrentToken.value == "{") {
							// In-line implementation
							tokenizer.SyncWithEndBrace ();
							break;
						}
						tokenizer.Advance (true);
					}
					//Console.WriteLine ("ParseMembers: skipped operator");
				} else {
					FieldInfo field = new FieldInfo ();
					field.IsConst = is_const;
					field.IsStatic = is_static;
					field.IsExtern = is_extern;
					field.Name = name;
					field.FieldType = returntype;
					field.IsPublic = accessibility == "public";
					field.IsPrivate = accessibility == "private";
					field.IsProtected = accessibility == "protected";
					field.Annotations = properties;

					// Field
					do {
						//Console.WriteLine ("ParseMembers: found field '{0}'", name);
						field.Parent = parent;
						parent.Children.Add (field);

						if (tokenizer.Accept (Token2Type.Punctuation, "[")) {
							while (!tokenizer.Accept (Token2Type.Punctuation, "]")) {
								tokenizer.Advance (true);
							}
						}
						if (tokenizer.Accept (Token2Type.Punctuation, ":")) {
							field.BitField = tokenizer.GetIdentifier ();
						}
						if (tokenizer.Accept (Token2Type.Punctuation, ",")) {
							field = new FieldInfo ();
							if (tokenizer.Accept (Token2Type.Punctuation, "*")) {
								// ok
							}
							field.Name = tokenizer.GetIdentifier ();
							field.FieldType = returntype;
							continue;
						}
						if (tokenizer.Accept (Token2Type.Punctuation, "=")) {
							tokenizer.Advance (true); /* this can be an arbitrary long expression, sync with the ';'?  */
						}
						break;
					} while (true);

					tokenizer.Accept (Token2Type.Punctuation, ";");
				}
			}
		} while (true);
	}