如何在 Bison 解析器上返回多个标记?

发布于 2024-12-12 07:54:10 字数 282 浏览 0 评论 0原文

我的语法是这样的

decl:

   attributes;  {/*create an object here with the attributes $$?*/ }


attributes:



  |

  att1 attributes {$$ = $1;}

  |

  att2 attributes {$$ = $1;}

  |

  attn attributes {$$ = $1;};

我想获取用户输入的所有属性,其中一些是可选的,顺序无关紧要,类型不同

My grammar is something like this

decl:

   attributes;  {/*create an object here with the attributes $?*/ }


attributes:



  |

  att1 attributes {$ = $1;}

  |

  att2 attributes {$ = $1;}

  |

  attn attributes {$ = $1;};

I want to get all the attributes entered by the user, some of them are optional and the order doesn't matter, types are different

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

演多会厌 2024-12-19 07:54:10

您需要在 $$ 变量中返回一个结构;根据需要分配给其成员。这是我手头上的一些代码的示例:

struct value_list {
    char *value;
    struct value_list *next;
};

# ...

valuelist:  TOK_VALUE
    {
        struct value_list *new = calloc(1, sizeof(struct value_list));
        if (!new)
            yyerror(_("Memory allocation error."));
        PDEBUG("Matched: value (%s)\n", $1);

        new->value = $1;
        new->next = NULL;
        $ = new;
    }

valuelist:  valuelist TOK_VALUE
    {
        struct value_list *new = calloc(1, sizeof(struct value_list));
        if (!new)
            yyerror(_("Memory allocation error."));
        PDEBUG("Matched: value (%s)\n", $1);

        new->value = $2;
        new->next = $1;
        $ = new;
    }

来自同一解析器的另一个示例,与上述更简单的规则相比,它在基于条目自定义 struct 方面付出了更多的努力;缺点是这变得相当复杂,但优点是这是对单个对象属性的更好演示:

/* from a header file */
struct codomain {
    char *namespace;
    char *name;             /* codomain name */
    char *attachment;
    struct alt_name *altnames;
    void *xmatch;
    size_t xmatch_size;
    int xmatch_len;
    /* ... and it goes on like this ... */
}

# from the grammar:

profile_base: TOK_ID opt_id flags TOK_OPEN rules TOK_CLOSE
    {
        struct codomain *cod = $5;

        if (!cod) {
            yyerror(_("Memory allocation error."));
        }

        cod->name = $1;
        cod->attachment = $2;
        if ($2 && $2[0] != '/')
            /* we don't support variables as part of the profile
             * name or attachment atm
             */
            yyerror(_("Profile attachment must begin with a '/'."));
        cod->flags = $3;
        if (force_complain)
            cod->flags.complain = 1;

        post_process_nt_entries(cod);
        PDEBUG("%s: flags='%s%s'\n",
               $3,
               cod->flags.complain ? "complain, " : "",
               cod->flags.audit ? "audit" : "");

        $ = cod;

    };

You need to return a structure in your $$ variable; assign to its members as you need to. Here's an example from some code I have handy:

struct value_list {
    char *value;
    struct value_list *next;
};

# ...

valuelist:  TOK_VALUE
    {
        struct value_list *new = calloc(1, sizeof(struct value_list));
        if (!new)
            yyerror(_("Memory allocation error."));
        PDEBUG("Matched: value (%s)\n", $1);

        new->value = $1;
        new->next = NULL;
        $ = new;
    }

valuelist:  valuelist TOK_VALUE
    {
        struct value_list *new = calloc(1, sizeof(struct value_list));
        if (!new)
            yyerror(_("Memory allocation error."));
        PDEBUG("Matched: value (%s)\n", $1);

        new->value = $2;
        new->next = $1;
        $ = new;
    }

Another example from the same parser, which puts more effort into customizing a struct based on an entry than the above simpler rules; the downside is that this is getting quite complex, but the upside is that this is a better demonstration of attributes of a single object:

/* from a header file */
struct codomain {
    char *namespace;
    char *name;             /* codomain name */
    char *attachment;
    struct alt_name *altnames;
    void *xmatch;
    size_t xmatch_size;
    int xmatch_len;
    /* ... and it goes on like this ... */
}

# from the grammar:

profile_base: TOK_ID opt_id flags TOK_OPEN rules TOK_CLOSE
    {
        struct codomain *cod = $5;

        if (!cod) {
            yyerror(_("Memory allocation error."));
        }

        cod->name = $1;
        cod->attachment = $2;
        if ($2 && $2[0] != '/')
            /* we don't support variables as part of the profile
             * name or attachment atm
             */
            yyerror(_("Profile attachment must begin with a '/'."));
        cod->flags = $3;
        if (force_complain)
            cod->flags.complain = 1;

        post_process_nt_entries(cod);
        PDEBUG("%s: flags='%s%s'\n",
               $3,
               cod->flags.complain ? "complain, " : "",
               cod->flags.audit ? "audit" : "");

        $ = cod;

    };
寒江雪… 2024-12-19 07:54:10
struct objectStruct{
  char* name;
  int value;
  objectStruct next;
  //...
}

现在语法

decl:
  attributes {
    objectStruct* myObject = $1;
    while(myObject!=NULL){
       if(myObject->name!=NULL){
          //do something with name
          myObject=myObject->next;
       }
       else if(myObject->value!=NULL){
          //do something with value
          myObject=myObject->next;
       }
       //...
     }
  };

attributes:
 {$=NULL;} 
|
 NAME attributes {
   objectStruct* myObject = new objectStruct();
   myObject->name = $1;
   myObject->value = NULL;
   myObject->next = $2;
   $=myObject;
}
|
 VALUE attributes {
   objectStruct* myObject = new objectStruct();
   myObject->value = $1;
   myObject->name= NULL;
   myObject->next = $2;
   $=myObject;
}
//...
;
struct objectStruct{
  char* name;
  int value;
  objectStruct next;
  //...
}

now the grammar

decl:
  attributes {
    objectStruct* myObject = $1;
    while(myObject!=NULL){
       if(myObject->name!=NULL){
          //do something with name
          myObject=myObject->next;
       }
       else if(myObject->value!=NULL){
          //do something with value
          myObject=myObject->next;
       }
       //...
     }
  };

attributes:
 {$=NULL;} 
|
 NAME attributes {
   objectStruct* myObject = new objectStruct();
   myObject->name = $1;
   myObject->value = NULL;
   myObject->next = $2;
   $=myObject;
}
|
 VALUE attributes {
   objectStruct* myObject = new objectStruct();
   myObject->value = $1;
   myObject->name= NULL;
   myObject->next = $2;
   $=myObject;
}
//...
;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文