0
votes

Hi I am new in lex/yacc and i am practicing to implement a parser for definition of a set of variables say int x,y,z; double a, b; char c. I need to assign a constant value to variables and also manage character constants as well as print all variables with their types and values. I had some codes online which i edited but always run into errors. If there is anyone out there who can help me.

lex code(calc.l)

%{
#include "y.tab.h"
%}
%%
"print"                {return print;}
"exit"                 {return exit_command;}
[a-zA-Z]               {yylval.id = yytext[0]; return identifier;}
[0-9]+                 {yylval.num = atoi(yytext); return number;}
[a-zA-Z]               {yylval.const = yytext[0]; return character;}
[0-9]*\.[0-9]+         {yylval.num = atoi(yytext); return decimal;}
[ \t\n]                ;
[-+=;]                 {return yytext[0];}
.                      {ECHO; yyerror ("unexpected character");}

%%
int yywrap (void) {return 1;}

yacc code(calc.y)

 %{
    void yyerror (char *s);

#include <stdio.h>     /* C declarations used in actions */
#include <stdlib.h>
int symbols[52];
int symbolVal(char symbol);
void updateSymbolVal(char symbol, int val);
void updateSymbolValD(char symbol, double dval);
void updateSymbolValC(char symbol, char cval);
%}

%union {int num; char id;double deci;char const;}         /* Yacc definitions */
%start line
%token print
%token exit_command
%token <num> number
%token <id> identifier
%token <deci> decimal
%token <const> character
%type <num> line exp term 
%type <id> assignment

%%

/* descriptions of expected inputs     corresponding actions (in C) */

line    : assignment ';'        {;}
        | exit_command ';'      {exit(EXIT_SUCCESS);}
        | print exp ';'         {printf("Printing %d\n", $2);}
        | line assignment ';'   {;}
        | line print exp ';'    {printf("Printing %d\n", $3);}
        | line exit_command ';' {exit(EXIT_SUCCESS);}
        ;

assignment : identifier '=' exp  { updateSymbolVal($1,$3); }
            ;
exp     : term                  {$$ = $1;}
        ;
term    : number                {$$ = $1;}
        | character             {$$ = $1;}
        | decimal               {$$ = $1;}
        | identifier            {$$ = symbolVal($1);} 
        ;

%%                     /* C code */

int computeSymbolIndex(char token)
{
    int idx = -1;
    if(islower(token)) {
        idx = token - 'a' + 26;
    } else if(isupper(token)) {
        idx = token - 'A';
    }
    return idx;
} 

/* returns the value of a given symbol */
int symbolVal(char symbol)
{
    int bucket = computeSymbolIndex(symbol);
    return symbols[bucket];
}

/* updates the value of a given integer symbol */
void updateSymbolVal(char symbol, int val)
{
    int bucket = computeSymbolIndex(symbol);
    symbols[bucket] = val;
}

/* updates the value of a given double symbol */
void updateSymbolVal(char symbol, double dval)
{
    int bucket = computeSymbolIndex(symbol);
    symbols[bucket] = dval;
}

/* updates the value of a given character symbol */
void updateSymbolVal(char symbol, char cval)
{
    int bucket = computeSymbolIndex(symbol);
    symbols[bucket] = cval;
}

int main (void) {
    /* init symbol table */
    int i;
    for(i=0; i<52; i++) {
        symbols[i] = 0;
    }

    return yyparse ( );
}

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

It always gives me the error ""calc.l", line 9: warning, rule cannot be matched" which is this line of code " [a-zA-Z] {yylval.const = yytext[0]; return character;}"

I have changed my lex and yacc codes to the codes below and have run into another error. Am hoping there is someone out there to help me with the understanding of the error and how to get the codes running.I have search online for the meaning of the error but m not getting the understanding.

**Lex codes**

calc.l

    %{
    #include "y.tab.h"
    %}
    %%
    "print"                {return print;}
    "exit"                 {return exit_command;}
    [a-zA-Z]               {yylval.id = yytext[0]; return identifier;}
    [0-9]+                 {yylval.num = atoi(yytext); return number;}
    [\'.\']                {yylval.const = yytext[0]; return character;}
    [0-9]*\.[0-9]+         {yylval.deci = atof(yytext); return decimal;}
    [ \t\n]                ;
    [=;]               {return yytext[0];}
    .                      {ECHO; yyerror ("unexpected character");}

    %%
    int yywrap (void) {return 1;}

**yacc codes**
  **calc.y**

%{
void yyerror (char *s);
#include <stdio.h>     /* C declarations used in actions */
#include <stdlib.h>
int symbols[52];
int symbolVal(char symbol);
void updateSymbolVal(char symbol, int val);
void updateSymbolValD(char symbol, double dval);
void updateSymbolValC(char symbol, char cval);
%}

%union {int num; char id;double deci;char const;}         /* Yacc definitions */
%start line
%token print
%token exit_command
%token <num>  number
%token <id> identifier
%token <deci> decimal
%token <const> character
%type <id> assignment 
%type <id> charact_assign 
%type <id> double_assign
%type <num>  exp 
%type <const> char_con
%type <deci> real_val


%%

/* descriptions of expected inputs     corresponding actions (in C) */

line    : assignment  ';'       {;}
        | charact_assign ';'    {;}
        | double_assign  ';'    {;}     
        | exit_command ';'      {exit(EXIT_SUCCESS);}
        | print assignment ';'  {printf("Printing %d\n", $2);}
        | line assignment ';'   {;}
        | line charact_assign ';' {;}
        | line double_assign ';'  {;}
        | line print assignment ';' {printf("Printing %d\n", $3);}
        | line exit_command ';' {exit(EXIT_SUCCESS);}
        ;

assignment : identifier '=' exp  { updateSymbolVal($1,$3); }
            ;

exp     : number                {$$ = $1;} 
        ;
charact_assign: identifier '=' char_con        { updateSymbolVal($1,$3); }
              ;

char_con      : character       {$$ = $1;}    
              ;
double_assign: identifier '=' real_val  { updateSymbolVal($1,$3); }
             ;

real_val     : decimal    {$$ = $1;}
             ;

%%                     /* C code */

int computeSymbolIndex(char token)
{
    int idx = -1;
    if(islower(token)) {
        idx = token - 'a' + 26;
    } else if(isupper(token)) {
        idx = token - 'A';
    }
    return idx;
} 

/* returns the value of a given symbol */
int symbolVal(char symbol)
{
    int bucket = computeSymbolIndex(symbol);
    return symbols[bucket];
}

/* updates the value of a given integer symbol */
void updateSymbolVal(char symbol, int val)
{
    int bucket = computeSymbolIndex(symbol);
    symbols[bucket] = val;
}

/* updates the value of a given double symbol */
void updateSymbolVal(char symbol, double dval)
{
    int bucket = computeSymbolIndex(symbol);
    symbols[bucket] = dval;
}

/* updates the value of a given character symbol */
void updateSymbolVal(char symbol, char cval)
{
    int bucket = computeSymbolIndex(symbol);
    symbols[bucket] = cval;
}

int main (void) {
    /* init symbol table */
    int i;
    for(i=0; i<52; i++) {
        symbols[i] = 0;
    }

    return yyparse ( );
}

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


**`Below are the errors i am running into:`**

    "calc.y", line 12: unrecognized '%' directive
    "calc.y", line 14: unrecognized '%' directive
    "calc.y", line 15: unrecognized '%' directive
    "calc.y", line 16: unrecognized '%' directive
    "calc.y", line 17: unrecognized '%' directive
    "calc.y", line 18: unrecognized '%' directive
    "calc.y", line 19: unrecognized '%' directive
    "calc.y", line 20: unrecognized '%' directive
    "calc.y", line 21: unrecognized '%' directive
    "calc.y", line 22: unrecognized '%' directive
    "calc.y", line 23: unrecognized '%' directive
    "calc.y", line 24: unrecognized '%' directive
    "calc.y", line 25: unrecognized '%' directive
    "calc.y", line 30: unrecognized rule
    "calc.y", line 30: unrecognized rule
    "calc.y", line 30: unrecognized rule
    "calc.y", line 34: unrecognized rule
    "calc.y", line 35: unrecognized rule
    "calc.y", line 36: unrecognized rule
    "calc.y", line 37: unrecognized rule
    "calc.y", line 38: unrecognized rule
    "calc.y", line 39: unrecognized rule
    "calc.y", line 40: unrecognized rule
    "calc.y", line 41: unrecognized rule
    "calc.y", line 42: unrecognized rule
1

1 Answers

2
votes

You have the same pattern twice:

[a-zA-Z]               {yylval.id = yytext[0]; return identifier;}
[0-9]+                 {yylval.num = atoi(yytext); return number;}
[a-zA-Z]               {yylval.const = yytext[0]; return character;}

So, anything that matches a-zA-Z will be matched by the first one, and nothing will ever match the second one.

In case it wasn't clear: a lex/flex lexer considers the rules in order, so the first rule that matches an input is the one that's used (and even if they would match, later patterns aren't considered if an earlier one matches). This is why (for example) you always put the . pattern last (assuming you use it, but you usually do)--since it will match anything, no pattern following it can ever match anything.