cannot perform desired operation

J

jiten

Hi all,
I have a small request. I am a newbie to lex/yacc and as part of term
assignment was developing a calculator. But, I have problem that I
cannot perform any real data type operation. Not even addition. At
best, the response is :
> command not found (e.g., for i/p: 5.0+6.0); else it is 'syntax
error'.
Kindly find the two files posted below:

calc.y
==========
%{#include<stdio.h>
%}
/*%union {double real; int integer;}*/
%token <real> REAL
%token <integer> INTEGER
%token PLUS MINUS TIMES DIVIDE LP RP NL UL
%type <real> rexpr
%type <integer> iexpr
%left PLUS MINUS
%left TIMES DIVIDE
%left UMINUS
%%
lines : /* nothing*/
| lines line
;
line : NL
|iexpr NL
{ printf("%d)%d\n", lineno, $1);}
|rexpr UL
{ printf("%d)%15.8lf\n", lineno, $1);}
iexpr : INTEGER
|iexpr PLUS iexpr
{ $$ = $1 + $3; }
|iexpr MINUS iexpr
{ $$ = $1 - $3; }
|iexpr TIMES iexpr
{ $$ = $1 * $3; }
|iexpr DIVIDE iexpr
{ if($3) $$ = $1/$3;
else {yyerror("divide by zero"); }
}
|MINUS iexpr %prec UMINUS
{ $$ = -$2;}
|LP iexpr RP
{ $$ = $2; }
rexpr : REAL
|rexpr PLUS rexpr
{ $$ = $1 + $3; }
|rexpr MINUS rexpr
{ $$ = $1 - $3; }
|rexpr TIMES rexpr
{ $$ = $1 * $3; }
|rexpr DIVIDE rexpr
{ if($3) $$ = $1/$3;
else {yyerror("divide by zero"); }
}
|MINUS rexpr %prec UMINUS
{ $$ = -$2;}
|LP rexpr RP
{ $$ = $2; }
|iexpr PLUS rexpr
{ $$ = (double)$1 + $3; }
|iexpr MINUS rexpr
{ $$ = (double)$1 - $3; }
|iexpr TIMES rexpr
{ $$ = (double)$1 * $3; }
|iexpr DIVIDE rexpr
{ if($3) $$ = (double)$1/$3;
else {yyerror("divide by zero"); }
}
|rexpr PLUS iexpr
{ $$ = $1 +(double)$3;}
|rexpr MINUS iexpr
{ $$ = $1 -(double)$3;}
|rexpr DIVIDE iexpr
{ if($3) $$ = (double)$1/$3;
else{yyerror("divide by zero"); }
}
%%
#include "lex.yy.c"
int lineno;
main()
{
return yyparse();
}
yyerror(char *s)
{
fprintf(stderr, "%s\n", s);
}

=============
calc.l
-----------
%{
#include"y.tab.h"
%}

integer [0-9]+
dreal ([0-9]*\.[0-9]+)
ereal ([0-9]*\.[0-9]+[Ee][+-]?[0-9]+)
real {dreal}|{ereal}
nl \n

%%

[ \t] ;
{integer} { sscanf(yytext, "%d", &yylval.integer);
return INTEGER;
}
{real} { sscanf(yytext, "%lf", &yylval.real);
return REAL;
}
\+ {return PLUS;}
\- {return MINUS;}
\* {return TIMES;}
\/ {return DIVIDE;}
\( {return LP;}
\) {return RP;}
{nl} {extern int lineno; lineno++; return NL;}
.. {return yytext[0];} /* to return any character otherwise
not handled as a single char. token to the parser*/

%%

int yywrap() { return 1;}




Best regards,
Jitender Ahuja
 
S

Seebs

Hi all,
I have a small request. I am a newbie to lex/yacc and as part of term
assignment was developing a calculator.

lex and yacc are not C, even though they are often used to develop C code.

I'd guess that comp.unix.programmer would have more people who are up to speed
on them.

If you're getting messages like "command not found", that sounds like you're
ending up entering your commands at the shell prompt, rather than submitting
them to your program -- but this would be something that, again, has more to
do with your work environment than with C.

-s
 
S

spinoza1111

Hi all,
I have a small request. I am  a newbie to lex/yacc and as part of term
assignment was developing a calculator. But, I have problem that I
cannot perform any real data type operation. Not even addition.  At
best, the response is :
 >  command not found (e.g., for i/p: 5.0+6.0); else it is 'syntax
error'.
Kindly find the two files posted below:

calc.y
==========
 %{#include<stdio.h>
%}
/*%union {double real; int integer;}*/
%token <real> REAL
%token <integer> INTEGER
%token PLUS MINUS TIMES DIVIDE LP RP NL UL
%type <real> rexpr
%type <integer> iexpr
%left PLUS MINUS
%left TIMES DIVIDE
%left UMINUS
%%
lines : /* nothing*/
      | lines line
      ;
line  : NL
      |iexpr NL
       { printf("%d)%d\n", lineno, $1);}
      |rexpr UL
       { printf("%d)%15.8lf\n", lineno, $1);}
iexpr : INTEGER
      |iexpr PLUS iexpr
       { $$ = $1 + $3; }
      |iexpr MINUS iexpr
       { $$ = $1 - $3; }
      |iexpr TIMES iexpr
       { $$ = $1 * $3; }
      |iexpr DIVIDE iexpr
       { if($3) $$ = $1/$3;
         else {yyerror("divide by zero"); }
       }
      |MINUS iexpr %prec UMINUS
      { $$ = -$2;}
      |LP iexpr RP
      { $$ = $2; }
rexpr : REAL
      |rexpr PLUS rexpr
       { $$ = $1 + $3; }
      |rexpr MINUS rexpr
       { $$ = $1 - $3; }
      |rexpr TIMES rexpr
       { $$ = $1 * $3; }
      |rexpr DIVIDE rexpr
       { if($3) $$ = $1/$3;
         else {yyerror("divide by zero"); }
       }
      |MINUS rexpr %prec UMINUS
      { $$ = -$2;}
      |LP rexpr RP
      { $$ = $2; }
      |iexpr PLUS rexpr
       { $$ = (double)$1 + $3; }
      |iexpr MINUS rexpr
       { $$ = (double)$1 - $3; }
      |iexpr TIMES rexpr
       { $$ = (double)$1 * $3; }
      |iexpr DIVIDE rexpr
       { if($3) $$ = (double)$1/$3;
         else {yyerror("divide by zero"); }
       }
      |rexpr PLUS iexpr
       { $$ = $1 +(double)$3;}
      |rexpr MINUS iexpr
       { $$ = $1 -(double)$3;}
      |rexpr DIVIDE iexpr
       { if($3) $$ = (double)$1/$3;
         else{yyerror("divide by zero"); }
       }
%%
#include "lex.yy.c"
int lineno;
main()
{
  return yyparse();}

yyerror(char *s)
{
  fprintf(stderr, "%s\n", s);

}

=============
calc.l
-----------
%{
#include"y.tab.h"
%}

integer [0-9]+
dreal   ([0-9]*\.[0-9]+)
ereal   ([0-9]*\.[0-9]+[Ee][+-]?[0-9]+)
real    {dreal}|{ereal}
nl      \n

%%

[ \t]        ;
{integer}    { sscanf(yytext, "%d", &yylval.integer);
               return INTEGER;
             }
{real}       { sscanf(yytext, "%lf", &yylval.real);
               return REAL;
             }
\+           {return PLUS;}
\-           {return MINUS;}
\*           {return TIMES;}
\/           {return DIVIDE;}
\(           {return LP;}
\)           {return RP;}
{nl}         {extern int lineno; lineno++; return NL;}
.            {return yytext[0];} /* to return any character otherwise
not handled as a single                                                 char. token to the parser*/

%%

int yywrap() { return 1;}

Best regards,
Jitender Ahuja

Mr. Ahuja, I shall be brief and general since the policy here is not
to over-help on homework, and this looks like homework.

A cursory examination shows IEXPR and REXPR on both sides of a binary
operator which is normally a problem. Your code needs a more precise
grammatical class on the left hand side of the binary operator in the
right hand side production, followed by the optional operator,
followed if by a recursive occurence of the grammatical class being
defined dependent on the presence of the operator:

expression := addFactor [ addOp expression ]
addOp := '+' | '-'
addFactor := mulFactor [ mulOp addfactor ]
mulOp := '*' | '/'
mulFactor := NUMBER | VARIABLE | '(' expression ')'

The above grammar requires (in its definition of mulFactor) that
special code be written to count the nesting level of parentheses so
as to find the balancing right parenthesis and not the leftmost which
is a flaw of this grammar (check yours for a similar flaw).

The above pseudocode I have shown you is NOT YACC. It is an obvious
formal notation in which you can probably see that square brackets
mean "the grammar inside us is optional but must be satisfied if the
first grammar symbol inside of us is present". Although I have used
yacc, don't get me started on how bad it is, starting with its C
centricity.

It doesn't appear to me that your code handles operator precedence if
that was a requirement, and on cursory examination, it appears that
you unnecessarily distinguish integer and real expressions.

It appears to me that you're being expected to understand a bit of
compiler design theory as embedded in yacc, truly an out of date
compiler "generator" that doesn't generate a compiler, only a pretty
bad bottom up recognizer.

If you're interested, my book ("Build Your Own .Net Language and
Compiler", Edward G. Nilges, apress 2004) discusses this in detail
especially in chapter 4. However, it abstracts compiler design theory
from its usual lair (C coding) and parachutes it into Visual Basic of
all places. This was meant to show that "computer science" is
rigorously independent of C coding despite what some of the folks here
might feel.
 
S

steve

lex and yacc are not C, even though they are often used to develop C code..

I'd guess that comp.unix.programmer would have more people who are up to speed
on them.

comp.compilers would be a much better choice. 1) It's a
moderated newsgroup. 2) The moderator is John Levine,
who wrote the O'rielly book on Lex and Yacc. 3) John
does not allow flamewars in comp.compilers.
 
S

spinoza1111

comp.compilers would be a much better choice.  1) It's a
moderated newsgroup.  2) The moderator is John Levine,
who wrote the O'rielly book on Lex and Yacc.  3) John
does not allow flamewars in comp.compilers.

I have been totally thrown out of that site. My belief is that John is
an enabler and plays favorites. He thinks I start trouble (who, me?).
It's OK, but overly C and yacc centric for obvious reasons. Of course,
the OP has a yacc problem.

But...it seems to me that the OP's class is so focused on a truly
outdated tool for parser generation that the professor didn't bother
to teach the basics, including how operator precedence is implemented
in syntax and how the leftpart of a grammar rule cannot, for most
parsers, recursively call itself, but must instead provide a sort of
"handle" in the form of a lower-level grammar category. This "handle"
must further reduce down to a lexical symbol that is hopefully unique;
this way the grammar can choose the correct form without lookahead.

This is not possible in disambiguating a+b and a*c, but here, the
disambiguation is the combination of "addFactor and plus" and
"mulFactor and times".

Possibly, yacc was thrown at the OP as a substitute for an
introduction to parsing as if the mad dream of yesteryear
(automatically generated compilers and software too) had come true,
and yacc would replace thinking.

John Levine's readiness to shitcan people in the typically Maoist
fashion increasingly characteristic of the Web as a whole is an aspect
of this anti-intellectualism.

Furthermore, "flamewars" usually imply a false equality between
people. What usually happens is simple bullying. Someone with original
ideas gets the shit kicked out of him, and codependents make less than
helpful suggestions, usually attempting to blame the victim.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top