Improve binding-set parser

Make gtk_binding_entry_add_signal_from_string() return the expected
token in case of parsing error, so that we can return a GError
instead of spewing. Also, add a separate scope for binding-set,
since allowing {} in identifiers in SCOPE_VALUE breaks the fact
that the ; after the last assignment in a rule is optional.
This commit is contained in:
Matthias Clasen 2011-01-28 19:36:24 -05:00
parent a04e721473
commit 8bb0d552f1
3 changed files with 31 additions and 15 deletions

View File

@ -1271,17 +1271,20 @@ create_signal_scanner (void)
* Key combinations must be in a format that can be parsed by
* gtk_accelerator_parse().
*
* Returns: %G_TOKEN_NONE if the signal was successfully parsed and added,
* the expected token otherwise
*
* Since: 3.0
**/
void
*/
GTokenType
gtk_binding_entry_add_signal_from_string (GtkBindingSet *binding_set,
const gchar *signal_desc)
const gchar *signal_desc)
{
static GScanner *scanner = NULL;
GTokenType ret;
g_return_if_fail (binding_set != NULL);
g_return_if_fail (signal_desc != NULL);
g_return_val_if_fail (binding_set != NULL, G_TOKEN_NONE);
g_return_val_if_fail (signal_desc != NULL, G_TOKEN_NONE);
if (G_UNLIKELY (!scanner))
scanner = create_signal_scanner ();
@ -1291,12 +1294,10 @@ gtk_binding_entry_add_signal_from_string (GtkBindingSet *binding_set,
ret = gtk_binding_parse_bind (scanner, binding_set);
if (ret != G_TOKEN_NONE)
g_scanner_unexp_token (scanner, ret, NULL, NULL, NULL,
"Could not parse binding", FALSE);
/* Reset for next use */
g_scanner_set_scope (scanner, 0);
return ret;
}
/**

View File

@ -125,8 +125,8 @@ void gtk_binding_entry_add_signall (GtkBindingSet *binding_set,
const gchar *signal_name,
GSList *binding_args);
void gtk_binding_entry_add_signal_from_string (GtkBindingSet *binding_set,
const gchar *signal_desc);
GTokenType gtk_binding_entry_add_signal_from_string (GtkBindingSet *binding_set,
const gchar *signal_desc);
void gtk_binding_entry_remove (GtkBindingSet *binding_set,
guint keyval,

View File

@ -801,7 +801,8 @@ enum ParserScope {
SCOPE_PSEUDO_CLASS,
SCOPE_NTH_CHILD,
SCOPE_DECLARATION,
SCOPE_VALUE
SCOPE_VALUE,
SCOPE_BINDING_SET
};
/* Extend GtkStateType, since these
@ -1505,6 +1506,12 @@ scanner_apply_scope (GScanner *scanner,
g_scanner_set_scope (scanner, scope);
if (scope == SCOPE_VALUE)
{
scanner->config->cset_identifier_first = G_CSET_a_2_z G_CSET_A_2_Z G_CSET_DIGITS "@#-_";
scanner->config->cset_identifier_nth = G_CSET_a_2_z G_CSET_A_2_Z G_CSET_DIGITS "@#-_ +(),.%\t\n'/\"";
scanner->config->scan_identifier_1char = TRUE;
}
else if (scope == SCOPE_BINDING_SET)
{
scanner->config->cset_identifier_first = G_CSET_a_2_z G_CSET_A_2_Z G_CSET_DIGITS "@#-_";
scanner->config->cset_identifier_nth = G_CSET_a_2_z G_CSET_A_2_Z G_CSET_DIGITS "@#-_ +(){}<>,.%\t\n'/\"";
@ -3318,19 +3325,27 @@ parse_rule (GtkCssProvider *css_provider,
if (scanner->token != G_TOKEN_LEFT_CURLY)
return G_TOKEN_LEFT_CURLY;
css_provider_push_scope (css_provider, SCOPE_VALUE);
css_provider_push_scope (css_provider, SCOPE_BINDING_SET);
g_scanner_get_next_token (scanner);
do
{
GTokenType ret;
if (scanner->token != G_TOKEN_IDENTIFIER)
{
scanner->user_data = "Binding definition";
return G_TOKEN_IDENTIFIER;
}
gtk_binding_entry_add_signal_from_string (binding_set,
scanner->value.v_identifier);
ret = gtk_binding_entry_add_signal_from_string (binding_set,
scanner->value.v_identifier);
if (ret != G_TOKEN_NONE)
{
scanner->user_data = "Binding definition";
return ret;
}
g_scanner_get_next_token (scanner);
if (scanner->token != ';')