You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
<p>The attribute stack consists of attributes of tokens as well as synthesized attributes. The macro YYSTYPE denotes the type of the attribute stack. For example, in the above production, $$,$1 and $3 are all of the type YYSTYPE. YYSTYPE is int by default. The macro definition
797
+
<p>The attribute stack consists of attributes of tokens as well as synthesized attributes. The macro YYSTYPE denotes the type of the attribute stack. For example, in the above production, $$,$1 and $3 are all of the type YYSTYPE. YYSTYPE is <i>int </i>by default. The macro definition
798
798
</p>
799
799
<divclass="syntax">
800
800
#define YYSTYPE int
801
801
</div>
802
802
<p>can be found in the y.tab.c file. YACC automatically declares yylval to be of the type YYSTYPE.
803
-
</p><p>Since by default, YACC defines YYSTYPE to be the type int, only integer valued attributes can be passed from yylex() to yyparse() and only integer attributes can be synthesized by default. If we were to attempt to assign any other value to yylval or any of the attribute stack variables, a type error would be flagged on compiling y.tab.c using gcc.
803
+
</p><p>Since by default, YACC defines YYSTYPE to be the type int, only integer valued attributes can be passed from yylex() to yyparse() using the variable <i>yylval</i>and only integer attributes can be synthesized by default. If we were to attempt to assign any other value to <i>yylval</i> or any of the attribute stack variables, a type error would be flagged on compiling y.tab.c using gcc.
804
804
</p><p>We will now see how to handle attributes of types other than integer.
805
805
</p><p>The default definition of YYSTYPE can overriden with any built-in or userdefined data type. For example if we wanted to print the prefix form of an expression:
806
806
</p>
@@ -812,7 +812,7 @@ <h3>YYSTYPE</h3>
812
812
<divclass="syntax">#define YYSTYPE char</div>
813
813
<p>In general, YACC sets the type of yylval to that defined by YYSTYPE. Hence, in this case, only character variables and constants can be assigned to yylval.</p>
814
814
815
-
<p>But in order to have multiple custom attribute values, YACC offers a useful feature called %unionto customize the type of YYSTYPE. %unionis useful when we require to have different tokens of different types. For example if we wanted some tokens to be of the type int and some tokens to be of the type char. The following code segment can be added to declarations section of the YACC program to achieve that.</p>
815
+
<p>But in order to have multiple custom attribute values, YACC offers a useful feature called <i>%union</i> declaration to customize the type of YYSTYPE. <i>%union</i> declaration is useful when we require to have different tokens return attributes of different types using <i>yylval</i>. For example if we wanted some tokens to be of the type int and some tokens to be of the type char, the following code segment may be added to the declaration section of the YACC program.</p>
816
816
817
817
<pre>
818
818
/* YACC Auxiliary declarations*/
@@ -874,7 +874,14 @@ <h3>Exercise:</h3>
874
874
<p><b>Sample input:</b> hello+my*world</p>
875
875
<p><b>Sample output:</b> + hello * my world</p>
876
876
877
-
<p>IMPORTANT NOTE: Now the attribute values to be passed are strings like “hello”. Hence YYSTYPE has to be set to char*. YACC sets the type of yylval to char*. Hence yylval can hold a pointer to a character string. Note that yytext holds the lexeme that was most recently read by yylex(). Hence, if we were to assign yytext directly to yylval, then yylval would point to this lexeme as required. When yylex() returns the token to yyparse(), this pointer gets pushed to the attribute stack corresponding to the token. However, this method fails because the location that yytext points to gets overwritten when the next lexeme is read from the input by yylex(). Hence the previously read string would be lost from that location. This corrupts the data referenced by the pointer in the attribute stack. To avoid this problem, separate memory should be allocated (using malloc) and the string in yytext should be copied (using strcpy) to this memory and yylval should be set to the newly allocated store. (Alternately the library function strdup may be used. This function allocates a new space, duplicates the string provided as input into this space and returns pointer to it.)
877
+
<p>IMPORTANT NOTE: Now the attribute values to be passed are strings like “hello”. The simple way to do this is to set YYSTYPE has to be set to char* and pass strings from the lexer to the parser using <i>yylval</i>. To achieve this, we may declare:
878
+
<pre>
879
+
%union{
880
+
char *c;
881
+
}
882
+
</pre>
883
+
884
+
YACC sets the type of yylval to char*. Hence yylval can hold a pointer to a character string. Note that yytext holds the lexeme that was most recently read by yylex(). Hence, if we were to assign yytext directly to yylval, then yylval would point to this lexeme as required. When yylex() returns the token to yyparse(), this pointer gets pushed to the attribute stack corresponding to the token. However, this method fails because the location that yytext points to gets overwritten when the next lexeme is read from the input by yylex(). Hence the previously read string would be lost from that location. This corrupts the data referenced by the pointer in the attribute stack. To avoid this problem, separate memory should be allocated (using malloc) and the string in yytext should be copied (using strcpy) to this memory and yylval should be set to the newly allocated store. (Alternately the library function strdup may be used. This function allocates a new space, duplicates the string provided as input into this space and returns pointer to it.)
0 commit comments