Wir werden den abstrakten Programmbaum durch C++-Datenstrukturen darstellen. Dazu definieren wir eine abstrakte Basisklasse, die die Schnittstelle unserer syntaktischen Objekte festlegt:
class Node // abstrakte Basisklasse
{
protected:
int nodetype;
public:
Node(){};
virtual ~Node() {};
virtual void Read() = 0; // Einlesen von cin
virtual void Write() = 0; // Ausgabe auf cout
virtual int Iswf() = 0; // stat. Semantik
virtual void Compile() = 0; // übersetzen
};
typedef Node *Nodeptr;
class IntNode : public Node
{private:
int i;
public:
IntNode(int ini = 0);
~IntNode();
void Read();
void Write();
friend ostream& operator << (ostream &os,
const IntNode &n);
virtual int Iswf();
virtual void Compile() = 0;
};
class IdNode : public Node
{private:
char *name;
public:
IdNode(char *n= NULL);
~IdNode();
void Read();
void Write();
virtual int Iswf();
virtual void Compile();
};
class UnNode : public Node
{private:
Nodeptr l;
public:
UnNode(Nodeptr il = NULL, int iop = 0);
~UnNode();
void Read();
void Write();
virtual int Iswf();
virtual void Compile();
};
class BinNode : public Node
{private:
Nodeptr l, r;
public:
BinNode(Nodeptr il = NULL,
int iop = 0, Nodeptr ir = NULL);
~BinNode();
void Read();
void Write();
virtual int Iswf();
virtual void Compile();
};
typedef IntNode *IntNodeptr;
typedef IdNode *IdNodeptr;
typedef UnNode *UnNodeptr;
typedef BinNode *BinNodeptr;
Im Parser werden nun in den semantischen Aktionen die Knoten des abstrakten Programmbaums erzeugt. Wir betrachten wieder die arithmetischen Ausdrücke von OBERON-0:
%{
#include "ober.h"
%}
%union {Node *nodeptr;
char strval[256]; /* Identifikatoren */
long intval; /* Integerkonstanten */
}
%token <intval> multop divop modop andop addop subop orop
...
%token <intval> integer
%token <strval> ident
%type <intval> Sign Op1 Op2 Relop
%type <nodeptr> Factor Term SimpleExpression Expression
%start Expression
%%
Expression: SimpleExpression
{tree = $1;}
|
SimpleExpression Relop SimpleExpression
{tree = new BinNode($1,$2,$3);}
Relop: eqsy {$$ = eqsy;}
| neqsy {$$ = neqsy;}
| ltsy {$$ = ltsy;}
| lesy {$$ = lesy;}
| gtsy {$$ = gtsy;}
| gesy {$$ = gesy;}
SimpleExpression: SimpleExpression Op1 Term
{$$ = new BinNode($1, $2, $3);}
|
Term
{$$ = $1;}
|
Sign Term
{if ($1 = subop)
$$ = new UnNode($2, $1);
else $$ = $2;}
Sign: addop {$$ = addop;} | subop {$$ = subop;}
Op1: addop {$$ = addop;} | subop {$$ = subop;}
| orop {$$ = orop;}
Term: Factor Op2 Term
{$$ = new BinNode($1,$2,$3);}
|
Factor
{$$ = $1;}
Op2: multop {$$ = multop;} | divop {$$ = divop;}
| andop {$$ = andop;} | modop {$$ = modop;}
Factor: lpar Expression rpar
{$$ = $2;}
|
integer
{$$ = new IntNode($1);}
|
ident
{$$ = new StringNode($1);}
| notsy Factor
{$$ = new UnNode($2, $1);}
%%
Prof. Dr. Reinhard Völler