I want to complete a parsing about varlist declaration,
like varlist:id comma varlist|id.
At this time, I need to set up a list about var
.
So I write this code:
varlist: id comma varlist{ createtnode($1.idcontext);}
|id{createtnode($1.idcontext);};
But I find $1.idcontext
is not that idcontext
I want which should be this id token's idcontext.
Now, $1.idcontext
is this sentence 'varlist'. Without the code action, this grammar works correctly.
typedef struct{
int* TC;
int* FC;
}boolcode;
typedef struct {
char* idcontext;
int constvalue;
int chain;
boolcode ftentry;
}includes;
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef struct{
int classify;
includes unique;
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define YYSTYPE_IS_DECLARED 1
#endif
VARList: IDENcode COMMA VARList{
if(YYDEBUG)
{printf("6\n");
printf("%s\n",$1.idcontext);
}
varlistnode* newvar=malloc(sizeof(varlistnode));
newvar->varname=$1.idcontext;
newvar->value=0;
newvar->next=NULL;
mynotes->next=newvar;
mynotes=mynotes->next;
}|IDENcode{
if(YYDEBUG)
{printf("7\n");printf("%s\n",$1.idcontext);}
varlistnode* newvar=malloc(sizeof(varlistnode));
newvar->varname=$1.idcontext;
newvar->value=0;
newvar->next=NULL;
mynotes->next=newvar;
mynotes=mynotes->next;
};
The words wait recognize:
a,b,c,d
The result of printf()
function:
7
d:
6
c,d:
6
b,c,d:
6
a,b,c,d:enter code here
The real problem in this program is not visible in this question because the bug is in your lexical scanner.
You haven't included the flex file in the question, but it's reasonable to guess that it contains something like this:
[[:alpha:]_][[:alnum:]_]* { yylval.unique.idcontext = yytext; /* INCORRECT */
return IDENcode;
}
It should read
[[:alpha:]_][[:alnum:]_]* { yylval.unique.idcontext = strdup(yytext);
return IDENcode;
}
yytext
points into the scanner's internal buffer, whose contents are modified every time the scanner is called. What you're seeing is a mild version of this problem, because your input is very short; if the input were long enough that yylex
needed to refill the buffer from the input file, then you would see complete garbage in your idcontext
fields. If you want to use the string later, you need to make a copy of it (and then you need to remember to free()
the copy when you no longer need it, which can be a bit of a challenge.)
The other possible issue -- and honestly I don't know whether you consider it a problem or not, because you did not specify what output you expect from your debugging trace -- is that your right-recursive rule:
varlist: id comma varlist { createtnode($1.idcontext); }
| id { createtnode($1.idcontext); }
ends up calling createtnode
on the id
s in reverse order, because a bison reduction action is executed when the rule is matched. Using right-recursion like that means that the first varlist
action to execute is actually the one corresponding to the last id
.
If you want the actions to execute left to right, you need to use left-recursion:
varlist: varlist comma id { createtnode($3.idcontext); } /* See below */
| id { createtnode($1.idcontext); }
Left-recursion has other advantages. For example, it does not require all the id
s (and comma
s) to pile up on the parser's internal stack waiting for the final reduction action.
Again, you don't show enough of your code to see how you use the result of these actions. It looks to me like you're trying to create a global linked list of variables, whose header you store in a global variable. (mynotes
evidently points to the tail of the list, so it can't be used to recover the head.) If that's the case, then the change above should work fine. But it would be more normal to make the semantic value of varlist
a list header, avoiding the use of global variables. That would result in code which looked more like this:
varlist: id comma varlist { $$ = append($1, createtnode($3.idcontext)); }
| id { $$ = append(newlist(), createtnode($1.idcontext); }