Yacc - утверждение - правила грамматики - PullRequest
1 голос
/ 07 февраля 2012

У меня есть небольшая программа, которая читает входные данные и возвращает данные в файл YACC, где я просто хочу распечатать.Я не правильно понимаю правила грамматики в файле yacc, я думаю.

Я получаю значения NULL, и что-то не печатается, и синтаксическая ошибка

вот файл ввода:

fd
bk 100
setc
int
fd 10 rt 90

Вот файл yacc:

%{

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

%}

%token NUMBER
%token ID
%token FD
%token BK
%token SETC
%token RT
%token INT
%%


statement :  command arg   {printf("KEYWORDS: %s\n", $1);}
           |command    {printf("OR-> %s\n", $1);}
           ;

command : FD               {$$ = $1; printf("FD-> %s\n", $1);}
     |BK              {$$ = $1;  printf("BK-> %s\n", $1);}
     |SETC            {$$ = $1;  printf("SETC-> %s\n", $1); }
     |INT             {$$ = $1;  printf("INT->  %s\n", $1);}
     |RT              {$$ = $1;  printf("RT->  %s\n", $1);}
     ;


arg : NUMBER            {$$ = $1; printf("NUMBER-> %d\n", $1);}
     ;

%%

Вот файл lex:

%{

 #include "y.tab.h"
 #include "stdio.h"
 #include <stdlib.h>


%}
%%

fd                    {return FD; }
bk                    {return BK;}
setc                  {return SETC;}
[-+]?[0-9]+           { yylval = atoi(yytext); return NUMBER;}
int                   {return INT;}
rt                    {return RT;}

.                    {printf("%s\n", yytext);}

%%

Вот вывод:

BK-> (null)

NUMBER-> 100
KEYWORDS: (null)

syntax error

Так почему же печатается только БК, а не остальные?Почему я получаю значения NULL?И почему у меня есть синтаксическая ошибка?

Извините, что есть 3 вопроса

1 Ответ

2 голосов
/ 07 февраля 2012

Во-первых, ваша грамматика принимает только один оператор, поэтому она анализирует первый оператор, а затем выдает синтаксическую ошибку, поскольку следующее прочитанное не является EOF. Попробуйте добавить следующее перед правилом для statement:

input: /* nothing */
     | input statement
     ;

Это позволит анализатору проанализировать любое количество операторов (0 или более) перед EOF

Во-вторых, ваш лексер не устанавливает yylval для ключевых слов, в то время как ваш синтаксический анализатор ожидает его (он обращается к $1 в действиях, где это соответствует токену ключевого слова), поэтому он получает случайный мусор. В этом случае это NULL, который он передает printf - вам повезло, что он не вылетел.

Чтобы это исправить, вам нужно вернуть что-то в yylval (возможно, строку в yytext), но, поскольку вы не определили это как что-либо еще, yylval - просто int, поэтому не может содержать строку , Вы можете использовать %union, чтобы сделать yylval объединением, которое может содержать либо int, либо char *, но это все еще оставляет вам огромную проблему с управлением памятью, выделяя место для строк и освобождая его, если вам не нужна память утечки. Проще всего было бы избавиться от ссылок на $1 в этих действиях, поскольку вам это на самом деле не нужно.

...