Ошибки при использовании зубров - PullRequest
1 голос
/ 11 октября 2009

Теперь я получаю другие вещи. Когда я делаю bison -d calc.y, я получаю много исходных кодов в консоли (со многими m4_define), но он не генерирует никаких файлов. Теперь мой код выглядит так:

%{
#define YYSTYPE double
#include <math.h>
%}
%token NUM
%%
input:    /* empty */
        | input line
;

line:     '\n'
        | exp '\n'  { printf ("\t%.10g\n", $1); }
;

exp:      NUM             { $$ = $1;         }
        | exp exp '+'     { $$ = $1 + $2;    }
        | exp exp '-'     { $$ = $1 - $2;    }
        | exp exp '*'     { $$ = $1 * $2;    }
        | exp exp '/'     { $$ = $1 / $2;    }
      /* Exponentiation */
        | exp exp '^'     { $$ = pow ($1, $2); }
      /* Unary minus    */
        | exp 'n'         { $$ = -$1;        }
;
%%

/* Lexical analyzer returns a double floating point 
   number on the stack and the token NUM, or the ASCII
   character read if not a number.  Skips all blanks
   and tabs, returns 0 for EOF. */

#include <ctype.h>
#include <stdio.h>

yylex ()
{
  int c;

  /* skip white space  */
  while ((c = getchar ()) == ' ' || c == '\t')  
    ;
  /* process numbers   */
  if (c == '.' || isdigit (c))                
    {
      ungetc (c, stdin);
      scanf ("%lf", &yylval);
      return NUM;
    }
  /* return end-of-file  */
  if (c == EOF)                            
    return 0;
  /* return single chars */
  return c;                                
}

yyerror (s)  /* Called by yyparse on error */
     char *s;
{
  printf ("%s\n", s);
}

main ()
{
  yyparse ();
}

Оригинальный вопрос

Я пытаюсь создать свой собственный язык разработки, но его так сложно запустить, и когда я начинаю, я получаю много ошибок и не знаю, как их решить. Это мой код:

#include <ctype.h>
#include <stdio.h>

yylex ()
{
  int c;

  /* skip white space  */
  while ((c = getchar ()) == ' ' || c == '\t')  
    ;
  /* process numbers   */
  if (c == '.' || isdigit (c))                
    {
      ungetc (c, stdin);
      scanf ("%lf", &yylval);
      return NUM;
    }
  /* return end-of-file  */
  if (c == EOF)                            
    return 0;
  /* return single chars */
  return c;                                
}

main ()
{
  yyparse ();
}

Файл исходного кода calc.y:

%token NUM
%%
input:
        | input line
;

line:     '\n'
        | exp '\n'  { printf ("\t%.10g\n", $1); }
;

exp:      NUM             { $$ = $1;         }
        | exp exp '+'     { $$ = $1 + $2;    }
        | exp exp '-'     { $$ = $1 - $2;    }
        | exp exp '*'     { $$ = $1 * $2;    }
        | exp exp '/'     { $$ = $1 / $2;    }
      /* Exponentiation */
        | exp exp '^'     { $$ = pow ($1, $2); }
      /* Unary minus    */
        | exp 'n'         { $$ = -$1;        }
;
%%

А теперь журнал компилятора:

C:\Documents and Settings\Nathan Campos\Desktop>gcc calc.tab.c -lm -o rpcalc
calc.tab.c: In function `yylex':
calc.tab.c:15: error: `yylval' undeclared (first use in this function)
calc.tab.c:15: error: (Each undeclared identifier is reported only once
calc.tab.c:15: error: for each function it appears in.)
calc.tab.c:16: error: `NUM' undeclared (first use in this function)

Что не так?

Ответы [ 5 ]

6 голосов
/ 11 октября 2009

Исправленный ответ

Измененный код, который вы предоставляете, компилируется почти чисто - вы должны #include <stdio.h>, чтобы printf() был объявлен до его использования. (Вы также должны использовать прототипы для функций - таких как yyerror(const char *str) и вообще перетаскивать код в 21-й век.)

Он даже правильно отвечает на '1 2 +'.

С одним файлом вам не нужно использовать 'bison -d'.

Если вы видите мусор, вам необходимо просмотреть команды сборки и среду сборки.


Оригинальный ответ

С чего начать?

Рекомендация: возьмите книгу О'Рейли по Lex и Yacc (из библиотеки) или Flex and Bison (обновление / переписывание в августе 2009 г. - вероятно, не в библиотеки пока нет). Если вам нужен ресурс быстрее, я предлагаю Unix Version 7 руководства или GNU Bison руководство - оба из которых доступны онлайн. В частности, прочитайте документы 7-го издания о Lex и Yacc; вы не пытаетесь делать то, что не было охвачено в первоначальных описаниях (хотя код C там предшествует стандарту C89 на десять или более лет).

  • Вам необходимо использовать bison -d для генерации заголовка, содержащего номера токенов. Для исходного файла 'zzz.y' это сгенерирует код C 'zzz.tab.c' и 'zzz.tab.h'.
  • Вам нужно включить 'zzz.tab.h' в основную программу.
  • Вам нужно использовать C99 и, следовательно, иметь тип возврата на yylex() и main().
  • Вам нужно объявить yylval. К счастью, файл 'zzz.tab.h' Bison сделает это правильно; это не так просто, как кажется.
  • Возможно, вы захотите разрешить использование отрицательных чисел в вашем лексическом анализаторе (-3.1416). Возможно, вы захотите разрешить и явно положительные числа (+3.1416).
  • Возможно, вам необходимо убедиться, что $$ и друзья имеют тип double, а не тип по умолчанию int (#define YYSTYPE double).
2 голосов
/ 11 октября 2009

IIRC, yylval объявлен Bison, но вы должны указать тип. Без этого компилятор запутывается и может выдавать вводящие в заблуждение ошибки.

Вам нужно определить YYSTYPE. В вашем случае вы можете избежать использования "#define YYSTYPE double". Сделайте это в грамматике в блоке% {...%} вверху.

% union также доступен для объявления YYSTYPE как union.

Это похоже на пример стандартного rpcalc для руководства Bison, поэтому я предполагаю, что вы можете достаточно легко найти "YYSTYPE" и "% union".

1 голос
/ 11 октября 2009

В вашем .y файле добавьте следующие строки:

void yyerror(char *errorinfo);
int yylex(void);

Вам также необходимо определить типы токенов, сгенерированные с помощью flex:

%token NUM

и т. Д.

Редактировать: Флекс и Бизон (О'Рейли) - отличный ресурс.

0 голосов
/ 16 октября 2009

Не очень хорошая идея #define YYSTYPE. Это точно не работает с бизоном, с которым я пробовал. Что вы должны сделать, это сказать Bison, что значения, с которыми вы работаете, являются двойными:

%union {
    double dval;
}

%type <dval> exp NUM

Bison теперь сгенерирует подходящий YYSTYPE для вас.

Но я рекомендую вам посмотреть учебник или что-то в этом роде. Томас Ниманн Компактное руководство по Lex & Yacc хороший, приводя примеры и пошаговые объяснения. Я преподаю курс по компилятору, и мой опыт показывает, что с бизоном и грамматикой может быть трудно начать слишком много проб и ошибок.

0 голосов
/ 11 октября 2009

Вы нигде не объявили переменную yylval .

...