support simple macro function, like A(x) --> #x --> x
authoryu.dongliang <18588496441@163.com>
Thu, 26 Sep 2024 15:18:45 +0000 (23:18 +0800)
committeryu.dongliang <18588496441@163.com>
Thu, 26 Sep 2024 15:18:45 +0000 (23:18 +0800)
examples/macro_str.c [new file with mode: 0644]
lex/scf_lex.c
lex/scf_lex_test.c
lex/scf_lex_util.c
parse/scf_dfa.c

diff --git a/examples/macro_str.c b/examples/macro_str.c
new file mode 100644 (file)
index 0000000..354799b
--- /dev/null
@@ -0,0 +1,9 @@
+#define A(x) #x
+
+int printf(const char* fmt, ...);
+
+int main()
+{
+       printf("%s\n", A(zzz));
+       return 0;
+}
index 42fff046f1a1e4a45730cf2a4a8d97c6a5713958..87eff60a43d2d5bade86ff4602c4ce06fef01261 100644 (file)
@@ -1038,6 +1038,8 @@ static int __parse_macro_argv(scf_lex_t* lex, scf_macro_t* m)
                        }
                }
 
+               scf_logw("macro '%s' arg: %s\n", m->w->text->data, w->text->data);
+
                ret = scf_vector_add(m->argv, w);
                if (ret < 0) {
                        scf_lex_word_free(w);
@@ -1193,11 +1195,133 @@ static int __parse_macro(scf_lex_t* lex, scf_lex_word_t** pword, scf_lex_word_t*
        return scf_lex_pop_word(lex, pword);
 }
 
+static int __fill_macro_argv(scf_lex_t* lex, scf_macro_t* m, scf_lex_word_t* use, scf_vector_t* argv)
+{
+       scf_lex_word_t** pp;
+       scf_lex_word_t*  w = NULL;
+
+       int ret = __lex_pop_word(lex, &w);
+       if (ret < 0)
+               return ret;
+
+       if (SCF_LEX_WORD_LP != w->type) {
+               scf_loge("macro '%s' needs args, file: %s, line: %d\n", m->w->text->data, w->file->data, w->line);
+               scf_lex_word_free(w);
+               return -1;
+       }
+
+       scf_lex_word_free(w);
+       w = NULL;
+
+       int n_lps = 0;
+       int n_rps = 0;
+       int i;
+
+       pp = NULL;
+
+       while (1) {
+               ret = __lex_pop_word(lex, &w);
+               if (ret < 0)
+                       return ret;
+
+               if (SCF_LEX_WORD_COMMA == w->type) {
+                       if (!pp) {
+                               scf_loge("unexpected ',' in macro '%s', file: %s, line: %d\n", m->w->text->data, w->file->data, w->line);
+
+                               scf_lex_word_free(w);
+                               ret = -1;
+                               goto error;
+                       }
+
+                       scf_lex_word_free(w);
+                       w  = NULL;
+
+                       if (n_rps == n_lps)
+                               pp = NULL;
+                       continue;
+
+               } else if (SCF_LEX_WORD_LP == w->type)
+                       n_lps++;
+               else if (SCF_LEX_WORD_RP == w->type) {
+                       n_rps++;
+
+                       if (n_rps > n_lps) {
+                               scf_lex_word_free(w);
+                               w = NULL;
+                               break;
+                       }
+               }
+
+               w->next = NULL;
+
+               if (pp)
+                       *pp = w;
+               else {
+                       ret = scf_vector_add(argv, w);
+                       if (ret < 0) {
+                               scf_lex_word_free(w);
+                               goto error;
+                       }
+               }
+
+               pp = &w->next;
+               w  = NULL;
+       }
+
+       if (m->argv->size != argv->size) {
+               scf_loge("macro '%s' needs %d args, but in fact give %d args,  file: %s, line: %d\n",
+                               m->w->text->data, m->argv->size, argv->size, use->file->data, use->line);
+               ret = -1;
+               goto error;
+       }
+
+       return 0;
+
+error:
+       for (i = 0; i < argv->size; i++) {
+               w  =        argv->data[i];
+               scf_slist_clear(w, scf_lex_word_t, next, scf_lex_word_free);
+       }
+
+       argv->size = 0;
+       return ret;
+}
+
+static int __convert_str(scf_lex_word_t* h)
+{
+       scf_lex_word_t* w;
+       scf_string_t*   s;
+
+       if (h->type != SCF_LEX_WORD_CONST_STRING) {
+               h->type  = SCF_LEX_WORD_CONST_STRING;
+
+               h->data.s = scf_string_clone(h->text);
+               if (!h->data.s)
+                       return -ENOMEM;
+       }
+
+       for (w = h->next; w; w = w->next) {
+
+               if (SCF_LEX_WORD_CONST_STRING != w->type)
+                       s = w->text;
+               else
+                       s = w->data.s;
+
+               int ret = scf_string_cat(h->data.s, s);
+               if (ret < 0)
+                       return ret;
+       }
+
+       scf_logw("h: %s, file: %s, line: %d\n", h->data.s->data, h->file->data, h->line);
+       return 0;
+}
+
 static int __use_macro(scf_lex_t* lex, scf_lex_word_t** pword, scf_lex_word_t* w)
 {
        scf_lex_word_t** pp;
        scf_lex_word_t*  p;
        scf_lex_word_t*  h;
+       scf_vector_t*    argv = NULL;
        scf_macro_t*     m;
 
        if (!lex->macros) {
@@ -1218,23 +1342,114 @@ static int __use_macro(scf_lex_t* lex, scf_lex_word_t** pword, scf_lex_word_t* w
                return 0;
        }
 
+       if (m->argv) {
+               argv = scf_vector_alloc();
+               if (!argv) {
+                       scf_lex_word_free(w);
+                       return -ENOMEM;
+               }
+
+               int ret = __fill_macro_argv(lex, m, w, argv);
+               if (ret < 0) {
+                       scf_lex_word_free(w);
+                       scf_vector_free(argv);
+                       return ret;
+               }
+       }
+
        scf_lex_word_free(w);
-       w = NULL;
+       w  = NULL;
 
        h  = NULL;
        pp = &h;
+
+       int ret  = 0;
+       int hash = 0;
+
        for (p = m->text_list; p; p = p->next) {
 
-               w  = scf_lex_word_clone(p);
-               if (!w) {
-                       scf_slist_clear(h, scf_lex_word_t, next, scf_lex_word_free);
-                       return -ENOMEM;
+               if (SCF_LEX_WORD_HASH == p->type) {
+                       hash = 1;
+                       continue;
                }
 
-               *pp =  w;
-               pp  = &w->next;
+               if (SCF_LEX_WORD_HASH2 == p->type) {
+                       hash = 2;
+                       continue;
+               }
+
+               if (m->argv) {
+                       assert(argv);
+                       assert(argv->size >= m->argv->size);
+
+                       for (i = 0; i < m->argv->size; i++) {
+                               w  =        m->argv->data[i];
+
+                               if (!scf_string_cmp(w->text, p->text))
+                                       break;
+                       }
+
+                       if (i < m->argv->size) {
+                               w    = argv->data[i];
+
+                               if (1 == hash) {
+                                       ret = __convert_str(w);
+                                       if (ret < 0)
+                                               goto error;
+
+                                       scf_slist_clear(w->next, scf_lex_word_t, next, scf_lex_word_free);
+                                       w->next = NULL;
+                               }
+
+                               *pp = w;
+                               while (w) {
+                                       pp = &w->next;
+                                       w  =  w->next;
+                               }
+
+                               argv->data[i] = NULL;
+
+                               hash = 0;
+                               continue;
+                       }
+               }
+
+               *pp = scf_lex_word_clone(p);
+               if (!*pp) {
+                       ret = -ENOMEM;
+                       goto error;
+               }
+
+               pp = &(*pp)->next;
+
+               hash = 0;
+       }
+
+error:
+       if (argv) {
+               for (i = 0; i < argv->size; i++) {
+                       w  =        argv->data[i];
+
+                       if (w)
+                               scf_slist_clear(w, scf_lex_word_t, next, scf_lex_word_free);
+               }
+
+               scf_vector_free(argv);
+               argv = NULL;
        }
 
+       if (ret < 0) {
+               scf_slist_clear(h, scf_lex_word_t, next, scf_lex_word_free);
+               return ret;
+       }
+
+#if 0
+       w = h;
+       while (w) {
+               scf_logi("---------- %s, line: %d\n", w->text->data, w->line);
+               w = w->next;
+       }
+#endif
        *pp            = lex->word_list;
        lex->word_list = h;
 
index 7b1d55d755b628db842134ce05ea5a24c8055abd..8f94494e6ad78cbb708e563906b98c57f5539f15 100644 (file)
@@ -5,14 +5,14 @@ int main(int argc, char* argv[])
        scf_lex_t*      lex = NULL;
 
        if (scf_lex_open(&lex, argv[1]) < 0) {
-               printf("%s(),%d, error: \n", __func__, __LINE__);
+               scf_loge("\n");
                return -1;
        }
 
        scf_lex_word_t* w = NULL;
        while (1) {
                if (scf_lex_pop_word(lex, &w) < 0) {
-                       printf("%s(),%d, error: \n", __func__, __LINE__);
+                       scf_loge("\n");
                        return -1;
                }
 
@@ -31,7 +31,7 @@ int main(int argc, char* argv[])
                printf("\n");
 
                if (SCF_LEX_WORD_EOF == w->type) {
-                       printf("%s(),%d, eof\n", __func__, __LINE__);
+                       scf_logi("eof\n");
                        break;
                }
 
@@ -39,6 +39,6 @@ int main(int argc, char* argv[])
                w = NULL;
        }
 
-       printf("%s(),%d, main ok\n", __func__, __LINE__);
+       scf_logi("main ok\n");
        return 0;
 }
index 5a6e5899d21b9f2426e760f03c14249f6487641b..edc2ede952472b776e54d53f4cf2d5e1b598177b 100644 (file)
@@ -13,10 +13,9 @@ scf_char_t* _lex_pop_char(scf_lex_t* lex)
                return c;
        }
 
-       c = malloc(sizeof(scf_char_t));
+       c = calloc(1, sizeof(scf_char_t));
        if (!c)
                return NULL;
-       c->next = NULL;
 
        int ret = fgetc(lex->fp);
        if (EOF == ret) {
index 2c14d165a9fd74aea9e4f5977625bc2d1197a1e0..e9cbba651328cb4ab6152422f113dd6a01bb3eaf 100644 (file)
@@ -399,7 +399,7 @@ static int _scf_dfa_node_parse_word(scf_dfa_t* dfa, scf_dfa_node_t* node, scf_ve
                scf_logd("pop w->type: %d, '%s', line: %d, pos: %d\n", w->type, w->text->data, w->line, w->pos);
 
        } else if (SCF_DFA_OK == ret) {
-               scf_logi("SCF_DFA_OK\n");
+               scf_logi("SCF_DFA_OK\n\n");
                return SCF_DFA_OK;
 
        } else if (SCF_DFA_CONTINUE == ret) {