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;