Yacc ist ein Framework, um eigene Interpreter zu erstellen.
Prerequisites:
* Download [[http://gnuwin32.sourceforge.net/downlinks/flex.php|Flex 2.5.4a]]
* Download [[http://downloads.sourceforge.net/gnuwin32/bison-2.4.1-setup.exe|Bison 2.4.1]]
* Download [[http://sourceforge.net/projects/dev-cpp/files/Binaries/Dev-C%2B%2B%204.9.9.2/devcpp-4.9.9.2_setup.exe/download?use_mirror=switch|DevC++]]
* Install Flex at "C:\GnuWin32"
* Install Bison at "C:\GnuWin32"
* Install DevC++ at "C:\Dev-Cpp"
* Open Environment Variables and dd "C:\GnuWin32\bin;C:\Dev-Cpp\bin;" to path.
[[https://www.youtube.com/watch?v=54bo1qaHAfk|Youtube tutorial]]
=====Example=====
File: calc.l
%{
#include "y.tab.h"
void yyerror (char *s);
int yylex();
%}
%%
"print" { return print; }
"printr" { return printr; }
"exit" { return exit_command; }
[a-zA-Z] { yylval.id = yytext[0]; return identifier; }
[0-9]+ { yylval.num = atoi(yytext); return number; }
[0-9]+\.[0-9]+ { yylval.dec = atof(yytext); return decimal; }
[ \t\n] ;
[-+=;] { return yytext[0]; }
. { ECHO; yyerror ("unexpected character"); }
%%
int yywrap (void) {return 1;}
File: calc.y
%{
void yyerror (char *s);
int yylex();
#include /* C declarations used in actions */
#include
#include
int symbols[52];
int symbolVal(char symbol);
void updateSymbolVal(char symbol, int val);
float tof(int i);
%}
%union {int num; char id; float dec;} /* Yacc definitions */
%start line
%token print
%token printr
%token exit_command
%token number
%token decimal
%token identifier
%type line exp term
%type assignment
%%
/* descriptions of expected inputs corresponding actions (in C) */
line : assignment ';' { ; }
| exit_command ';' { exit(EXIT_SUCCESS); }
| print exp ';' { printf("Printing %d\n", $2); }
| printr exp ';' { printf("Printing %f\n", $2); }
| line assignment ';' { ; }
| line print exp ';' { printf("Printing %d\n", $3); }
| line printr exp ';' { printf("Printing %f\n", $3); }
| line exit_command ';' { exit(EXIT_SUCCESS); }
;
assignment : identifier '=' exp { updateSymbolVal($1,$3); }
;
exp : term { $$ = $1;}
| exp '+' term { $$ = $1 + $3; }
| exp '-' term { $$ = $1 - $3; }
;
term : number { $$ = $1; }
| decimal { $$ = tof($1); }
| identifier { $$ = symbolVal($1); }
;
%%
/* C code */
float tof(int i) {
float f = i + 0.0;
return f;
}
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 symbol */
void updateSymbolVal(char symbol, int val)
{
int bucket = computeSymbolIndex(symbol);
symbols[bucket] = val;
}
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);}
Compilation
flex calc.l
bison -dy calc.y
gcc -g lex.yy.c y.tab.c -o calc
Example
C:\> calc
a = 1;
b = 2;
c = a + b;
print c;