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

Page 1 of 1

## 4 Replies - 12904 Views - Last Post: 21 March 2010 - 12:40 AMRate Topic: 1 Votes //<![CDATA[ rating = new ipb.rating( 'topic_rate_', { url: 'https://www.dreamincode.net/forums/index.php?app=forums&module=ajax&section=topics&do=rateTopic&t=72667&amp;s=f7f4a61cd9fef1f802dff7426b5d8d3c&md5check=' + ipb.vars['secure_hash'], cur_rating: 5, rated: 0, allow_rate: 0, multi_rate: 1, show_rate_text: true } ); //]]>

### #1 Mr. Member

• New D.I.C Head

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

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

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) {
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

• New D.I.C Head

Reputation: 0
• 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.

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;
}
```

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

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.