[vala/switch-to-gir] girparser: Use Regex to parse vala types.
- From: Luca Bruno <lucabru src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/switch-to-gir] girparser: Use Regex to parse vala types.
- Date: Thu, 26 Aug 2010 16:41:49 +0000 (UTC)
commit 4168fd84193dbde5fb4153745f9d733fc95f378a
Author: Luca Bruno <lethalman88 gmail com>
Date: Thu Aug 26 16:42:15 2010 +0200
girparser: Use Regex to parse vala types.
Based on Evan Nemerson patch.
vala/valagirparser.vala | 379 +++++++++++++++++++++++++++-------------------
1 files changed, 222 insertions(+), 157 deletions(-)
---
diff --git a/vala/valagirparser.vala b/vala/valagirparser.vala
index a502152..b883c8b 100644
--- a/vala/valagirparser.vala
+++ b/vala/valagirparser.vala
@@ -36,7 +36,9 @@ public class Vala.GirParser : CodeVisitor {
HIDDEN,
TYPE,
CHEADER_FILENAME,
- NAME;
+ NAME,
+ OWNED,
+ UNOWNED;
public static ArgumentType? from_string (string name) {
var enum_class = (EnumClass) typeof(ArgumentType).class_ref ();
@@ -52,14 +54,16 @@ public class Vala.GirParser : CodeVisitor {
class Argument {
public Expression expression;
- public SourceLocation source_location;
+ public SourceLocation begin;
+ public SourceLocation end;
public SourceReference source_reference;
public bool used = false;
- public Argument (Expression expression, SourceLocation source_location, SourceReference? source_reference = null) {
+ public Argument (Expression expression, SourceLocation begin, SourceLocation end, SourceReference? source_reference = null) {
this.expression = expression;
- this.source_location = source_location;
+ this.begin = begin;
+ this.end = end;
this.source_reference = source_reference;
}
}
@@ -75,18 +79,16 @@ public class Vala.GirParser : CodeVisitor {
public string pattern;
public PatternSpec pattern_spec;
public MetadataType type;
- public MetadataParser parser;
public SourceReference source_reference;
public bool used = false;
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, MetadataParser? parser = null, SourceReference? source_reference = null) {
+ public Metadata (string pattern, MetadataType type = MetadataType.GENERIC, SourceReference? source_reference = null) {
this.pattern = pattern;
this.pattern_spec = new PatternSpec (pattern);
this.type = type;
- this.parser = parser;
this.source_reference = source_reference;
}
@@ -168,18 +170,6 @@ public class Vala.GirParser : CodeVisitor {
return false;
}
-
- 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) {
- type_arg.used = true;
- 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;
- }
}
class MetadataParser {
@@ -222,70 +212,6 @@ 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 () {
old_end = end;
current = scanner.read_token (out begin, out end);
@@ -328,26 +254,33 @@ public class Vala.GirParser : CodeVisitor {
}
}
- string? parse_glob (out SourceReference source_reference) {
- if (current != TokenType.IDENTIFIER && current != TokenType.STAR) {
- return null;
- }
-
+ string? parse_identifier (out SourceReference source_reference, bool is_glob) {
var begin = this.begin;
var builder = new StringBuilder ();
do {
- if (current == TokenType.IDENTIFIER) {
- builder.append (get_string ());
- source_reference = get_src (begin);
- next ();
- } else if (current == TokenType.STAR) {
+ if (is_glob && current == TokenType.STAR) {
builder.append_c ('*');
- source_reference = get_src (begin);
- next ();
} else {
- break;
+ if (current == TokenType.IDENTIFIER) {
+ builder.append (get_string ());
+ } else if (current == TokenType.UNOWNED) {
+ builder.append ("unowned");
+ } else {
+ break;
+ }
}
+ source_reference = get_src (begin);
+ next ();
} while (!has_space ());
+
+ if (builder.str == "") {
+ if (is_glob) {
+ Report.error (get_src (begin), "expected pattern");
+ } else {
+ Report.error (get_src (begin), "expected identifier");
+ }
+ return null;
+ }
return builder.str;
}
@@ -375,13 +308,13 @@ public class Vala.GirParser : CodeVisitor {
}
SourceReference src;
- var pattern = parse_glob (out src);
+ var pattern = parse_identifier (out src, true);
if (pattern == null) {
return null;
}
metadata = parent_metadata.get_child (pattern, type);
if (metadata == null) {
- metadata = new Metadata (pattern, type, this, src);
+ metadata = new Metadata (pattern, type, src);
parent_metadata.add_child (metadata);
}
@@ -392,13 +325,13 @@ public class Vala.GirParser : CodeVisitor {
return null;
}
- pattern = parse_glob (out src);
+ pattern = parse_identifier (out src, true);
if (pattern == null) {
return null;
}
var child = metadata.get_child (pattern, type);
if (child == null) {
- child = new Metadata (pattern, type, this, src);
+ child = new Metadata (pattern, type, src);
metadata.add_child (child);
}
metadata = child;
@@ -410,7 +343,7 @@ public class Vala.GirParser : CodeVisitor {
return metadata;
}
- Expression? parse_literal () {
+ Expression? parse_literal (out SourceLocation end) {
var src = get_current_src ();
Expression expr = null;
@@ -434,67 +367,37 @@ public class Vala.GirParser : CodeVisitor {
Report.error (src, "expected literal");
break;
}
+ end = this.end;
next ();
return expr;
}
- 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));
- next ();
- } 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) {
while (current != TokenType.EOF && !has_newline ()) {
- if (current != TokenType.IDENTIFIER) {
- Report.error (get_current_src (), "expected argument name");
+ SourceReference src;
+ var id = parse_identifier (out src, false);
+ if (id == null) {
return false;
}
- var id = ArgumentType.from_string (get_string ());
- var arg_src = get_current_src ();
- if (id == null) {
- Report.error (arg_src, "unknown argument");
+ var arg_type = ArgumentType.from_string (id);
+ if (arg_type == null) {
+ Report.error (src, "unknown argument");
return false;
}
- if (next () != TokenType.ASSIGN) {
+ if (current != TokenType.ASSIGN) {
Report.error (get_current_src (), "expected `='");
return false;
}
next ();
- var expr_begin = this.begin;
- Expression expr = parse_literal ();
+ SourceLocation begin = this.begin;
+ SourceLocation end;
+ Expression expr = parse_literal (out end);
if (expr == null) {
return false;
}
- metadata.add_argument (id, new Argument (expr, expr_begin, arg_src));
+ metadata.add_argument (arg_type, new Argument (expr, begin, end, src));
}
return true;
@@ -522,6 +425,8 @@ public class Vala.GirParser : CodeVisitor {
public Namespace parent_namespace;
}
+ static GLib.Regex type_from_string_regex;
+
MarkupReader reader;
CodeContext context;
@@ -676,15 +581,173 @@ public class Vala.GirParser : CodeVisitor {
metadata_stack.remove_at (metadata_stack.size - 1);
}
- DataType? element_get_data_type (ArgumentType arg_type, string attribute_name, bool owned_by_default) {
- var type = metadata.get_data_type (arg_type, owned_by_default);
- if (type == null) {
- type = parse_type_from_gir_name (reader.get_attribute (attribute_name));
+ UnresolvedSymbol? parse_symbol_from_string (string symbol_string, SourceReference? source_reference = null) {
+ UnresolvedSymbol? sym = null;
+ foreach (unowned string s in symbol_string.split (".")) {
+ sym = new UnresolvedSymbol (sym, s, source_reference);
+ }
+ if (sym == null) {
+ Report.error (source_reference, "a symbol must be specified");
+ }
+ return sym;
+ }
+
+ bool parse_type_arguments_from_string (DataType parent_type, string type_arguments, SourceReference? source_reference = null) {
+ int type_arguments_length = (int) type_arguments.length;
+ GLib.StringBuilder current = new GLib.StringBuilder.sized (type_arguments_length);
+
+ int depth = 0;
+ for (var c = 0 ; c < type_arguments_length ; c++) {
+ if (type_arguments[c] == '<' || type_arguments[c] == '[') {
+ depth++;
+ current.append_unichar (type_arguments[c]);
+ } else if (type_arguments[c] == '>' || type_arguments[c] == ']') {
+ depth--;
+ current.append_unichar (type_arguments[c]);
+ } else if (type_arguments[c] == ',') {
+ if (depth == 0) {
+ var dt = parse_type_from_string (current.str, true, source_reference);
+ if (dt == null) {
+ return false;
+ }
+ parent_type.add_type_argument (dt);
+ current.truncate ();
+ } else {
+ current.append_unichar (type_arguments[c]);
+ }
+ } else {
+ current.append_unichar (type_arguments[c]);
+ }
+ }
+
+ var dt = parse_type_from_string (current.str, true, source_reference);
+ if (dt == null) {
+ return false;
+ }
+ parent_type.add_type_argument (dt);
+
+ return true;
+ }
+
+ DataType? parse_type_from_string (string type_string, bool owned_by_default, SourceReference? source_reference = null) {
+ if (type_from_string_regex == null) {
+ try {
+ type_from_string_regex = new GLib.Regex ("^(?:(owned|unowned|weak) +)?([0-9a-zA-Z_\\.]+)(?:<(.+)>)?(\\*+)?(\\[(,*)?\\])?(\\?)?$", GLib.RegexCompileFlags.ANCHORED | GLib.RegexCompileFlags.DOLLAR_ENDONLY | GLib.RegexCompileFlags.OPTIMIZE);
+ } catch (GLib.RegexError e) {
+ GLib.error ("Unable to compile regex: %s", e.message);
+ }
+ }
+
+ GLib.MatchInfo match;
+ if (!type_from_string_regex.match (type_string, 0, out match)) {
+ Report.error (source_reference, "unable to parse type");
+ return null;
+ }
+
+ DataType? type = null;
+
+ var ownership_data = match.fetch (1);
+ var type_name = match.fetch (2);
+ var type_arguments_data = match.fetch (3);
+ var pointers_data = match.fetch (4);
+ var array_data = match.fetch (5);
+ var nullable_data = match.fetch (6);
+
+ var nullable = nullable_data != null && nullable_data.length > 0;
+
+ if (ownership_data == null && type_name == "void") {
+ if (array_data == null && !nullable) {
+ type = new VoidType (source_reference);
+ if (pointers_data != null) {
+ for (int i=0; i < pointers_data.length; i++) {
+ type = new PointerType (type);
+ }
+ }
+ return type;
+ } else {
+ Report.error (source_reference, "invalid void type");
+ return null;
+ }
+ }
+
+ bool value_owned = owned_by_default;
+
+ if (ownership_data == "owned") {
+ if (owned_by_default) {
+ Report.error (source_reference, "unexpected `owned' keyword");
+ } else {
+ value_owned = true;
+ }
+ } else if (ownership_data == "unowned") {
+ if (owned_by_default) {
+ value_owned = true;
+ } else {
+ Report.error (source_reference, "unexpected `unowned' keyword");
+ return null;
+ }
+ }
+
+ var sym = parse_symbol_from_string (type_name, source_reference);
+ if (sym == null) {
+ return null;
+ }
+ type = new UnresolvedType.from_symbol (sym, source_reference);
+
+ if (type_arguments_data != null && type_arguments_data.length > 0) {
+ if (!parse_type_arguments_from_string (type, type_arguments_data, source_reference)) {
+ return null;
+ }
+ }
+
+ if (pointers_data != null) {
+ for (int i=0; i < pointers_data.length; i++) {
+ type = new PointerType (type);
+ }
+ }
+
+ if (array_data != null) {
+ type = new ArrayType (type, (int) array_data.length + 1, null);
+ }
+
+ type.nullable = nullable;
+ return type;
+ }
+
+ DataType? element_get_type (DataType type, bool owned_by_default, out bool changed = null, ArgumentType arg_type = ArgumentType.TYPE) {
+ if (&changed != null) {
+ changed = false;
+ }
+
+ if (metadata.has_argument (arg_type)) {
+ var src = metadata.args.get (arg_type).expression.source_reference;
+ var new_type = parse_type_from_string (metadata.get_string (arg_type), owned_by_default, src);
+ if (&changed != null) {
+ changed = true;
+ }
+ return new_type;
+ }
+
+ if (!(type is VoidType)) {
+ if (owned_by_default) {
+ if (metadata.has_argument (ArgumentType.UNOWNED)) {
+ type.value_owned = !metadata.get_bool (ArgumentType.UNOWNED);
+ if (&changed != null) {
+ changed = true;
+ }
+ }
+ } else {
+ if (metadata.has_argument (ArgumentType.OWNED)) {
+ type.value_owned = metadata.get_bool (ArgumentType.OWNED);
+ if (&changed != null) {
+ changed = true;
+ }
+ }
+ }
}
return type;
}
- string? element_get_string (ArgumentType arg_type, string attribute_name) {
+ string? element_get_string (string attribute_name, ArgumentType arg_type) {
var str = metadata.get_string (arg_type);
if (str == null) {
str = reader.get_attribute (attribute_name);
@@ -898,7 +961,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 = element_get_data_type (ArgumentType.TYPE, "target", true);
+ alias.base_type = element_get_type (parse_type_from_gir_name (reader.get_attribute ("target")), true);
alias.parent_namespace = current_namespace;
next ();
end_element ("alias");
@@ -1115,10 +1178,9 @@ public class Vala.GirParser : CodeVisitor {
} else {
string ctype;
var type = parse_type (out ctype, out array_length_idx, transfer == "full");
- if (metadata.has_argument (ArgumentType.TYPE)) {
- // keep the parsed ctype
- type = metadata.get_data_type (ArgumentType.TYPE, false);
- } else {
+ bool changed;
+ type = element_get_type (type, false, out changed);
+ if (!changed) {
// discard ctype, duplicated information
ctype = null;
}
@@ -1495,7 +1557,7 @@ public class Vala.GirParser : CodeVisitor {
Interface parse_interface () {
start_element ("interface");
- var iface = new Interface (element_get_string (ArgumentType.NAME, "name"), get_current_src ());
+ var iface = new Interface (element_get_string ("name", ArgumentType.NAME), get_current_src ());
iface.access = SymbolAccessibility.PUBLIC;
iface.external = true;
@@ -1682,7 +1744,7 @@ public class Vala.GirParser : CodeVisitor {
Method parse_constructor (string? parent_ctype = null) {
start_element ("constructor");
- string name = element_get_string (ArgumentType.NAME, "name");
+ string name = element_get_string ("name", ArgumentType.NAME);
string throws_string = reader.get_attribute ("throws");
next ();
@@ -1736,17 +1798,19 @@ public class Vala.GirParser : CodeVisitor {
Symbol parse_function (string element_name) {
start_element (element_name);
- string name = element_get_string (ArgumentType.NAME, "name");
+ string name = element_get_string ("name", ArgumentType.NAME);
string cname = reader.get_attribute ("c:identifier");
string throws_string = reader.get_attribute ("throws");
string invoker = reader.get_attribute ("invoker");
next ();
DataType return_type;
+
if (current_token == MarkupTokenType.START_ELEMENT && reader.name == "return-value") {
return_type = parse_return_value ();
} else {
return_type = new VoidType ();
}
+ return_type = element_get_type (return_type, true);
Symbol s;
@@ -1787,6 +1851,7 @@ public class Vala.GirParser : CodeVisitor {
while (current_token == MarkupTokenType.START_ELEMENT) {
if (!push_metadata ()) {
+ skip_element ();
continue;
}
@@ -2061,7 +2126,7 @@ public class Vala.GirParser : CodeVisitor {
var arg = metadata.args[arg_type];
if (!arg.used) {
// if metadata is used and argument is not, then it's a unexpected argument
- Report.error (arg.source_reference, "unexpected argument in this context");
+ Report.warning (arg.source_reference, "argument not used in this context");
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]