Yacc example on Ubuntu 17.04
Install Yacc:
sudo apt install bison
The Yacc input file calc.y:
%{
void yyerror(char *s);
#include<stdio.h> /* c declarations used in actions */
#include<stdlib.h>
int symbols[52]; /* symbol table a through z and A through Z */
int symbolVal(char symbol);
void updateSymbolVal(char symbol, int val);
%}
/* Yacc definitions
the union lets me specify the different types that my lexical analyzer can return
integers put in num and characters in id */
%union{int num; char id;}
%start line
%token print
%token exit_command
%token <num> number
%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);}
| line assignment ';' {;}
| line print exp ';' {printf("Printing %d\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;}
| identifier {$$ = symbolVal($1);}
;
%% /* c code */
int computeSymbolIndex(char token){
int idx = -1;
if(islower(token)){
idx = token - 'a' + 26; /* the lower case are going to map from 26 to 51 */
}
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];
}
/* update 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();//the function generated by yacc
}
void yyerror(char *s){fprintf(stderr, "%s\n",s);}
The lex input file calc.l
%{
#include"y.tab.h"
%}
%%
"print" {return print;}
"exit" {return exit_command;}
[a-zA-Z] {yylval.id = yytext[0]; return identifier;}
[0-9]+ {yylval.num = atoi(yytext); return number;}
[ \t\n] ;
[-+=;] {return yytext[0];}
. {ECHO; yyerror ("unexpected character");}
%%
int yywrap (void) {return 1;}
Commands to generate the interpreter:
yacc -d calc.y # to generate y.tab.h and y.tab.c is the actual generated parser lex calc.l # generates lex.yy.c gcc lex.yy.c y.tab.c -o calc
Sample results:

浙公网安备 33010602011771号