1
votes

i have a small program that reads input and returns data to a yacc file where i just want to print out. I am not understanding the grammar rules correctly in the yacc file i think.

I am getting NULL values and somethings are not printing and a syntax error

here is the input file:

fd
bk 100
setc
int
fd 10 rt 90

Here is the yacc file:

%{

#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);}
     ;

%%

Here is the lex file:

%{

 #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);}

%%

Here is the output:

BK-> (null)

NUMBER-> 100
KEYWORDS: (null)

syntax error

So why is it only printing BK and not the rest? Why am i getting NULL values? And why do i have a syntax error?

Sorry there's 3 questions

1

1 Answers

2
votes

First, your grammar only accepts a single statement, so it parses the first statement and then gives a syntax error as the next thing read is not an EOF. Try adding the following before the rule for statement:

input: /* nothing */
     | input statement
     ;

This will let the parser parse any number of statements (0 or more) before an EOF

Second, your lexer doesn't set yylval for keywords, while your parser expects it to (it accesses $1 in actions where that corresponds to a keyword token), so it gets random garbage. In this case it happens to be a NULL that it passes to printf -- you're lucky it didn't crash.

To fix this, you'll need to return something in yylval (the string in yytext, perhaps), but as you haven't defined it as anything else, yylval is just an int, so can't hold a string. You can use %union to make yylval a union that can hold either an int or a char *, but that still leaves you with a huge memory management problem allocating space for strings and freeing it if you don't want memory leaks. Easiest would be to get rid of the references to $1 in those actions, as you don't really need it.