Search code examples
ccompiler-constructionbisonflex-lexerlex

Is it possible to define multiple 'names' in Flex/Lex?


I am trying to run flex on the following file with the arguments -lfl. I am received by the following errors:

romans.l:14: name defined twice
romans.l:16: name defined twice
romans.l:17: name defined twice
romans.l:19: name defined twice
romans.l:22: name defined twice
romans.l:23: name defined twice
romans.l:24: bad character: \
romans.l:24: unknown error processing section 1
romans.l:24: unknown error processing section 1
romans.l:24: bad character: {
romans.l:24: unknown error processing section 1
romans.l:24: unknown error processing section 1
romans.l:24: bad character: }
romans.l:25: unrecognised '%' directive
flex: can't open -lfl 

Let's ignore the other errors in my code for the moment, as I am confused as to why there exists an issue with lines 14 through 23. To the best of my knowledge, there shouldn't be an issue with what I am trying to do. Here is my lex file.

  1  %{
  2 // file created via echo
  3 # include <studio.h>
  4 # include "roman.tab.h"
  5 %}
  6 I{4}    { yyerror("syntax error");}
  7 V{4}    { yyerror("syntax error");}
  8 X{4}    { yyerror("syntax error");}
  9 C{4}    { yyerror("syntax error");}
 10 L{4}    { yyerror("syntax error");}
 11 D{4}    { yyerror("syntax error");}
 12 M{4}    { yyerror("syntax error");}
 13 CM      { yylval = 900; return ARABIC_NUMERAL /* NINEHUNDRED */;}
 14 M       { yylval = 1000; return ARABIC_NUMERAL /* THOUSAND */ ; }
 15 CD      { yylval = 400; return ARABIC_NUMERAL /*return FOURHUNDRED*/;}
 16 D       { yylval = 500; return ARABIC_NUMERAL /*return FIVEHUNDRED*/;}
 17 C       { yylval = 100; return ARABIC_NUMERAL /*return HUNDRED*/;}
 18 XL      { yylval = 40; return ARABIC_NUMERAL /*return FOURTY*/;}
 19 L       { yylval = 40; return ARABIC_NUMERAL /*return FIFTY*/;}
 20 IX      { yylval = 9; return ARABIC_NUMERAL /*return NINE*/; }
 21 IV      { yylval = 4; return ARABIC_NUMERAL /*return FOUR*/; }
 22 V       { yyval = 5; return ARABIC_NUMERAL /*return FIVE*/; }
 23 I       { yylval = 1; return ARABIC_NUMERAL /*return ONE*/; }
 24 \n      { return EOL }
 25 %

Numbers at the front are just the line numbers (copied from vim with :setnumber flag enabled).

I am assuming the fault has something to do with "return ARABIC_NUMERAL" line, but no where have I seen that this is explicitly against the rules of lex? Scratching my head here genuinely and would appreciate any pointers in the right direction.


Solution

  • Use this — using %% before and after the matching rules instead of %, etc.

    %{
    // file created via echo
    #include <stdio.h>
    #include "roman.tab.h"
    %}
    %%
    I{4}    { yyerror("syntax error");}
    V{4}    { yyerror("syntax error");}
    X{4}    { yyerror("syntax error");}
    C{4}    { yyerror("syntax error");}
    L{4}    { yyerror("syntax error");}
    D{4}    { yyerror("syntax error");}
    M{4}    { yyerror("syntax error");}
    M       { yylval = 1000; return ARABIC_NUMERAL /* THOUSAND */; }
    CM      { yylval =  900; return ARABIC_NUMERAL /* NINEHUNDRED */; }
    D       { yylval =  500; return ARABIC_NUMERAL /* FIVEHUNDRED */; }
    CD      { yylval =  400; return ARABIC_NUMERAL /* FOURHUNDRED */; }
    C       { yylval =  100; return ARABIC_NUMERAL /* HUNDRED */; }
    XC      { yylval =   90; return ARABIC_NUMERAL /* NINETY */; }
    L       { yylval =   50; return ARABIC_NUMERAL /* FIFTY */; }
    XL      { yylval =   40; return ARABIC_NUMERAL /* FORTY */; }
    X       { yylval =   10; return ARABIC_NUMERAL /* TEN */; }
    IX      { yylval =    9; return ARABIC_NUMERAL /* NINE */; }
    V       { yylval =    5; return ARABIC_NUMERAL /* FIVE */; }
    IV      { yylval =    4; return ARABIC_NUMERAL /* FOUR */; }
    I       { yylval =    1; return ARABIC_NUMERAL /* ONE */; }
    \n      { return EOL; }
    %%
    

    I 'fixed' studio.h to stdio.h, inserted a missing ; (after EOL) and a missing l (in yylval for V), and changed the second 40 to 50 (and the spelling of 'forty'). I added the XC and X rules — you seem to have overlooked 90 and 10.

    I also made the alignment and comments more symmetric; consistency is very important in programming.

    The second %% is optional; the first is not.

    You supply the -lfl option to your compiler when linking; you do not provide it to flex when converting the source. That's why you got the error about -lfl not being found.