The usual way is to use different flex rules for the different classes of tokens that can occur, with A_OR_B tokens for things that might be two different things:
[0-9]+ {
yylval.u32 = strtol(yytext, 0, 10);
return NUMBER; }
[a-fA-F][a-fA-F0-9]* {
yylval.string = strdup(yytext);
return NUMBER_OR_NAME; }
[a-fA-F0-9]+ {
yylval.u32 = strtol(yytext, 0, 16);
return NUMBER; }
[a-zA-Z][a-zA-Z0-9]* {
yylval.string = strdup(yytext);
return NAME; }
Flex will always try to match the longest match, but when multiple patterns match the same length, it will match the first one.
In your parser, you use rules like:
name: NAME | NUMBER_OR_NAME ;
number: NUMBER | NUMBER_OR_NAME { $$ = strtol($1, 0, 16); free($1); } ;