1
votes

I am to implement a parser using lex/yacc for the definitions of variables in c language. For example:

int x,y,z;
double a,b;
char c;

and then assign values to the variables. For example:

x = 2
a=2.5
c = 't'

I want to try with int and double for the start so that once it works I modify and introduce char definition and assignment but as it stands now I am unable to define a variable on a single line with my code. Anytime I try I get syntax error. This is the error I get:

double t,y,e;
doublet,ysyntax error

I am hoping there are guys out there to help me solve this problem.

lex file

edited.lex

%{

#include <ctype.h>
#include<stdio.h>
#include <stdlib.h>
#include <string.h>
/* include YACC symbol encoding */
#include "calc.h"
#include "edited.tab.h"


char varname[256];

%}

%option noyywrap

DIGIT [0-9]+

ID [a-zA-Z][a-zA-Z0-9]*


%%
    symbtbl *ptr; /* local variable */

int|float|double|char                 { ECHO;return DATATYPE; }
[[:space:]]                           /* skip spaces */
{DIGIT}+"."{DIGIT}*|"."{DIGIT}+              {sscanf(yytext,"%lg",&yylval.val); ECHO;return DECIMAL;}


"'"."'"                      {sscanf(yytext,"%c",&yylval.vchar); ECHO;return CHARACTER;}  
"," { return yytext[0];}
";" { return yytext[0];}
{ID}   {strcpy(varname,yytext); yylval.sptr=varname;ECHO; return VAR;}
%%

yacc file edited.y

%{
/* math functions */
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "calc.h"


/* custom data structure definitions */


}*/

%}

/* bison data types for symbols */
%union{
  double val;    /* numeric data */
  char vchar;

   /* reference to variables*/
   symbtbl *sptr;

} 

%start Program


%token <val>DECIMAL
%token <vchar>CHARACTER
%token <sptr> VAR 
%token DATATYPE
%left declaration_list
%type <val> declaration_list 
%type <val> assignment_variable 
%type <val> exp 



%%
 Program                :  Program statement
                        ;

 statement              : vardef
                        | assignment_variable
                        ;
vardef                  :  DATATYPE declaration_list ';'|vardef
                        ;
declaration_list        : VAR {$1->value.var;printf("%s",$1->value.var);}
                        | declaration_list ',' VAR   {$1->value.var;}
                        ;
assignment_variable     : VAR '=' exp ';' {$1->value.var=$3;}                     
                        ;                 


exp                     : DECIMAL     {$$=$1;} 
                        ;                      

/*
 * error message handling
 */3
%%
#include <stdio.h>
#include <ctype.h>
char *p;
yyerror(char *s) {
  printf("%s\n",s);
}

main( argc, argv )
char *argv[];
{
  p = argv[0];

  yyparse();
}

symbol table utils.c

/*
 * Symbol table management functions
*/

#include <string.h>
#include <stdlib.h>

#include "calc.h"

/* head of symbol table list */
symbtbl *st=NULL;

/* add a symbol to table given name and type */

symbtbl *putsymb(char *name, int type) {
    symbtbl *ptr;
    if((ptr=(symbtbl *)(malloc(sizeof(symbtbl))))==NULL) {
        return(NULL); /* allocation failed */
    }
    ptr->name = strdup(name);
    if(ptr->name==NULL) {
        free(ptr);
        return(NULL); /* allocation failed */
    }
    ptr->type=type;
    ptr->value.var=0;
    /* add to list */
    ptr->next=st;
    st=ptr;
    return ptr;
}

/* get a symbol from table */

symbtbl *getsymb(char *name) {
    symbtbl *ptr;
    /* scan the list for element */
    for(ptr=st;ptr!=NULL;ptr=ptr->next)
        if(!strcmp(ptr->name,name))
           return ptr;

    return(NULL); /* not found */
}

header file calc.h

/*
 * Symbol Table element
 * The Symbol Table is a list of entries
 * that represent variables or functions
 */

typedef struct SymbTbl {
  char *name; /* symbol name */
  int type; /* symbol type VAR|FNCT */
  union  {
      double var; /* variable value */
      double (*fnctptr)(); /* function pointer */
  } value; /* value/function associated to symbol */
    struct SymbTbl *next; /* list forward pointer */
} symbtbl;

/* global variables */

extern symbtbl *st; /* head of symbol table list */

/* function prototypes */

symbtbl *putsymb(char *,int);
symbtbl *getsymb(char *);
1
Your DIGIT rule includes a + at the end; adding + or * when you use it is, at best, inviting confusion. It isn't clear to me how you get a token back for = signs. Your sample C assignments are missing semicolons.Jonathan Leffler

1 Answers

0
votes

I tried to use bison to generate de parser but i get some errors. I do new rules from blank following the same spirit. I think you need to understand the purpose of the stack because you have only one semantic action using $$. Additionally I think "$1->value.var;" in the semantic action have no sense because is not a function call or assignment.

Here the code, i hope can be helpful

edited.lex

%{

#include <ctype.h>
#include<stdio.h>
#include <stdlib.h>
#include <string.h>
/* include YACC symbol encoding */
#include "edited.tab.h"


char *varname;
char *strdatatype;

%}

%option noyywrap

DIGIT [0-9]+

ID [a-zA-Z][a-zA-Z0-9]*


%%

int|float|double|char           { strdatatype = strdup(yytext); yylval.str=strdatatype; return DATATYPE; }
[[:space:]]             /* skip spaces

INT (1, 2, 3, ...) | (FLOAT or DOUBLE) 1., 2.3, ... | .12, .23, ... */
{DIGIT}+|{DIGIT}+"."{DIGIT}*|"."{DIGIT}+        {sscanf(yytext,"%lg",&yylval.val); return DECIMAL; }

    /* if you want keep the "'" characters yylval.vchar cannot be char type. "'" are added in the semantic action */
"'"."'"                 { yylval.vchar = yytext[1]; return CHARACTER; }  
"," { return yytext[0];}
";" { return yytext[0];}
"=" { return yytext[0];}
{ID}                    { varname = strdup(yytext); yylval.str=varname; return VAR; }
%%

edited.y

%{
/* math functions */
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* custom data structure definitions */

%}

/* bison data types for symbols */
%union{
  double val;    /* numeric data */
  char vchar;
  char *str;
};

%start Program

%token <val>DECIMAL
%token <vchar>CHARACTER
%token <str> VAR
%token <str> DATATYPE

%type <str> statement;
%type <str> inner_statement;
%type <str> vardef;
%type <str> declaration_list;
%type <str> assignment_variable;
%type <str> exp;

%%

Program         : statements
            ;

statements      : statements statement
            | /* lambda */
            ;

statement       : inner_statement ';' {printf("%s; OK\n", $1);}
            ;

inner_statement     : vardef { $$ = $1; }
            | assignment_variable { $$ = $1; }
            ;

vardef          : DATATYPE declaration_list { char tmp[255]; sprintf(tmp, "%s %s", $1, $2); $$ = strdup(tmp);}
            ;

declaration_list    : VAR { $$ = $1;}
            | declaration_list ',' VAR { char tmp[255]; sprintf(tmp, "%s, %s", $1, $3); $$ = strdup(tmp);};

assignment_variable : VAR '=' exp { char tmp[255]; sprintf(tmp, "%s = %s", $1, $3); $$ = strdup(tmp);}

exp         : DECIMAL { char tmp[255]; sprintf(tmp, "%lf", $1); $$ = strdup(tmp); }
            | CHARACTER { char tmp[255]; sprintf(tmp, "'%c'", $1); $$ = strdup(tmp); }
            ;


/*
 * error message handling
 */
%%
#include <stdio.h>
#include <ctype.h>
char *p;
yyerror(char *s) {
  printf("error %s\n",s);
}

main( argc, argv )
char *argv[];
{
  p = argv[0];

  yyparse();
}