Created
October 15, 2012 17:56
-
-
Save gvx/3893986 to your computer and use it in GitHub Desktop.
Thingy to learn how to use Flex and Bison
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%{ | |
#include "units.tab.c" | |
%} | |
%option noyywrap | |
int -?[0-9]+ | |
%% | |
[ \t] /*empty*/ | |
m { return METER; } | |
kg { return KILOGRAM; } | |
s { return SECOND; } | |
A { return AMPERE; } | |
K { return KELVIN; } | |
mol { return MOLE; } | |
cd { return CANDELA; } | |
[a-zA-Z]+ { (*(char**)&yylval) = strdup(yytext); return OTHER; } | |
\* { return MUL; } | |
\/ { return DIV; } | |
\^ { return POW; } | |
{int} { yylval.i[0] = atoi(yytext); return INT; } | |
\n { return 0; } | |
\( { return LPAREN; } | |
\) { return RPAREN; } | |
\: { return COLON; } | |
. { return 256; } | |
%% |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%{ | |
#include <stdio.h> | |
#define YYSTYPE struct ints | |
struct ints { | |
int i[7]; | |
}; | |
int yylex(void); | |
void yyerror(char const*); | |
void construct(YYSTYPE); | |
YYSTYPE init(int); | |
char *names[7] = {"m", "kg", "s", "A", "K", "mol", "cd"}; | |
#define NNAMES 32 | |
char *othernames[NNAMES]; | |
YYSTYPE othervalues[NNAMES]; | |
int namesused = 0; | |
%} | |
%token METER | |
%token KILOGRAM | |
%token SECOND | |
%token AMPERE | |
%token KELVIN | |
%token MOLE | |
%token CANDELA | |
%token MUL | |
%token DIV | |
%token POW | |
%token INT | |
%token LPAREN | |
%token RPAREN | |
%token OTHER | |
%token COLON | |
%left MUL DIV | |
%right POW | |
%% | |
line : | |
| OTHER COLON exp { | |
char *s = *(char**)&$1; | |
if (namesused < NNAMES) | |
{ | |
othernames[namesused] = s; | |
othervalues[namesused++] = $3; | |
} | |
else | |
{ | |
puts("No names left."); | |
} | |
$$ = $3; | |
} | |
| exp { construct( $1 ); } | |
| error '\n' { yyerrok; } | |
; | |
exp: | |
METER { $$ = init(0); } | |
| KILOGRAM { $$ = init(1); } | |
| SECOND { $$ = init(2); } | |
| AMPERE { $$ = init(3); } | |
| KELVIN { $$ = init(4); } | |
| MOLE { $$ = init(5); } | |
| CANDELA { $$ = init(6); } | |
| exp MUL exp { | |
int i; | |
for (i = 0; i < 7; i++) | |
$$.i[i] = $1.i[i] + $3.i[i]; | |
} | |
| exp DIV exp { | |
int i; | |
for (i = 0; i < 7; i++) | |
$$.i[i] = $1.i[i] - $3.i[i]; | |
} | |
| exp POW INT { | |
int i; | |
for (i = 0; i < 7; i++) | |
$$.i[i] = $1.i[i] * $3.i[0]; | |
} | |
| LPAREN exp RPAREN { $$ = $2; } | |
| OTHER { | |
char *s = *(char**)&$1; | |
int i; | |
YYSTYPE unit_less = {0}; | |
$$ = unit_less; | |
for (i = 0; i < namesused; i++) | |
{ | |
if (!strcmp(othernames[i], s)) | |
{ | |
$$ = othervalues[i]; | |
break; | |
} | |
} | |
free(s); | |
} | |
; | |
%% | |
void construct(YYSTYPE input) | |
{ | |
int i; | |
int p = 0; | |
for (i = 0; i < 7; i++) | |
{ | |
int j = input.i[i]; | |
if (j) | |
{ | |
if (p) | |
{ | |
putchar(j > 0 ? '*' : (j=-j, '/')); | |
} | |
else if (j < 0) | |
{ | |
fputs("1/", stdout); | |
j=-j; | |
} | |
p = 1; | |
if (j == 1) | |
{ | |
fputs(names[i], stdout); | |
} | |
else | |
{ | |
printf("%s^%d", names[i], j); | |
} | |
} | |
} | |
if (!p) | |
{ | |
fputs("unit-less", stdout); | |
} | |
putchar(10); | |
} | |
int main (void) | |
{ | |
while (1) | |
{ | |
fputs("? ", stdout); | |
yyparse (); | |
} | |
} | |
void yyerror (char const *s) | |
{ | |
fprintf (stderr, "%s\n", s); | |
} | |
inline YYSTYPE init(int j) | |
{ | |
YYSTYPE ss = {0}; | |
ss.i[j] = 1; | |
return ss; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
For /r/dailyprogrammer.