[vala/switch-to-gir] girparser: Parse vala types in the metadata



commit f5e1e3443ca0977b23ee04ebd738cf70e5ca8e29
Author: Luca Bruno <lethalman88 gmail com>
Date:   Wed Aug 25 12:00:10 2010 +0200

    girparser: Parse vala types in the metadata

 vala/valagirparser.vala |  207 +++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 175 insertions(+), 32 deletions(-)
---
diff --git a/vala/valagirparser.vala b/vala/valagirparser.vala
index 565d4b6..f728bb8 100644
--- a/vala/valagirparser.vala
+++ b/vala/valagirparser.vala
@@ -32,20 +32,31 @@ public class Vala.GirParser : CodeVisitor {
 		SIGNAL
 	}
 
-	enum Argument {
-		HIDDEN;
+	enum ArgumentType {
+		HIDDEN,
+		TYPE;
 
-		public static Argument? from_string (string name) {
-			var enum_class = (EnumClass) typeof(Argument).class_ref ();
+		public static ArgumentType? from_string (string name) {
+			var enum_class = (EnumClass) typeof(ArgumentType).class_ref ();
 			unowned GLib.EnumValue? enum_value = enum_class.get_value_by_nick (name);
 			if (enum_value != null) {
-				Argument value = (Argument) enum_value.value;
+				ArgumentType value = (ArgumentType) enum_value.value;
 				return value;
 			}
 			return null;
 		}
 	}
 
+	class Argument {
+		public Expression expression;
+		public SourceLocation source_location;
+
+		public Argument (Expression expression, SourceLocation source_location) {
+			this.expression = expression;
+			this.source_location = source_location;
+		}
+	}
+
 	class Metadata {
 		private static Metadata _empty = new Metadata ("");
 		public static Metadata empty {
@@ -54,18 +65,21 @@ public class Vala.GirParser : CodeVisitor {
 			}
 		}
 
-		public SourceReference source_reference;
 		public string pattern;
 		public PatternSpec pattern_spec;
 		public MetadataType type;
+		public MetadataParser parser;
+		public SourceReference source_reference;
+
 		public bool used = false;
-		public Vala.Map<Argument,CodeNode> args = new HashMap<Argument,CodeNode> ();
+		public Vala.Map<ArgumentType,Argument> args = new HashMap<ArgumentType,Argument> ();
 		public ArrayList<Metadata> children = new ArrayList<Metadata> ();
 
-		public Metadata (string pattern, MetadataType type = MetadataType.GENERIC, SourceReference? source_reference = null) {
+		public Metadata (string pattern, MetadataType type = MetadataType.GENERIC, MetadataParser? parser = null, SourceReference? source_reference = null) {
 			this.pattern = pattern;
 			this.pattern_spec = new PatternSpec (pattern);
 			this.type = type;
+			this.parser = parser;
 			this.source_reference = source_reference;
 		}
 
@@ -82,16 +96,24 @@ public class Vala.GirParser : CodeVisitor {
 			return Metadata.empty;
 		}
 
-		public void add_argument (Argument key, CodeNode value) {
+		public void add_argument (ArgumentType key, Argument value) {
 			args.set (key, value);
 		}
 
-		public bool has_argument (Argument key) {
+		public bool has_argument (ArgumentType key) {
 			return args.contains (key);
 		}
 
-		public string? get_string (Argument arg) {
-			var lit = args.get (arg) as StringLiteral;
+		public Expression? get_expression (ArgumentType arg) {
+			var val = args.get (arg);
+			if (val != null) {
+				return val.expression;
+			}
+			return null;
+		}
+
+		public string? get_string (ArgumentType arg) {
+			var lit = get_expression (arg) as StringLiteral;
 			if (lit != null) {
 				return lit.eval ();
 			}
@@ -99,8 +121,8 @@ public class Vala.GirParser : CodeVisitor {
 			return null;
 		}
 
-		public int get_integer (Argument arg) {
-			var lit = args.get (arg) as IntegerLiteral;
+		public int get_integer (ArgumentType arg) {
+			var lit = get_expression (arg) as IntegerLiteral;
 			if (lit != null) {
 				return lit.value.to_int ();
 			}
@@ -108,20 +130,20 @@ public class Vala.GirParser : CodeVisitor {
 			return 0;
 		}
 
-		public double get_double (Argument arg) {
-			var name = args.get (arg);
-			if (name is RealLiteral) {
-				var lit = (RealLiteral) name;
+		public double get_double (ArgumentType arg) {
+			var expr = get_expression (arg);
+			if (expr is RealLiteral) {
+				var lit = (RealLiteral) expr;
 				return lit.value.to_double ();
-			} else if (name is IntegerLiteral) {
-				var lit = (IntegerLiteral) name;
+			} else if (expr is IntegerLiteral) {
+				var lit = (IntegerLiteral) expr;
 				return lit.value.to_int ();
 			}
 			return 0;
 		}
 
-		public bool get_bool (Argument arg) {
-			var lit = args.get (arg) as BooleanLiteral;
+		public bool get_bool (ArgumentType arg) {
+			var lit = get_expression (arg) as BooleanLiteral;
 			if (lit != null) {
 				return lit.value;
 			}
@@ -129,8 +151,15 @@ public class Vala.GirParser : CodeVisitor {
 			return false;
 		}
 
-		public DataType get_data_type (Argument arg) {
-			return args.get (arg) as DataType;
+		public DataType? get_data_type (ArgumentType arg, bool owned_by_default) {
+			var type_arg = args.get (arg);
+			if (type_arg != null && type_arg.expression is StringLiteral) {
+				var location = SourceLocation (type_arg.source_location.pos + 1, type_arg.source_location.line, type_arg.source_location.column + 1);
+				parser.seek (location);
+				var type = parser.parse_type (owned_by_default);
+				return type;
+			}
+			return null;
 		}
 	}
 
@@ -158,6 +187,10 @@ public class Vala.GirParser : CodeVisitor {
 			return new SourceReference (scanner.source_file, begin.line, begin.column, end.line, end.column);
 		}
 
+		SourceReference get_src (SourceLocation begin) {
+			return new SourceReference (scanner.source_file, begin.line, begin.column, end.line, end.column);
+		}
+
 		public Metadata parse_metadata (SourceFile metadata_file) {
 			scanner = new Scanner (metadata_file);
 			next ();
@@ -169,6 +202,70 @@ public class Vala.GirParser : CodeVisitor {
 			return tree;
 		}
 
+		public DataType? parse_type (bool owned_by_default) {
+			// sync with valaparser.vala
+			var begin = this.begin;
+	
+			if (accept (TokenType.VOID)) {
+				DataType type = new VoidType (get_src (begin));
+				while (accept (TokenType.STAR)) {
+					type = new PointerType (type);
+				}
+				return type;
+			}
+
+			bool value_owned = owned_by_default;
+
+			if (owned_by_default && accept (TokenType.UNOWNED)) {
+				value_owned = false;
+			} else if (!owned_by_default) {
+				value_owned = accept (TokenType.OWNED);
+			}
+
+			var sym = parse_symbol_name ();
+			if (sym == null) {
+				return null;
+			}
+			List<DataType> type_arg_list = parse_type_argument_list ();
+
+			DataType type = new UnresolvedType.from_symbol (sym, get_src (begin));
+			if (type_arg_list != null) {
+				foreach (DataType type_arg in type_arg_list) {
+					type.add_type_argument (type_arg);
+				}
+			}
+
+			while (accept (TokenType.STAR)) {
+				type = new PointerType (type, get_src (begin));
+			}
+
+			if (!(type is PointerType)) {
+				type.nullable = accept (TokenType.INTERR);
+			}
+
+			while (accept (TokenType.OPEN_BRACKET)) {
+				if (current != TokenType.CLOSE_BRACKET) {
+					Report.error (get_current_src (), "expected `]'");
+					return null;
+				}
+
+				type.value_owned = true;
+			
+				var array_type = new ArrayType (type, 0, get_src (begin));
+				array_type.nullable = accept (TokenType.INTERR);
+
+				type = array_type;
+			}
+
+			type.value_owned = value_owned;
+			return type;
+		}
+
+		public void seek (SourceLocation location) {
+			scanner.seek (location);
+			next ();
+		}
+
 		TokenType next () {
 			current = scanner.read_token (out begin, out end);
 			return current;
@@ -178,6 +275,14 @@ public class Vala.GirParser : CodeVisitor {
 			return ((string) begin.pos).ndup ((end.pos - begin.pos));
 		}
 
+		inline bool accept (TokenType type) {
+			if (current == type) {
+				next ();
+				return true;
+			}
+			return false;
+		}
+
 		MetadataType? parse_metadata_access () {
 			switch (current) {
 			case TokenType.DOT:
@@ -211,7 +316,7 @@ public class Vala.GirParser : CodeVisitor {
 				return null;
 			}
 
-			metadata = new Metadata (get_string (), type, get_current_src ());
+			metadata = new Metadata (get_string (), type, this, get_current_src ());
 			if (parent_metadata == null) {
 				Report.error (get_current_src (), "cannot determinate parent namespace");
 				return null;
@@ -236,7 +341,7 @@ public class Vala.GirParser : CodeVisitor {
 					Report.error (get_current_src (), "expected identifier");
 					return null;
 				}
-				var child = new Metadata (get_string (), type, get_current_src ());
+				var child = new Metadata (get_string (), type, this, get_current_src ());
 				metadata.add_child (child);
 				metadata = child;
 			}
@@ -268,6 +373,37 @@ public class Vala.GirParser : CodeVisitor {
 			}
 		}
 
+		UnresolvedSymbol? parse_symbol_name () {
+			// sync with valaparser.vala
+			var begin = this.begin;
+			UnresolvedSymbol sym = null;
+			do {
+				if (current != TokenType.IDENTIFIER) {
+					Report.error (get_current_src (), "expected identifier");
+					return null;
+				}
+				string name = get_string ();
+				sym = new UnresolvedSymbol (sym, name, get_src (begin));
+			} while (accept (TokenType.DOT));
+			return sym;
+		}
+
+		List<DataType>? parse_type_argument_list () {
+			if (accept (TokenType.OP_LT)) {
+				var list = new ArrayList<DataType> ();
+				do {
+					var type = parse_type (true);
+					list.add (type);
+				} while (accept (TokenType.COMMA));
+				if (current != TokenType.OP_GT) {
+					Report.error (get_current_src (), "expected `>'");
+					return null;
+				}
+				return list;
+			}
+			return null;
+		}
+
 		bool parse_args (Metadata metadata) {
 			var old_end = end;
 			if (current != TokenType.IDENTIFIER) {
@@ -281,7 +417,7 @@ public class Vala.GirParser : CodeVisitor {
 					break;
 				}
 
-				var id = Argument.from_string (get_string ());
+				var id = ArgumentType.from_string (get_string ());
 				if (id == null) {
 					Report.error (get_current_src (), "unknown argument");
 					return false;
@@ -297,8 +433,7 @@ public class Vala.GirParser : CodeVisitor {
 				if (expr == null) {
 					return false;
 				}
-
-				metadata.add_argument (id, expr);
+				metadata.add_argument (id, new Argument (expr, begin));
 			} while (current == TokenType.IDENTIFIER);
 
 			return true;
@@ -461,7 +596,7 @@ public class Vala.GirParser : CodeVisitor {
 			return false;
 		}
 		var new_metadata = get_metadata_from_element ();
-		if (new_metadata.has_argument (Argument.HIDDEN) && new_metadata.get_bool (Argument.HIDDEN)) {
+		if (new_metadata.has_argument (ArgumentType.HIDDEN) && new_metadata.get_bool (ArgumentType.HIDDEN)) {
 			return false;
 		}
 
@@ -475,6 +610,14 @@ public class Vala.GirParser : CodeVisitor {
 		metadata_stack.remove_at (metadata_stack.size - 1);
 	}
 
+	DataType? element_get_type (string attribute_name, bool owned_by_default) {
+		var type = metadata.get_data_type (ArgumentType.TYPE, owned_by_default);
+		if (type == null) {
+			type = parse_type_from_gir_name (reader.get_attribute ("target"));
+		}
+		return type;
+	}
+
 	void parse_repository () {
 		start_element ("repository");
 		next ();
@@ -671,7 +814,7 @@ public class Vala.GirParser : CodeVisitor {
 		var alias = new Alias ();
 		alias.source_reference = get_current_src ();
 		alias.name = reader.get_attribute ("name");
-		alias.base_type = parse_type_from_gir_name (reader.get_attribute ("target"));
+		alias.base_type = element_get_type ("target", true);
 		alias.parent_namespace = current_namespace;
 		next ();
 		end_element ("alias");
@@ -953,7 +1096,7 @@ public class Vala.GirParser : CodeVisitor {
 		return type;
 	}
 
-	DataType parse_type_from_gir_name (string type_name) {
+	DataType? parse_type_from_gir_name (string type_name) {
 		DataType type;
 		if (type_name == "none") {
 			type = new VoidType (get_current_src ());



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]