Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在bison/yacc语义操作中构建异构数据类型数组(或集合)的最佳方法_C_Bison_Yacc - Fatal编程技术网

在bison/yacc语义操作中构建异构数据类型数组(或集合)的最佳方法

在bison/yacc语义操作中构建异构数据类型数组(或集合)的最佳方法,c,bison,yacc,C,Bison,Yacc,可以将其视为一组元素,这些元素不一定都是同一类型的。我有以下代码: // The struct I'll use inside Bison to dynamically create collections: typedef struct ListElementType { union value { int intVal; float floatVal; char* charptrVal; } value; struct

可以将其视为一组元素,这些元素不一定都是同一类型的。我有以下代码:

// The struct I'll use inside Bison to dynamically create collections:
typedef struct ListElementType {
    union value {
        int intVal;
        float floatVal;
        char* charptrVal;
    } value;

    struct ListElementType* next;
} ListElementType;
在Bison,我有:

%union
{
    int int_type;
    char char_type;
    float float_type;
    char* charptr_type;
    ListElementType* listElementType;
}
//----------------------------------------------------
%token <charptr_type> STRING
%token <int_type> INTEGER
%token <float_type> REAL
%type<listElementType> ElementList
//----------------------------------------------------
//----------------------------------------------------
ElementList
: ElementList ',' LiteralType
{ 
    $$ = malloc(sizeof(listElementType));
    $$->next = $1;
    $$->value = $3;
}

| LiteralType
{ 
    $$ = malloc(sizeof(listElementType));
    $$->next = 0;
    $$->value = $1;
}
;
//----------------------------------------------------
LiteralType
: STRING
| INTEGER
| REAL
;
或者有没有一种方法可以声明LiteralType可以有三个值中的任意一个,然后尝试提取无类型联合赋值


或者整个方法都错了,还有更好的方法吗?

我认为您忽略了一个事实,即Bison没有尝试实现完整的C类型检查。因为您为STRING和LiteralType指定了不同的类型名称,所以它的任务是报告它的默认操作($$=$1)从(bison)类型检查的角度来看做了一些奇怪的事情。如果您确实想使用默认赋值,只需给它们相同的类型(在您的情况下为值)

此外,您编码的并集值是并集值的两倍,这似乎不是必需的:

%code requires
{
  typedef struct ListElementType {
    union value {
      int intVal;
      float floatVal;
      char* charptrVal;
    } value;

    struct ListElementType* next;
  } ListElementType;
}

%union
 {
   union value value;
   ListElementType* list;
 };

%token <value> STRING INTEGER REAL
%type <value> LiteralType 
%type <list> ElementList
%%
ElementList
: ElementList ',' LiteralType
{ 
  $$ = malloc(sizeof($$));
  $$->next = $1;
  $$->value = $3;
}
| LiteralType
{ 
  $$ = malloc(sizeof($$));
  $$->next = 0;
  $$->value = $1;
}
;
//----------------------------------------------------
LiteralType
: STRING
| INTEGER
| REAL
;
%代码需要
{
类型定义结构ListElementType{
联合价值{
int intVal;
浮球浮球;
char*charptrVal;
}价值观;
结构ListElementType*下一步;
}李斯特类型;
}
%联合
{
联合价值;
ListElementType*列表;
};
%令牌字符串整数实数
%类型文字类型
%类型元素列表
%%
元素列表
:ElementList','LiteralType
{ 
$$=malloc(sizeof($);
$$->next=$1;
$$->value=$3;
}
|文字类型
{ 
$$=malloc(sizeof($);
$$->next=0;
$$->value=$1;
}
;
//----------------------------------------------------
文字类型
:字符串
|整数
|真实的
;

我最终选择了这种方法

  • 请注意,不是让元素生产(ex-LiteralType nonterminal)简化为一个union,而是简化为一个具有union和类型成员的结构。类型成员是告诉集合中存储的每个元素的类型的方法
  • 还要注意,ListType结构有一个指向元素的void*指针。在这个精心设计的示例中,ElementType结构类型的成员就足够了。然而,我正在使元素成为一个通用指针,以使用相同的结构依次存储由元素列表组成的声明列表 %代码要求 { 类型定义结构元素{

    %code requires {
        typedef struct Element {
            union {
                int intVal;
                float floatVal;
                char* charptrVal;            
            };
    
        char type;
    
        } ElementType;
    
        typedef struct ListType {
            void* element;
            struct ListType* next;
    
        } ListType;
    }
    
    %union
    {
        int int_type;
        char char_type;
        float float_type;
        char* charptr_type;
        ListType* ListType;
        ElementType* ElementType;
    }
    
    
    
    %token <charptr_type> KEYWORD
    %token <charptr_type> ID
    %token <charptr_type> STRING
    %token <int_type> INTEGER
    %token <float_type> REAL
    %token END 0
    
    
    %type<ElementType> Element
    %type<ListType> ElementList
    
    //----------------------------------------------------
    ElementList
    : Element ',' ElementList
    {
        $$ = malloc(sizeof(ListType));
        $$->element = (void*)$1;
        $$->next = $3;
    }
    
    | Element
    {
        $$ = malloc(sizeof(ListType));
        $$->element = (void*)$1;
        $$->next = NULL;
    }
    ;
    //----------------------------------------------------
    Element
    : STRING
    {
        char* aString = malloc(sizeof(char)*strlen($1)+1);
        strcpy(aString, $1);
        free(yylval.charptr_type);
    
        $$ = malloc(sizeof(ElementType));
        $$->charptrVal = aString;
        $$->type = 's';
    }
    | INTEGER
    {
        $$ = malloc(sizeof(ElementType));
        $$->intVal = $1;
        $$->type = 'i';
    }
    
    | REAL
    {
        $$ = malloc(sizeof(ElementType));
        $$->floatVal = $1;
        $$->type = 'f';    
    }
    ;
    
    %代码需要{
    类型定义结构元素{
    联合{
    int intVal;
    浮球浮球;
    char*charptrVal;
    };
    煤焦类型;
    }元素类型;
    类型定义结构列表类型{
    void*元素;
    结构ListType*next;
    }列表类型;
    }
    %联合
    {
    int_型;
    字符型;
    浮球型;
    char*charptr_类型;
    ListType*ListType;
    ElementType*ElementType;
    }
    %令牌关键字
    %令牌ID
    %令牌串
    %令牌整数
    %象征性真实
    %令牌端0
    %类型元素
    %类型元素列表
    //----------------------------------------------------
    元素列表
    :元素“,”元素列表
    {
    $$=malloc(sizeof(ListType));
    $$->element=(void*)$1;
    $$->next=$3;
    }
    |元素
    {
    $$=malloc(sizeof(ListType));
    $$->element=(void*)$1;
    $$->next=NULL;
    }
    ;
    //----------------------------------------------------
    元素
    :字符串
    {
    char*aString=malloc(sizeof(char)*strlen($1)+1);
    strcpy(阿斯汀,1美元);
    免费(yylval.charptr_型);
    $$=malloc(sizeof(ElementType));
    $$->charptrVal=aString;
    $$->type='s';
    }
    |整数
    {
    $$=malloc(sizeof(ElementType));
    $$->intVal=$1;
    $$->type='i';
    }
    |真实的
    {
    $$=malloc(sizeof(ElementType));
    $$->floatVal=$1;
    $$->type='f';
    }
    ;
    
    通常,您要做的是在异构列表类型中有一个类型标记:

    typedef enum ListElementType { INTEGER, REAL, STRING } ListElementType
    typedef struct ListElement {
        ListElementType  type;
        union {
            int intVal;
            float floatVal;
            char* charptrVal;
        } value;
        struct ListElement* next;
    } ListElement;
    
    然后,无论何时创建ListElement,都可以适当地设置
    类型
    字段。稍后,您可以检查
    类型
    字段以查看它是什么

    您的野牛代码将变为:

    %union
    {
        int int_type;
        char char_type;
        float float_type;
        char* charptr_type;
        ListElement* listElement;
        struct { ListElement *head, *tail } list;
    }
    //----------------------------------------------------
    %token <charptr_type> STRING
    %token <int_type> INTEGER
    %token <float_type> REAL
    %type<list> ElementList
    %type<listElement> LiteralType
    //----------------------------------------------------
    %%
    //----------------------------------------------------
    ElementList
    : ElementList ',' LiteralType
        { $$.head = $1.head;
          $$.tail = $1.tail->next = $3; }
    | LiteralType
        { $$.head = $$.tail = $1; }
    ;
    //----------------------------------------------------
    LiteralType
    : STRING  { ($$ = NewListElement(STRING))->value.charptrVal = $1; }
    | INTEGER { ($$ = NewListElement(INTEGER))->value.intVal = $1; }
    | REAL    { ($$ = NewListElement(REAL))->value.floatVal = $1; }
    ;
    %%
    ListElement *NewListElement(ListElementType type) {
        ListElement *rv = malloc(sizeof(ListElement));
        rv->type = type;
        rv->next = 0;
        return rv; }
    
    %union
    {
    int_型;
    字符型;
    浮球型;
    char*charptr_类型;
    ListElement*ListElement;
    结构{ListElement*head,*tail}列表;
    }
    //----------------------------------------------------
    %令牌串
    %令牌整数
    %象征性真实
    %类型元素列表
    %类型文字类型
    //----------------------------------------------------
    %%
    //----------------------------------------------------
    元素列表
    :ElementList','LiteralType
    {$$.head=$1.head;
    $$.tail=$1.tail->next=$3;}
    |文字类型
    {$$.head=$$.tail=$1;}
    ;
    //----------------------------------------------------
    文字类型
    :STRING{($=NewListElement(STRING))->value.charptrVal=$1;}
    |整数{($=NewListElement(整数))->value.intVal=$1;}
    |REAL{($=NewListElement(REAL))->value.floatVal=$1;}
    ;
    %%
    ListElement*NewListElement(ListElementType类型){
    ListElement*rv=malloc(sizeof(ListElement));
    rv->type=type;
    rv->next=0;
    返回rv;}
    
    我明白你的意思,但如果我举你的例子,Bison仍然会为LiteralType默认赋值提供类型冲突:!=!=!=!=此外,即使我将自己$$.intVal=$1;,等等添加到文字的每个动作中,Bison也不再抱怨,但现在gcc抱怨ListermentType是未知类型否,它不会报告冲突。您可能已经删除了我指定的
    %type LiteralType
    ,并且您还保留了所有更改的
    %token
    。因此,实际上,除了我回答的内容之外,您可能会得到不同的结果:)1-我的版本(2.6)仍然需要我在LiteralType产品中显式地完成赋值。没有它们,它就无法完成赋值并报告冲突。2-添加此项实际上解决了问题。3-ListermentType未知类型是由于bison 2.3(当我切换到2.6时,它消失了)4-我看不出我在哪里对联合进行了两次编码。5-为什么你要声明STRING、REAL和INTEGER与LiteralType属于同一类型,而它们不是。这3个是标记/终端。它们不是非终端,并且具有特定的类型。6-t
    typedef enum ListElementType { INTEGER, REAL, STRING } ListElementType
    typedef struct ListElement {
        ListElementType  type;
        union {
            int intVal;
            float floatVal;
            char* charptrVal;
        } value;
        struct ListElement* next;
    } ListElement;
    
    %union
    {
        int int_type;
        char char_type;
        float float_type;
        char* charptr_type;
        ListElement* listElement;
        struct { ListElement *head, *tail } list;
    }
    //----------------------------------------------------
    %token <charptr_type> STRING
    %token <int_type> INTEGER
    %token <float_type> REAL
    %type<list> ElementList
    %type<listElement> LiteralType
    //----------------------------------------------------
    %%
    //----------------------------------------------------
    ElementList
    : ElementList ',' LiteralType
        { $$.head = $1.head;
          $$.tail = $1.tail->next = $3; }
    | LiteralType
        { $$.head = $$.tail = $1; }
    ;
    //----------------------------------------------------
    LiteralType
    : STRING  { ($$ = NewListElement(STRING))->value.charptrVal = $1; }
    | INTEGER { ($$ = NewListElement(INTEGER))->value.intVal = $1; }
    | REAL    { ($$ = NewListElement(REAL))->value.floatVal = $1; }
    ;
    %%
    ListElement *NewListElement(ListElementType type) {
        ListElement *rv = malloc(sizeof(ListElement));
        rv->type = type;
        rv->next = 0;
        return rv; }