0
votes

I want to implement the abs operator in Flex and Bison; so far the program that I made is the following:

Bison file

%{
#include <stdio.h>
%}

/* declare tokens */
%token NUMBER
%token ADD SUB MUL DIV ABS
%token EOL

%%
calclist: /* nothing */
    | calclist exp EOL { 
                printf("= %d\n", $2); 
               }
;

exp: factor     
    | exp ADD factor { $$ = $1 + $3; }
    | exp SUB factor { $$ = $1 - $3; }
;

factor: term        
    | factor MUL term { $$ = $1 * $3; }
    | factor DIV term { $$ = $1 / $3; }
;

term: NUMBER        
    | ABS term {if ($2>=0) $$=$2;
            else $$= - $2;}
;
%%
main(int argc, char **argv)
{
    yyparse();
}
yyerror(char *s)
{
    fprintf(stderr, "error: %s\n", s);
}

Flex file

%{
# include "f5.tab.h"
%}
/* recognize tokens for the calculator and print them out */

%%
"+" { return ADD; }
"-" { return SUB; }
"*" { return MUL; }
"/" { return DIV; }
"|" { return ABS; }
[0-9]+ { yylval = atoi(yytext); 
    return NUMBER; 
    }
\n  { return EOL; }
[ \t]   { /* ignore whitespace */ }
.   { 
        printf("Mystery character %c\n", *yytext); 
    }
%%
yywrap()
{
}

I compile it with:

bison -d bisonfile.y
flex flexfile.l
gcc bisonfile.tab.c lex.yy.c -o test.exe

Then when I enter one expression like the following:

34+|3

it outputs 37

but when I put something like:

34+|-3

it prints "syntax error"

Why is that? Any help would be valuable.

Thanks

2
you're lexing that as NUMBER, ADD, ABS, SUB, NUMBER which doesn't get handled by your parsing rules. You probably want to consider + and - as possible unary operations as wellRorschach
@jenesaisquoi could you give me some sort of solution? I have tried everything and nothing seems to workLittle
why don't you add another rule for unary expressions, eg. unary_expr: SUB ... | ...Rorschach

2 Answers

1
votes

Because - is not a number and | can only be applied to a number (or to another | applied to a number):

term: NUMBER
    | ABS term

So |- is a syntax error.

0
votes

The change can also be made in the lexer file, where we can define NUMBER to be a string of one or more digits optionally prefixed by either a + or a - symbol.

This would make the lexer file look as follows: (Note, in this case, there is no change needed for the bison file)

calc.lex

%{
    #include "calc.tab.h"
%}

%%

"+"                 { return ADD; }
"-"                 { return SUB; }
"*"                 { return MUL; }
"/"                 { return DIV; }
"|"                 { return ABS; }
("+"|"-")?[0-9]+    { yylval = atoi(yytext); return NUMBER; }
\n                  { return EOL; }
[ \t]               { /* ignore white spaces */ }
.                   { printf("Mystery character %s\n", yytext); }

%%

Edit:

  • An important implication from this definition of NUMBER is that now when you want addition or subtraction you need to write <space>+<space> and <space>-<space> respectively or else it will attach the operator with the number to its right.