Настоящая проблема в этой программе не видна в этом вопросе, потому что ошибка в вашем лексическом сканере.
Вы не включили файл flex в вопрос, но разумно предположить, что он содержит что-то вроде этого:
[[:alpha:]_][[:alnum:]_]* { yylval.unique.idcontext = yytext; /* INCORRECT */
return IDENcode;
}
Следует читать
[[:alpha:]_][[:alnum:]_]* { yylval.unique.idcontext = strdup(yytext);
return IDENcode;
}
yytext
указывает на внутренний буфер сканера, содержимое которого изменяется при каждом вызове сканера. То, что вы видите, является мягкой версией этой проблемы, потому что ваш вклад очень короткий; если бы ввод был достаточно длинным, чтобы yylex
требовалось заполнить буфер из входного файла, вы бы увидели полный мусор в ваших полях idcontext
. Если вы хотите использовать строку позже, вам нужно сделать ее копию (и затем вам нужно будет помнить free()
копию, когда она вам больше не нужна, что может быть сложной задачей).
Другая возможная проблема - и, честно говоря, я не знаю, считаете ли вы это проблемой или нет, потому что вы не указали, какой вывод вы ожидаете из своей трассировки отладки, - это ваше право -рекурсивное правило:
varlist: id comma varlist { createtnode($1.idcontext); }
| id { createtnode($1.idcontext); }
в итоге вызывает createtnode
на id
s в обратном порядке, потому что действие сокращения зубра выполняется , когда правило соответствует . Подобное использование правой рекурсии означает, что первое действие varlist
, которое нужно выполнить, фактически соответствует последнему id
.
Если вы хотите, чтобы действия выполнялись слева направо, вам нужно использовать левую рекурсию:
varlist: varlist comma id { createtnode($3.idcontext); } /* See below */
| id { createtnode($1.idcontext); }
Левая рекурсия имеет и другие преимущества. Например, не требуется, чтобы все id
s (и comma
s) накапливались во внутреннем стеке синтаксического анализатора в ожидании окончательного действия сокращения.
Опять же, вы не показываете достаточно своего кода, чтобы увидеть, как вы используете результат этих действий. Мне кажется, что вы пытаетесь создать глобальный связанный список переменных, заголовок которого вы храните в глобальной переменной. (mynotes
, очевидно, указывает на конец списка, поэтому его нельзя использовать для восстановления головы.) Если это так, то приведенные выше изменения должны работать нормально. Но было бы более нормально сделать семантическое значение varlist
заголовком списка, избегая использования глобальных переменных. Это приведет к коду, который будет выглядеть примерно так:
varlist: id comma varlist { $$ = append($1, createtnode($3.idcontext)); }
| id { $$ = append(newlist(), createtnode($1.idcontext); }