rules: use goto instead of state variable
authorRan Benita <ran234@gmail.com>
Tue, 28 Aug 2012 15:04:25 +0000 (18:04 +0300)
committerRan Benita <ran234@gmail.com>
Wed, 5 Sep 2012 13:37:43 +0000 (16:37 +0300)
There's no noticeable speed difference, but I think it's nicer and more
explicit than the previous code. Some people just don't like goto,
though..

Signed-off-by: Ran Benita <ran234@gmail.com>
src/xkbcomp/rules.c

index c048605..ee936c9 100644 (file)
@@ -412,6 +412,7 @@ struct matcher {
     /* Input.*/
     struct rule_names rmlvo;
     struct location loc;
+    union lvalue val;
     struct scanner scanner;
     darray(struct group) groups;
     /* Current mapping. */
@@ -999,179 +1000,153 @@ matcher_rule_apply_if_matches(struct matcher *m)
         m->mapping.skip = true;
 }
 
-enum rules_state {
-    STATE_INITIAL = 0,
-    STATE_BANG,
-    STATE_GROUP_NAME,
-    STATE_GROUP_ELEMENT,
-    STATE_MAPPING_MLVO,
-    STATE_MAPPING_KCCGST,
-    STATE_RULE_MLVO_FIRST,
-    STATE_RULE_MLVO,
-    STATE_RULE_KCCGST,
-};
+static enum rules_token
+gettok(struct matcher *m)
+{
+    return lex(&m->scanner, &m->val, &m->loc);
+}
 
 static bool
 matcher_match(struct matcher *m, const char *string, size_t len,
               const char *file_name, struct xkb_component_names *out)
 {
     enum rules_token tok;
-    enum rules_state state = STATE_INITIAL;
-    union lvalue val;
 
     if (!m)
         return false;
 
     scanner_init(&m->scanner, m->ctx, string, len, file_name);
-    memset(&val, 0, sizeof(val));
-
-    while ((tok = lex(&m->scanner, &val, &m->loc)) != TOK_END_OF_FILE)
-    {
-        if (tok == TOK_ERROR)
-            goto error;
-
-        switch (state) {
-        case STATE_INITIAL:
-            switch (tok) {
-            case TOK_BANG:
-                state = STATE_BANG;
-                break;
-            case TOK_END_OF_LINE:
-                state = STATE_INITIAL;
-                break;
-            default:
-                goto state_error;
-            }
-            break;
 
-        case STATE_BANG:
-            switch (tok) {
-            case TOK_GROUP_NAME:
-                matcher_group_start_new(m, val.string);
-                state = STATE_GROUP_NAME;
-                break;
-            case TOK_IDENTIFIER:
-                matcher_mapping_start_new(m);
-                matcher_mapping_set_mlvo(m, val.string);
-                state = STATE_MAPPING_MLVO;
-                break;
-            default:
-                goto state_error;
-            }
-            break;
+initial:
+    switch (tok = gettok(m)) {
+    case TOK_BANG:
+        goto bang;
+    case TOK_END_OF_LINE:
+        goto initial;
+    case TOK_END_OF_FILE:
+        goto finish;
+    default:
+        goto unexpected;
+    }
 
-        case STATE_GROUP_NAME:
-            switch (tok) {
-            case TOK_EQUALS:
-                state = STATE_GROUP_ELEMENT;
-                break;
-            default:
-                goto state_error;
-            }
-            break;
+bang:
+    switch (tok = gettok(m)) {
+    case TOK_GROUP_NAME:
+        matcher_group_start_new(m, m->val.string);
+        goto group_name;
+    case TOK_IDENTIFIER:
+        matcher_mapping_start_new(m);
+        matcher_mapping_set_mlvo(m, m->val.string);
+        goto mapping_mlvo;
+    default:
+        goto unexpected;
+    }
 
-        case STATE_GROUP_ELEMENT:
-            switch (tok) {
-            case TOK_IDENTIFIER:
-                matcher_group_add_element(m, val.string);
-                state = STATE_GROUP_ELEMENT;
-                break;
-            case TOK_END_OF_LINE:
-                state = STATE_INITIAL;
-                break;
-            default:
-                goto state_error;
-            }
-            break;
+group_name:
+    switch (tok = gettok(m)) {
+    case TOK_EQUALS:
+        goto group_element;
+    default:
+        goto unexpected;
+    }
 
-        case STATE_MAPPING_MLVO:
-            switch (tok) {
-            case TOK_IDENTIFIER:
-                if (!m->mapping.skip)
-                    matcher_mapping_set_mlvo(m, val.string);
-                state = STATE_MAPPING_MLVO;
-                break;
-            case TOK_EQUALS:
-                state = STATE_MAPPING_KCCGST;
-                break;
-            default:
-                goto state_error;
-            }
-            break;
+group_element:
+    switch (tok = gettok(m)) {
+    case TOK_IDENTIFIER:
+        matcher_group_add_element(m, m->val.string);
+        goto group_element;
+    case TOK_END_OF_LINE:
+        goto initial;
+    default:
+        goto unexpected;
+    }
 
-        case STATE_MAPPING_KCCGST:
-            switch (tok) {
-            case TOK_IDENTIFIER:
-                if (!m->mapping.skip)
-                    matcher_mapping_set_kccgst(m, val.string);
-                state = STATE_MAPPING_KCCGST;
-                break;
-            case TOK_END_OF_LINE:
-                if (!m->mapping.skip)
-                    matcher_mapping_verify(m);
-                state = STATE_RULE_MLVO_FIRST;
-                break;
-            default:
-                goto state_error;
-            }
-            break;
+mapping_mlvo:
+    switch (tok = gettok(m)) {
+    case TOK_IDENTIFIER:
+        if (!m->mapping.skip)
+            matcher_mapping_set_mlvo(m, m->val.string);
+        goto mapping_mlvo;
+    case TOK_EQUALS:
+        goto mapping_kccgst;
+    default:
+        goto unexpected;
+    }
 
-        case STATE_RULE_MLVO_FIRST:
-            if (tok == TOK_BANG) {
-                state = STATE_BANG;
-                break;
-            } else if (tok == TOK_END_OF_LINE) {
-                state = STATE_INITIAL;
-                break;
-            }
-            matcher_rule_start_new(m);
-            /* fallthrough */
-        case STATE_RULE_MLVO:
-            switch (tok) {
-            case TOK_IDENTIFIER:
-                if (!m->rule.skip)
-                    matcher_rule_set_mlvo(m, val.string);
-                state = STATE_RULE_MLVO;
-                break;
-            case TOK_STAR:
-                if (!m->rule.skip)
-                    matcher_rule_set_mlvo_wildcard(m);
-                state = STATE_RULE_MLVO;
-                break;
-            case TOK_GROUP_NAME:
-                if (!m->rule.skip)
-                    matcher_rule_set_mlvo_group(m, val.string);
-                state = STATE_RULE_MLVO;
-                break;
-            case TOK_EQUALS:
-                state = STATE_RULE_KCCGST;
-                break;
-            default:
-                goto state_error;
-            }
-            break;
+mapping_kccgst:
+    switch (tok = gettok(m)) {
+    case TOK_IDENTIFIER:
+        if (!m->mapping.skip)
+            matcher_mapping_set_kccgst(m, m->val.string);
+        goto mapping_kccgst;
+    case TOK_END_OF_LINE:
+        if (!m->mapping.skip)
+            matcher_mapping_verify(m);
+        goto rule_mlvo_first;
+    default:
+        goto unexpected;
+    }
 
-        case STATE_RULE_KCCGST:
-            switch (tok) {
-            case TOK_IDENTIFIER:
-                if (!m->rule.skip)
-                    matcher_rule_set_kccgst(m, val.string);
-                state = STATE_RULE_KCCGST;
-                break;
-            case TOK_END_OF_LINE:
-                if (!m->rule.skip)
-                    matcher_rule_verify(m);
-                if (!m->rule.skip)
-                    matcher_rule_apply_if_matches(m);
-                state = STATE_RULE_MLVO_FIRST;
-                break;
-            default:
-                goto state_error;
-            }
-            break;
-        }
+rule_mlvo_first:
+    switch (tok = gettok(m)) {
+    case TOK_BANG:
+        goto bang;
+    case TOK_END_OF_LINE:
+        goto rule_mlvo_first;
+    case TOK_END_OF_FILE:
+        goto finish;
+    default:
+        matcher_rule_start_new(m);
+        goto rule_mlvo_no_tok;
+    }
+
+rule_mlvo:
+    tok = gettok(m);
+rule_mlvo_no_tok:
+    switch (tok) {
+    case TOK_IDENTIFIER:
+        if (!m->rule.skip)
+            matcher_rule_set_mlvo(m, m->val.string);
+        goto rule_mlvo;
+    case TOK_STAR:
+        if (!m->rule.skip)
+            matcher_rule_set_mlvo_wildcard(m);
+        goto rule_mlvo;
+    case TOK_GROUP_NAME:
+        if (!m->rule.skip)
+            matcher_rule_set_mlvo_group(m, m->val.string);
+        goto rule_mlvo;
+    case TOK_EQUALS:
+        goto rule_kccgst;
+    default:
+        goto unexpected;
+    }
+
+rule_kccgst:
+    switch (tok = gettok(m)) {
+    case TOK_IDENTIFIER:
+        if (!m->rule.skip)
+            matcher_rule_set_kccgst(m, m->val.string);
+        goto rule_kccgst;
+    case TOK_END_OF_LINE:
+        if (!m->rule.skip)
+            matcher_rule_verify(m);
+        if (!m->rule.skip)
+            matcher_rule_apply_if_matches(m);
+        goto rule_mlvo_first;
+    default:
+        goto unexpected;
+    }
+
+unexpected:
+    switch (tok) {
+    case TOK_ERROR:
+        goto error;
+    default:
+        goto state_error;
     }
 
+finish:
     if (darray_empty(m->kccgst[KCCGST_KEYCODES]) ||
         darray_empty(m->kccgst[KCCGST_TYPES]) ||
         darray_empty(m->kccgst[KCCGST_COMPAT]) ||