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
", $2);}
        | line assignment ';'   {;}
        | line print exp ';'    {printf("Printing %d
", $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
",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;}
[ 	
]         ;
[-+=;]          {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:

原文地址:https://www.cnblogs.com/cxxszz/p/8682801.html