2009-12-05 35 views
14

Mục đích của nghiệp đoàn trong tệp yacc là gì? Nó có liên quan trực tiếp đến yylval trong tập tin flex? Nếu bạn không sử dụng yylval, sau đó bạn không cần phải sử dụng công đoàn?yylval và union

Trả lời

11

Tuyên bố %union sửa đổi loại yylval.

Các bison thủ explains:

Trong một (nonreentrant) thường phân tích cú pháp, giá trị ngữ nghĩa của các dấu hiệu phải được lưu trữ vào biến toàn cầu yylval. Khi bạn đang sử dụng chỉ một loại dữ liệu cho các giá trị ngữ nghĩa, yylval có loại đó. Như vậy, nếu loại là int (mặc định), bạn có thể viết những dòng này trong yylex:

... 
yylval = value; /* Put value onto Bison stack. */ 
return INT;  /* Return the type of the token. */ 
... 

Khi bạn đang sử dụng nhiều loại dữ liệu, loại yylval 's là một sự kết hợp làm từ việc kê khai %union (xem phần Các Bộ sưu tập các loại giá trị). Vì vậy, khi bạn lưu trữ giá trị của một mã thông báo, bạn phải sử dụng thành viên thích hợp của công đoàn. Nếu việc kê khai %union trông như thế này:

%union { 
    int intval; 
    double val; 
    symrec *tptr; 
} 

sau đó các mã trong yylex có thể trông như thế này:

... 
yylval.intval = value; /* Put value onto Bison stack. */ 
return INT;   /* Return the type of the token. */ 
... 
21

Mục đích của union là cho phép lưu trữ loại khác nhau của các đối tượng vào các nút phát ra bởi flex.

Để giải thích rõ hơn bạn có thể có ví dụ:

%union 
{ 
    int intValue; 
    float floatValue; 
    char *stringValue; 
} 

trong .y nếu bạn muốn cung cấp hỗ trợ cơ bản cho int, floatstring loại. Bạn có thể làm gì với điều này?

Hai điều:

Trước tiên, bạn có thể tự động đặt giá trị phù hợp khi tạo mã thông báo. Hãy suy nghĩ về .l tập tin của ví dụ trước, bạn có thể có:

[a-zA-Z][a-zA-Z0-9]* { 
yylval.stringValue = strdup(yytext); 
return IDENTIFIER; 
} 

[0-9]+ { 
yylval.intValue = atoi(yytext); 
return INTEGER; 
} 

[0-9]*\.[0-9]+"f"? { 
    yylval.floatValue = new atof(yytext); 
return FLOAT; 
} 

Bên cạnh đó bạn có thể sử dụng giá trị trực tiếp trong bạn flex ngữ pháp:

nexp: nexp '+' nexp { $<floatValue>$ = $<floatValue>1 + $<floatValue>3 } 

Cuối cùng nếu bạn có kế hoạch để sử dụng một cú pháp OOP cây bạn có thể xác định công đoàn là

%union 
{ 
    class ASTNode *node; 
} 

trong đó ASTNode là lớp tổ tiên của bất kỳ loại nào nút yntax.

+3

Tại sao xác định một liên kết của một phần tử? Tại sao không chỉ '#define YYSTYPE class ASTNode *' (nếu bộ nhớ phục vụ). –