4 Replies - 8841 Views - Last Post: 21 March 2010 - 12:40 AM Rate Topic: ***** 1 Votes

#1 Mr. Member  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 19-November 08

Calculator taking identifiers as variable names//yacc, lex, c

Post icon  Posted 19 November 2008 - 06:03 PM

Hello. I need some help with my calculator that should accept identifiers as variable names. Do make a simple calculator using lex, yacc and c is easy. But when it comes to allowing the variable names to be longer ones (identifiers) then I got confused. For instance I can assign a=4, b=5 and a+b=9. Simple math. But how am I supposed to use hash table to hold the names of the variables(identifiers) using lex, yacc and c. I'm provided with some preliminary code to get started but I really got confused. I think my knowledge of c is not sufficient. I can't use the hash table code provided. Can anyone help me urgently. I'm posting the codes I already have. Thanks for the ones who'll help in advance.


****item.h****
//item.h 

/* Key is defined as a string */
typedef char *Key;

/* Variable names are the only identifier 

/* key value pair stored in the hash table */

typedef struct {
	Key		 key;   //  variable name is the key 
	int		 value; //  its value is an integer
} Item;


/* eq macro compares two key values A and B,
   returns true if they are equal */
#define eq(A,B) (strcmp(A,B) == 0) 

#define key(item) (item.key)





***symtab.c***

//symtab.c
#include <stdlib.h>

#include "item.h"
#define null(A) (key(st[A]) == key(NULLitem))

Item NULLitem = {0,0};

static int N, M;

static Item *st;

void STinit(int max) {
   int i;
   N = 0;
   M = 2*max;
   st = (Item *) malloc(M*sizeof(Item));
   for(i=0; i<M; i++) st[i] = NULLitem;
}


void STinsert(Item item) {
   Key v = key(item);
   int i = hash(v,M);
   while(!null(i)) i = (i+1) % M;
   st[i] = item; N++;
}

Item STsearch(Key v) {
   int i = hash(v,M);
   while (!null(i)) 
	  if eq(v,key(st[i])) 
		 return st[i];
	  else
		 i = (i+1) % M;
   return NULLitem;
}   


Item *SThandle(Key v) {
	  int i = hash(v,M);
	  while (!null(i))
		 if eq(v,key(st[i]))
			 return st+i;
		 else
			 i = (i+1) % M;
	  return NULL;
}


int hash(char *v, int M) {
   int h, a = 31415, b=27183;
   for(h=0; *v != '\0'; v++, a = a*b % (M-1))
	  h  = (a*h + *v) % M;
   return h;
}





***calc.l***
//calc.l

	/* calculator #1 */
%{
	#include "y.tab.h"
	#include <stdlib.h>
	#include <string.h>
	void yyerror(char *);
%}

%%

[a-z]	   {
				// return a duplicate of yytext
				yylval.sValue =
				return VARIABLE;
				}

[0-9]+	  {
				yylval.iValue = atoi(yytext);
				return INTEGER;
			}

[-+()=/*\n]	 { return *yytext; }

[ \t]  ;	   /* skip whitespace */

.			   yyerror("Unknown character");

%%

int yywrap(void) {
	return 1;
}





***calc.y***
//calc.y

%{
	#include <stdio.h>
	void yyerror(char *);
	int yylex(void);

  
%}

%union {
	int   iValue;				 /* integer value */
	char* sValue;				/* a string value */
};


%token <iValue> INTEGER 
%token <sValue> VARIABLE
%left '+' '-'
%left '*' '/'

%type <iValue> expression

%%

program:
		program statement '\n'
		| /* NULL */
	   ;

statement:
		expression					  { printf("%d\n", $1); }
		| VARIABLE '=' expression	   { sym[$1] = $3; }
	   ;

expression:
		INTEGER
		| VARIABLE					  { $$ = sym[$1]; }
		| expression '+' expression	 { $$ = $1 + $3; }
		| expression '-' expression	 { $$ = $1 - $3; }
		| expression '*' expression	 { $$ = $1 * $3; }
		| expression '/' expression	 { $$ = $1 / $3; }
		| '(' expression ')'			{ $$ = $2; }
	   ;

%%

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

int main(void) {
	void print_header();
	print_header(); // do not remove
	yyparse();
}




Is This A Good Question/Topic? 0
  • +

Replies To: Calculator taking identifiers as variable names//yacc, lex, c

#2 Mr. Member  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 19-November 08

Re: Calculator taking identifiers as variable names//yacc, lex, c

Posted 20 November 2008 - 07:04 AM

Isn't there really no one to give me some instructions. There are experts among you guys. I need help.
Was This Post Helpful? 0
  • +
  • -

#3 Guest_Saumya Mishra*


Reputation:

Re: Calculator taking identifiers as variable names//yacc, lex, c

Posted 20 March 2010 - 09:46 AM

try this:
code for yacc file:
%{
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
       int yylex();

#define NVARS 100
       char *vars[NVARS]; double vals[NVARS]; int IsvalsDouble[NVARS]; int nvars=0;

int IsTermDouble = 0;
int IsMuldivDouble = 0;
int IsExprDouble = 0;

%}

%union { double dval; int ivar; }
%token <dval> FLOAT
%token <dval> INT;    
%token <ivar> VARIABLE
%type <dval> expr
%type <dval> muldiv
%type <dval> term


%%
program:
     line program
          | line
line:
     expr '\n' { printf("%g\n",$1); IsExprDouble = 0; }    
          | VARIABLE '=' expr '\n' { printf("Variable Update\n"); vals[$1] = $3; IsvalsDouble[$1] = IsExprDouble; }   

expr:          
     expr '+' muldiv { if(IsMuldivDouble == 1) IsExprDouble = 1; if(IsMuldivDouble == 0){int c1 = $1; int c2 = $3; $$ = c1 + c2;} else $$ = $1 + $3; }
     | expr '-' muldiv { if(IsMuldivDouble == 1) IsExprDouble = 1; if(IsMuldivDouble == 0){int c1 = $1; int c2 = $3; $$ = c1 - c2;} else $$ = $1 - $3; }
     | muldiv { if(IsMuldivDouble == 1) IsExprDouble = 1;$$ = $1; }

muldiv:
     muldiv '*' term { if(IsTermDouble == 1) IsMuldivDouble = 1; if(IsMuldivDouble == 0){int c1 = $1; int c2 = $3; $$ = c1*c2;} else $$ = $1 * $3; }
     | muldiv '/' term {if(IsTermDouble == 1) IsMuldivDouble = 1; if(IsMuldivDouble == 0){int c1 = $1; int c2 = $3; $$ = (c1/c2);} else $$ = $1 / $3; }
     | muldiv '%' term {if(IsTermDouble == 1) IsMuldivDouble = 1; if(IsMuldivDouble == 0){int c1 = $1; int c2 = $3; $$ = (c1 % c2);} else { printf("float not allowed in %\n"); return;} }
     | term { if(IsTermDouble == 1) IsMuldivDouble = 1; $$ = $1; }

term:         
   '(' expr ')' { $$ = $2; IsTermDouble = IsExprDouble;}
    | VARIABLE { $$ = vals[$1]; IsTermDouble = IsvalsDouble[$1]; }
    | FLOAT { $$ = $1;IsTermDouble = 1;}
    | INT {$$ = $1; IsTermDouble = 0; }

%%


int varindex(char *varname)
{
  int i;
  for (i=0; i<nvars; i++)
    if (strcmp(varname,vars[i])==0)
      return i;
  vars[nvars] = strdup(varname);
  return nvars++;
}
void yyerror(char *s)
{
  fprintf(stderr,"%s\n",s);
  return;
}
int main(void)
{
yyparse();
return 0;
}

Was This Post Helpful? 0

#4 Guest_Saumya Mishra*


Reputation:

Re: Calculator taking identifiers as variable names//yacc, lex, c

Posted 20 March 2010 - 09:48 AM

in lex file use:
%{
#include <stdlib.h>
#include <stdio.h>
#include "y.tab.h"
void yyerror(char*);
int varindex(char *var);
%}

%%

[ \t]   ;       /* skip whitespace */


([0-9]+) {          // to identify integer values
yylval.dval = atoi(yytext);
return INT;}

(([0-9]+(\.[0-9]*)?)|([0-9]*\.[0-9]+)) {    // to identify float values
yylval.dval = atof(yytext);
return FLOAT;}

[-+()=/%*\n]     { return *yytext; }            // to identify symbols

[a-z][a-z0-9]* {             // to identify variables
yylval.ivar = varindex(yytext);
return VARIABLE;}

. {char msg[25];        // for errors
sprintf(msg,"%s <%s>","invalid character",yytext);
yyerror(msg);
}

Was This Post Helpful? 0

#5 Guest_Roney Laeddis*


Reputation:

Re: Calculator taking identifiers as variable names//yacc, lex, c

Posted 21 March 2010 - 12:40 AM

I did a course on parsing and here is a simple calculator:
lex file:
%{
#include "y.tab.h"
extern int yylval;
%}

%%
[a-z A-Z]+                {yylval.s = findname(yytext); return identifier;}
[0-9]+                {yylval.i = atoi(yytext); return digit;}
[ \t\n]               ;
[-+*/()%=;]             {return yytext[0];}


%%

yywrap (void) {return 1;}



yacc file:
%{
#include <stdio.h>
#include <ctype.h>
int reg[1000];
%}
%union {int i,string s;}
%start input
%token  <s> identifier
%token  <i> digit 
%type <i> expression number
%left '+' '-'
%left '*' '/' '%'
%right '='

%%

input  : expression '\n'                   {printf ("result %d\n", $1);}
       | identifier '=' expression         {reg[$1]= $3;}
       ;
expression : '(' expression ')'            { $$ = $2; }
           | expression '+' expression     { $$ = $1 + $3; }
           | expression '-' expression     { $$ = $1 − $3; }
           | expression '*' expression     { $$ = $1 ∗ $3; }
           | expression '/' expression     { $$ = $1 / $3; }        
           | expression '%' expression     { $$ = $1 % $3; }
           | identifier                    { $$ = reg[$1]; }
           | number
           ;
number : digit       {$$ = $1;}
       | number digit  {$$ = $1*10 + $2; }
       | digit '.' digit  {$$ = $1 + $3*0.1; }
       ;
        
%%    

main (void) {
               return yyparse ( );
            }

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

This post has been edited by JackOfAllTrades: 21 March 2010 - 06:28 AM
Reason for edit:: Added code tags.

Was This Post Helpful? 0

Page 1 of 1