Yacc ist ein Framework, um eigene Interpreter zu erstellen.

Prerequisites:

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 <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;