Беда с принтом в Бизоне - PullRequest
0 голосов
/ 22 августа 2010

Я пробовал что-то подобное в моем файле Bison ...

ReturnS: RETURN expression {printf(";")}

... но точка с запятой печатается ПОСЛЕ следующего токена, после этого правила, а не сразу после выражения.Это правило было разработано, поскольку мы должны преобразовать входной файл в форму, похожую на c, а исходный язык не требует точки с запятой после выражения в операторе возврата, но это делает C, поэтому я решил добавить еговручную на выход с помощью printf.Похоже, это не работает, так как точка с запятой добавляется, но по какой-то причине она добавляется после анализа следующего токена (вне правила ReturnS) вместо права, когда правило выражения возвращается в ReturnS.

Это правило также приводит к тому же результату:

loop_for: FOR var_name COLONEQUALS expression TO {printf("%s<=", $<chartype>2);} expression STEP {printf("%s+=", $<chartype>2);} expression {printf(")\n");} Code ENDFOR

Помимо первых двух printf не работает правильно (я напишу еще один вопрос относительно этого), последний printf фактически называется ПОСЛЕ первого токена / литералаПравило «Код» было проанализировано, в результате чего получилось что-то вроде этого:

for (i=0; i<=5; i+=1
a)
=a+1;

вместо

for (i=0; i<=5; i+=1)
a=a+1;

Есть идеи, что я делаю не так?

Ответы [ 2 ]

1 голос
/ 22 августа 2010

Возможно, потому что грамматика должна заглянуть на один токен, чтобы решить уменьшить ее по правилу, которое вы показываете.

Действие выполняется, когда правило сокращено, и очень типично, что грамматика должнапрочитайте еще один токен, прежде чем он узнает, что он может / должен уменьшить предыдущее правило.

Например, если выражение может состоять из неопределенной последовательности добавленных терминов, оно должно быть прочитано за пределами последнего термина, чтобы знать егоэто не еще один знак «+» для продолжения выражения.


После просмотра грамматики Yacc / Bison и анализатора Lex / Flex некоторые проблемы стали очевидны, а другим потребовалось немного больше разобраться.

  • Лексический анализатор выполнял большую часть печати, что означало, что грамматика неправильно контролировала то, что появилось когда.Анализатор делал слишком много.
  • Анализатор также не делал достаточно работы - возможно выполнение строк и чисел грамматического процесса по одному символу за раз, но излишне тяжелая работа.
  • Обработка комментариевсложно, если они должны быть сохранены.В обычном компиляторе C лексический анализатор выбрасывает комментарии;в этом случае комментарии должны были быть сохранены.Правило обработки этого было перенесено из грамматики (где оно вызывало сдвиг / уменьшение и уменьшение / уменьшение конфликтов из-за пустых строк, совпадающих с комментариями) в лексический анализатор.Это не всегда может быть оптимальным, но в этом контексте все работает нормально.
  • Лексический анализатор должен был гарантировать, что он возвращает подходящее значение для yylval, когда это значение необходимо.
  • грамматика, необходимая для распространения подходящих значений в $$, чтобы обеспечить наличие в правилах необходимой информации.Ключевые слова по большей части не нуждались в значении;такие вещи, как имена и числа переменных.
  • Грамматика должна была печатать в соответствующих местах.

Возвращенное прототипное решение имело большую утечку памяти, поскольку использовалось strdup()либерально и не использовал free() вообще.Убедиться в том, что утечки исправлены - возможно, с помощью массива char вместо указателя char для YYSTYPE - оставлено на OP.

0 голосов
/ 26 августа 2010

Комментарии не являются хорошим местом для предоставления примеров кода, поэтому я приведу пример кода, который работает после того, как Джонатан (ответил выше) поработал над моим кодом.Ему приписывают все должное, это не мое.

Вместо того, чтобы FLEX печатал какие-либо распознанные части и позволял BISON впоследствии выполнять форматирование, Джонатан предложил, чтобы FLEX ничего не печатал и возвращался только в BISON, что должно затемсправиться со всей печатью самостоятельно.

Итак, вместо чего-то подобного ...


FLEX

"FOR"   {printf("for ("); return FOR;}
"TO"    {printf("; "); return TO;}
"STEP"  {printf("; "); return STEP;}
"ENDFOR"    {printf("\n"); printf("}\n"); return ENDFOR;}
[a-zA-Z]+   {printf("%s",yytext); yylval.strV = yytext; return CHARACTERS;}
":="    {printf("="); lisnew=0; return COLONEQUALS;}

ЗУБР

loop_for:   FOR var_name {strcpy(myvar, $<strV>2);} COLONEQUALS expression TO {printf("%s<=", myvar);} expression STEP {printf("%s+=", myvar);} expression {printf(")\n");} Code ENDFOR

... он предложил это:


FLEX

[a-zA-Z][a-zA-Z0-9]*    { yylval = strdup(yytext); return VARNAME;}
[1-9][0-9]*|0           { yylval = strdup(yytext); return NUMBER; }

ЗУБР

loop_for:   FOR var_name COLONEQUALS NUMBER TO NUMBER STEP NUMBER
    { printf("for (%s = %s; %s <= %s; %s += %s)\n", $2, $4, $2, $6, $2, $8); }
var_name:   VARNAME
...