Yacc ist ein Framework, um eigene Interpreter zu erstellen.
Prerequisites:
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 <stdio.h> /* C declarations used in actions */
#include <stdlib.h>
#include <ctype.h>
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 <num> number
%token <dec> decimal
%token <id> identifier
%type <num> line exp term
%type <id> 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;