parser.y:
codice:
%{
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "symtab.h"
#include "ast.h"

static int currType = 0;
static int uname = 0;
char *strUname[21];

int yylex(void);
void yyerror(nodeType **pTree, Scope *pScope, Scope **pScope2, char *s);
char *makeUniqueName(char *strName);
%}

%union {
    int iValue;                 /* interi e booleani */
    double dblValue;            /* valori in virgola mobile */   
    char *strValue;                /* stringhe */
    nodeType *nPtr;             /* puntatore al nodo dell'AST */
};

%token <strValue> ID
%token <strValue> STRING_LITERAL
%token <iValue> INTEGER_LITERAL
%token <dblValue> REAL_LITERAL
%token <iValue> BOOLEAN_LITERAL
%token WHILE IF PRINT
%token INT REAL BOOL STRINGA
%nonassoc IFX
%nonassoc ELSE

%left GE LE EQ NE '>' '<'
%left '+' '-'
%left '*' '/'
%nonassoc UMINUS

%type <nPtr> program stmt expr stmt_list


%parse-param {nodeType **pTree}
%parse-param {Scope *pScope}
%parse-param {Scope **pScope2}

%%

program:
        decl_list stmt_list               { *pTree = $2; }
        ;

decl_list:
        decl
        | decl_list decl
        ;
       
decl:    /* Vuoto */
        | type { sprintf(strUname, "%d", uname++); } var_list ';'
        ;       
       
type:
        INT { currType = T_INTEGER; }
        | REAL { currType = T_REAL; }
        | BOOL { currType = T_BOOLEAN; }       
        | STRINGA { currType = T_STRING; }       
        ;       
       
var_list:
        ID
        {
            Valore val;
            char *uniqueName;
            if ( currType == T_INTEGER )
                val.iVal = 0;
            else if ( currType == T_REAL )
                val.dblVal = 0.0;
            else if ( currType == T_BOOLEAN )
                val.bVal = 0;
            else
            {
                val.strVal = (char*)malloc(sizeof(char)*strlen($1)+1);
                strcpy(val.strVal, yylval.strValue);
            }
            scopeInsert(pScope, $1, currType, T_VAR, val, 0);
            uniqueName = makeUniqueName($1);
            scopeInsert(*pScope2, uniqueName, currType, T_VAR, val, 0);
        }       
        | var_list ',' ID
        {
            Valore val;
            char *uniqueName;           
            if ( currType == T_INTEGER )
                val.iVal = 0;
            else if ( currType == T_REAL )
                val.dblVal = 0.0;
            else if ( currType == T_BOOLEAN )
                val.bVal = 0;
            else
            {
                val.strVal = (char*)malloc(sizeof(char)*strlen($3)+1);
                strcpy(val.strVal, yylval.strValue);
            }           
            scopeInsert(pScope, $3, currType, T_VAR, val, 0);
            uniqueName = makeUniqueName($3);           
            scopeInsert(*pScope2, uniqueName, currType, T_VAR, val, 0);
        }
        ;       
       
stmt_list:
          stmt                  { $$ = $1; }
        | stmt_list stmt        { $$ = opr(';', 2, $1, $2); }
        ;
       
stmt:
          ';'                            { $$ = opr(';', 2, NULL, NULL); }
        | expr ';'                       { $$ = $1; }
        | PRINT expr ';'                 { $$ = opr(PRINT, 1, $2); }
        | ID '=' expr ';'                   {
                                            HashTable Dati;
                                            nodeType *nodePtr;
                                            char *uniqueName;               
                                            if ( !scopeFind(pScope, $1, &Dati) )
                                            {
                                                yyerror(pTree, pScope, pScope2, "identificatore non dichiarato\n");
                                                Dati.Tipo1 = T_BOOLEAN;
                                                Dati.Tipo2 = T_VAR;
                                                Dati.Value.bVal = 0;
                                                Dati.bInizializzato = 0;
                                                uniqueName = makeUniqueName($1);
                                                return 1;
                                            }                                                                               
                                            uniqueName = makeUniqueName($1);                                           
                                            nodePtr = id($1, uniqueName,  Dati.Tipo1, Dati.Tipo2, Dati.Value, Dati.bInizializzato);
                                            $$ = opr('=', 2, nodePtr, $3);
                                         }
        | WHILE '(' expr ')' stmt        { $$ = opr(WHILE, 2, $3, $5); }
        | IF '(' expr ')' stmt %prec IFX { $$ = opr(IF, 2, $3, $5); }
        | IF '(' expr ')' stmt ELSE stmt { $$ = opr(IF, 3, $3, $5, $7); }
        | '{' { scopePush(pScope); } decl_list stmt_list '}'    { $$ = $4; scopePop(pScope); }
        ;

expr:
          INTEGER_LITERAL       {
                                    Valore val;
                                    val.iVal = $1;
                                    $$ = con(T_INTEGER, val);
                                }
          | REAL_LITERAL        {
                                    Valore val;
                                    val.dblVal = $1;
                                    $$ = con(T_REAL, val);
                                }                               
          | BOOLEAN_LITERAL     {
                                    Valore val;
                                    val.bVal = $1;
                                    $$ = con(T_BOOLEAN, val);
                                }
          | STRING_LITERAL      {
                                    Valore val;
                                    int len = strlen($1);                                                                       
                                    val.strVal = (char*)malloc(sizeof(char)*len+1);
                                    strcpy(val.strVal, $1);
                                    $$ = con(T_STRING, val);
                                }                                                                                               
        | ID                    {
                                    HashTable Dati;       
                                    char *uniqueName;
                                    if ( !scopeFind(pScope, $1, &Dati) )
                                    {
                                        yyerror(pTree, pScope, pScope2, "identificatore non dichiarato\n");
                                        Dati.Tipo1 = T_BOOLEAN;
                                        Dati.Tipo2 = T_VAR;
                                        Dati.Value.bVal = 0;
                                        Dati.bInizializzato = 0;
                                        uniqueName = makeUniqueName($1);
                                        return 1;
                                    }                                   
                                    uniqueName = makeUniqueName($1);
                                    $$ = id($1, uniqueName, Dati.Tipo1, Dati.Tipo2, Dati.Value, Dati.bInizializzato);
                                }
        | '-' expr %prec UMINUS { $$ = opr(UMINUS, 1, $2); }
        | expr '+' expr         { $$ = opr('+', 2, $1, $3); }
        | expr '-' expr         { $$ = opr('-', 2, $1, $3); }
        | expr '*' expr         { $$ = opr('*', 2, $1, $3); }
        | expr '/' expr         { $$ = opr('/', 2, $1, $3); }
        | expr '<' expr         { $$ = opr('<', 2, $1, $3); }
        | expr '>' expr         { $$ = opr('>', 2, $1, $3); }
        | expr GE expr          { $$ = opr(GE, 2, $1, $3); }
        | expr LE expr          { $$ = opr(LE, 2, $1, $3); }
        | expr NE expr          { $$ = opr(NE, 2, $1, $3); }
        | expr EQ expr          { $$ = opr(EQ, 2, $1, $3); }
        | '(' expr ')'          { $$ = $2; }
        ;

%%

void yyerror(nodeType **pTree, Scope *pScope, Scope **pScope2, char *s)
{
    fprintf(stdout, "%s\n", s);
}

char *makeUniqueName(char *strName)
{
    char *uniqueName;
    int len1, len2;
   
    len1 = strlen(strName);
    len2 = strlen(strUname);
    uniqueName = (char*)malloc(len1+len2+1);
    strcpy(uniqueName, strName);
   
    return strcat(uniqueName, strUname);
}
codice:
bison -l -d -o parser.c parser.y
flex -f -L -Ca -olexer.c lexer.l
gcc -Wall -O2 main.c parser.c lexer.c ast.c symtab.c -o myparser
Il primo comando utilizza bison e produce i file parser.c e parser.h
Il secondo comando utilizza flex per produrre l'analizzatore lessicale, lexer.c

Il programma prodotto da gcc va richiamato passandogli da riga di comando un file che contiene il programmino che vogliamo interpretare.
Per esempio:

prova.prg:
codice:
int x, y;

x = 5;
y = 8;

print x + y;
codice:
./myparser prova.prg
output:
codice:
13
prova2.prg:
codice:
int i;

i = 0;

while ( i < 10 )
{
   print i;
   i = i + 1;
}
codice:
./myparser prova2.prg
output:
codice:
0
1
2
3
4
5
6
7
8
9