What is wrong with this yacc file? - c

I'm getting this error tema4.y:13.19-26: syntax error, unexpected typetype on the following code, please help me!
%{
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
%}
%union {
int intval;
char* strval;
char* charval;
}
%token <charval>SHR <intval>NR
%token CMP
%type <strval>str <intval>expr
%nonassoc CMP '|'
%left '+' '-'
%left '*' '`' '#'
%start s
%%
s:str {printf("%s \n",$<strval>$);}
| expr {printf("%s \n",$<intval>$)}
;
str : str '+' str {
char* s=malloc(strlen($1)+strlen($3)+1);
strcpy(s,$1);
strcat(s,$3);
$$=s;
}
| str '-' str {
char *s=malloc(strlen($1));
char *sir=malloc(strlen($1)-strlen($3));
char *pt,*ps;
int i;
strcpy(s,$1);
pt=strstr(s,$3);
if(pt) {
ps=pt+strlen($3);
strncpy(pt,ps,strlen(ps));
ps+=strlen(ps);
strncpy(sir,s,strlen($1)-strlen($3));
}
$$=sir;
}
| str '*' NR {
int i;
char* s=malloc(strlen($1)*NR+1);
for(i=0;i<$3;i++)
{
strcat(s,$1);
}
$$=s;
}
| str '#' NR {
char *s=malloc($3+1);
strcpy(s,$1);
if($3>strlen($1)) {printf("Nr prea mare\n");exit(1);}
else {s=s+strlen(s)-$3;
$$=s;}
}
| NR '`' str {
char *s=malloc($1+1);
strncpy(s,$3,$1);
$$=s;
}
| '(' str ')' {
$$=$2;
}
| SHR {
char* s=malloc(strlen($1));
strcpy(s,$1);
$$=s;
}
| expr
;
expr : str CMP str {
if(strcmp($1,$3)) $$=0;
else $$=1;
}
| '|' str '|' {
$$=strlen($2);
}
;
%%
int main(){
yyparse();
}

John has the answer for your first error -- only one type in a %type or %token declaration. For the second error (type clash), the problem is your rule str: expr ; -- str is a <strval> while expr is an <intval>, so the default action ({ $$ = $1; } effectively) has a type clash.
You also have a reduce/reduce conflict somewhere -- you'll need to run yacc with -d and look at the resulting y.output file for more detail on what the conflict is.

As best I can tell you can only have one <type> in a %token or %type declaration. You can have multiple tokens or non-terminals but only one type name. Try splitting those lines:
%token <charval> SHR
%token <intval> NR
%token CMP
%type <strval> str
%type <intval> expr

Related

Syntax error by Yacc even though the syntax is per grammar

My yacc parser is showing syntax error even though the syntax is as per grammar.
my Yacc code:
%{
void yyerror (char *s);
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int symbols[100];
int yylex();
int symbolVal(char symbol);
void updateSymbolVal(char symbol,int val);
%}
%union {int num; char id;}
%start line
%token WHILE
%token lt
%token gt
%token exit_command
%token <num> number
%token <id> identifier
%type <num> line exp term
%type <id> assignment
%type <num> condition
%%
line: assignment {;}
|line assignment {;}
|exit_command {exit(EXIT_SUCCESS);}
|line exit_command {exit(EXIT_SUCCESS);}
|whileLoop {;}
|condition {;}
;
whileLoop: WHILE '(' condition ')' '{' assignment '}' {printf("while loop condition var:%d\n",$3);}
;
assignment : identifier '=' exp {updateSymbolVal($1,$3);}
;
exp : term {$$ = $1;}
| exp '+' term {$$ = $1 + $3;}
| exp '-' term {$$ = $1 - $3;}
;
term : number {$$ = $1;}
| identifier {$$ = symbolVal($1);}
;
condition : identifier cond_op identifier {$$ = $1;}
|identifier cond_op number {$$ = $1;}
;
cond_op : lt
| gt
;
%%
int computeSymbolIndex(char token){
int idx = -1;
if(islower(token)){
idx = token - 'a' +26;
}
else if(isupper(token)){
idx = token - 'A' + 26;
}
return idx;
}
int symbolVal(char symbol){
int bucket = computeSymbolIndex(symbol);
return symbols[bucket];
}
void updateSymbolVal(char symbol, int val){
int bucket = computeSymbolIndex(symbol);
symbols[bucket] = val;
}
int main(void){
int i;
for(i=0;i<52;i++){
symbols[i] = 0;
}
return yyparse();
}
void yyerror (char *s){fprintf (stderr, "%s\n",s);}
My Lex code:
%{
#include "y.tab.h"
%}
%%
"while" {printf("while\n"); return WHILE;}
"exit" {return exit_command;}
[a-zA-Z] {yylval.id = yytext[0]; return identifier;}
[0-9]+ {yylval.num = atoi(yytext); return number;}
"<" {return lt;}
">" {return gt;}
[ \t\n] ;
[-+=;] {return yytext[0];}
. ;
%%
int yywrap (void)
{
return 1;
}
Example text on which a syntax error is shown:
while(i>0){i = i-1}
"while" gets printed as per lex but the next line of output is "Syntax Error".
Even the "while loop condition var" is not getting printed.
The syntax error is shown especially of the while loop.
All the other things like the condition statements assignments etc seem to work fine.
Why is this happening?
You have a lexer fallback rule which silently discards unrecognised characters:
. ;
That's really not a good idea, as you have just discovered. In this case, no other rule recognises ( or ), so they are ignored by the above rule. Your parser, however, is expecting a parenthesis. It doesn't get one, so it reports a syntax error.
Better is the following fallback rule, which could replace the preceding rule:
/* [-+=;] {return yytext[0];} */ /* now redundant*/
. {return yytext[0];}
This accepts any character in the lexer. However, most characters are not used as character literals anywhere in the grammar, so they will be treated as invalid tokens by the parser, causing a syntax error.
You could get a more precise error message by writing the error in your lex fallback rule, but yhen you need to make sure that all vslid characters are recognised:
[-+=;(){}] {return yytext[0];}
. {return yytext[0];}
Personally, I'd add <> to that list rather than having dedicated rules (and unnecessary token names.)

I got an error in function `yylex': lex.yy.c:(.text+0x2ac): undefined reference

I am new with lex and yacc, and I am following the "lex & yacc 1992" book.
I am working in an example in chapter 3, and I have an error in the compiling process, but I couldn't find a solution;
here is the code:
the lex file.l :
%{
#include "y.tab.h"
#include "symboletable.h"
#include <math.h>
extern int yylavl;
%}
%%
([0-9]+|([0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?) {
yylval.dval = atof(yytext);
return NUMBER;
}
[ \t] ; /* ignore whitespace */
[A-Za-z][A-Za-z0-9]* { /* return symbol pointer */
yylval.symp = symlook(yytext);
return NAME;
}
"$" { return 0; }
\n |
. return yytext[0];
%%
and here the yacc file.y
%{
#include "symboletable.h"
#include <string.h>
#include <stdio.h> /* C declarations used in actions */
int yylex();
void yyerror(const char *s);
%}
%union {
double dval;
struct symtab *symp;
}
%token <symp> NAME
%token <dval> NUMBER
%left '+' '-'
%left '*' '/'
%nonassoc UMINUS
%type <dval> expression
%%
statement_list : statement '\n'
| statement_list statement '\n'
;
statement : expression { printf("= %g\n", $1); }
| NAME '=' expression {$1->value = $3; }
;
expression : NAME {$$ = $1->value; }
| expression '+' expression {$$ = $1 + $3; }
| expression '-' expression {$$ = $1 - $3; }
| expression '*' expression {$$ = $1 * $3; }
| expression '/' expression
{ if ($3 ==0.0)
yyerror("divide by zero");
else
$$ = $1 / $3;
}
| '-' expression %prec UMINUS {$$ = -$2; }
| '(' expression ')' {$$ = $2; }
| NUMBER
;
%%
according to the example in the book, I need to write a symbol table routines, to get the string and allocate dynamic space for the string, here the file.h
the symboletable.h
#define NSYMS 20 /* maximum number of symbols */
struct symtab {
char *name;
double value;
} symtab[NSYMS];
struct symtab *symlook();
and the symboletable.pgm:
/* look up a symbol table entry, add if not present */
struct symtab *
symlook(s)
char *s;
{
char *p;
struct symtab *sp;
for (sp = symtab; sp < &symtab[NSYMS]; sp++){
/* is it already here ? */
if (sp->name && !strcmp(sp->name, s))
return sp;
/* is it free */
if (!sp->name){
sp->name = strdup(s);
return sp;
}
/* otherwise continue to next */
}
yyerror("Too many symbols");
exit(1); /* cannot continue */
} /* symlook */
now when I run the following command:
yacc -d file.y
lex file.l
cc -c lex.yy.c -o newfile -ll
cc -o new y.tab.c lex.yy.c -ly -ll
but here the error I got:
/tmp/ccGnPAO2.o: In function yylex': lex.yy.c:(.text+0x2ac):
undefined reference tosymlook' collect2: error: ld returned 1 exit
status
so, why I got that error, I am totally follow the example ?
You need to include your symbol table implementation in your compilation command. Otherwise, how is the linker going to find that code?

I'm receiving an error when giving my language a second input

The program generated from my bison/flex files works fine for the first input(the first run of yyparse()), but throws an error when I try and run it a second time.
for example:
chris#chris-Inspiron-1525:~/4850/hw$ ./calc
HORN 3+4*6-11+33*2 ?
= 82
HORN 1+1 ?
error: syntax error
Basically, commands exist between 'HORN' and '?'
Here's my .y file:
%{
#include <stdlib.h>
#include <stdio.h>
void yyerror(const char *str);
%}
%union
{
int ival;
float fval;
char* word;
}
%start line
%type <word> wexp
%type <ival> iexp
%type <fval> fexp
%left PLUS MINUS
%left STAR DIV MOD
%left POW
%token GT
%token LT
%token ASGN
%token LP
%token RP
%token LB
%token RB
%token NOT
%token GTEQ
%token LTEQ
%token EQTO
%token NOTEQ
%token HORN
%token QMARK
%token <word> WORD
%token <fval> FLOAT
%token <ival> INTEGER
%%
line : HORN wexp QMARK { printf("=\t%s\n", $2); }
| HORN iexp QMARK { printf("=\t%d\n", $2); }
| HORN fexp QMARK { printf("=\t%f\n", $2); }
;
iexp : iexp MINUS iexp { $$ = $1 - $3; }
| iexp PLUS iexp { $$ = $1 + $3; }
| iexp STAR iexp { $$ = $1 * $3; }
| iexp DIV iexp { $$ = $1 / $3; }
| INTEGER { $$ = $1; }
;
fexp : FLOAT { $$ = $1; }
;
wexp : WORD { $$ = $1; }
;
%%
int main(){
yyparse();
}
void yyerror(const char *str)
{
printf("error: %s\n",str);
}
Thanks for any input!
Your yacc grammar only declare one line. When you have finished one line any following input is a syntax error.
The current way to allow as many lines as you need is to add as first rule something like :
lines : line
| lines line
;
Provided you correctly ignore end of line in the lex part ...

Segmentation Fault after assignment statement(lex and yacc)

This code works perfectly fine. After compiling lex and yacc, the code is able to do basic arithmetic operations, and even echoes the value of a variable when asked to do so. The only problem is with assignment statements.
If I want to, say, do A = 12, and later type A to see its value, the program crashes and I get a segmentation fault. How do I ensure that my assignment statements work, and how can I avoid this segmentation fault?
Here is my code:
//lex file
/*Lex input specification*/
%{
#include <stdlib.h>
#include <stdio.h>
#include "y.tab.h"
void yyerror(char*);
%}
%%
" " ;
[A-Z] { yylval = *yytext-'a'; return VARIABLE;}
[0-9]+([0-9])* { yylval=atoi(yytext); return INTEGER;}
[-/+()=*\n] { return *yytext;}
[\t] ;
. { yyerror("invalid character");}
%%
int yywrap(void) { return 1;}
And the yacc file:
/*yacc*/
%token INTEGER VARIABLE
%left '|'
%left '&'
%left '+' '-'
%left '*' '/'
%left UMINUS
%{
void yyerror(char*);
int yylex(void);
int sym[26];
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
%}
%%
program:
program statement '\n'
|
;
statement:
expr {printf("%d\n",$1);}
| VARIABLE '=' expr {sym[$1] = $3;}
;
expr:
INTEGER {$$ = $1;}
| VARIABLE {$$ = sym[$1];}
| expr '*' expr {$$ = $1 * $3;}
| expr '/' expr {$$ = $1 / $3;}
| expr '+' expr {$$ = $1 + $3;}
| expr '-' expr {$$ = $1 - $3;}
| '(' expr ')' {$$ = $2;}
;
%%
void yyerror(char*s) {
fprintf(stderr, "%s\n", s);
}
int main(void) {
yyparse();
return 0;
}
(I flagged this as "not reproducible" because the fix was so trivial; however the flag has now timed-out/aged away. I'll answer instead so it is not shown as an open unanswered question).
As #BLUEPIXY noted:
maybe *yytext-'A'
Which, to clarify, is the lex rule:
[A-Z] { yylval = *yytext-'A'; return VARIABLE;}

Bison conflicting type for yyerror

I'm trying to make a calculator from flex and bison, but I found an error during the compile.
Here is the error:
C:\GnuWin32\src>gcc lex.yy.c y.tab.c -o tugas
tugas.y:51: error: conflicting types for 'yyerror'
y.tab.c:1433: error: previous implicit declaration of 'yyerror' was here
Here is my .l code :
%{
#include <stdio.h>
#include "y.tab.h"
YYSTYPE yylval;
%}
plus [+]
semi [;]
minus [-]
var [a-z]
digit [0-1]+
equal [:=]
%%
{var} {yylval = *yytext - 'a'; return VAR;}
{digit} {yylval = atoi(yytext); return DIGIT;}
{plus} {return PLUS;}
{minus} {return MINUS;}
{equal} {return EQUAL;}
{semi} {return SEMI;}
. { return *yytext; }
%%
int main(void)
{
yyparse();
return 0;
}
int yywrap(void)
{
return 0;
}
int yyerror(void)
{
printf("Error\n");
exit(1);
}
And here is my .y code :
%{
int sym[26];
%}
%token DIGIT VAR
%token MINUS PLUS EQUAL
%token SEMI
%%
program: dlist SEMI slist
;
dlist: /* nothing */
| decl SEMI dlist
;
decl: 'VAR' VAR {printf("deklarasi variable accepted");}
;
slist: stmt
| slist SEMI stmt
;
stmt: VAR EQUAL expr {sym[$1] = $3;}
| 'PRINT' VAR {printf("%d",sym[$2]);}
;
expr: term {$$ = $1;}
| expr PLUS term { $$ = $1 + $3;}
| expr MINUS term { $$ = $1 - $3; }
;
term: int {$$ = $1;}
| VAR {$$ = sym[$1]; }
;
int: DIGIT {$$ = $1;}
| int DIGIT
;
Why I am getting this error? any suggestion to overcome this issue.Thanks in advance
yyerror should have this signature:
int yyerror(char *);
Since it is expected to accept a string to be used in the error message (would probably be better with a const char *, but you might get additional (ignorable) warnings with that...
You need to change
int yyerror(void)
to
int yyerror(char*)
In other words, yyerror() must take a single c-string argument which describes the error which occured.

Resources