CTT_Guard

Top  Previous  Next

Codeerzeugung > Unterstützender Code > CTT_Guard

 

template <class char_type, class plugin_type> class CTT_Guard

 

Zu Beginn einer jeden Produktion sorgt der Konstruktor einer Instanz der Klasse CTT_Guard dafür, dass ein Stack aktualisiert wird, der aus den Scannern besteht  - genauer: aus Zeigern auf die Scanner -, die am Ende des Aufrufs der Produktion zu testen sind. Beim Verlassen der Produktion sorgt der Destruktor von CTT_Guard für die erneute Aktualisierung des Stacks, indem der zu Beginn hinzugefügte Scanner wieder entfernt wird. Der Destruktor wird benutzt, da andere Anweisungen nach einer return-Anweisung nicht mehr ausgeführt würden.

 

Der 1. Template-Parameter kann entweder char oder wchar_t sein. Der 2. Template-Parameter ist entweder CTT_ParseStatePlugin oder ein davon abgeleiteter Typ.

 

 

Makros:

 

Der vom TextTransformer produzierte Code soll portabel sein, d.h.er soll auf verschiedenen Systemen und mit verschiedenen C++-Kompilern funktionieren.

Wegen einer Besonderheit von Microsoft Visual Express C++ ist es erforderlich den gesamten Code einer Produktion mittels zweier Makros in einen try-catch-Block einzuschließen, damit der Aufruf des Destruktors tatsächlich zum gewünschten Zeitpunkt erfolgt.

 

#define ENTER_GUARD(number, production) \

  GUARD Guard = ProductionBegin(xState, xiScannerIndex, xiSkipScannerIndex, xeLS, number, production); \

  try {

 

(ENTER_CONST_GUARD and ENTER_LA_GUARD sind entprechende Makros für const-Parser und Vorausschauen.)

 

#define EXIT_GUARD(number, returnvalue) \

       } \

  catch (...) { \

     if(xiScannerIndex > -2) \

        throw; \

  } \

  Guard.StayAlive(); \

  return returnvalue;

 

 

In Visual Express C++ sorgt nämlich eine "Optimierung" dafür, dass die CTT_Guard-Variable sofort nach ihrer Erzeugung wieder aufgeräumt wird. Um die Variable bis zum Verlassen der Produktion am Leben zu erhalten, muss dem Microsoft-Compiler vorgegaukelt werden, dass sie nochmals benötigt würde. Deshalb wird am Ende der Produktion, nach dem catch-Block, nochmals die ansonsten funktionslose StayAlive-Funktion der CTT_Guard-Klasse aufgerufen. Diese Funktion  wird nur durchlaufen, wenn die Produktion keinen Wert zurück gibt. Andernfalls erfolgt die Rückgabe schon innerhalb des try-catch-Blocks. Wenn tatsächlich eine Ausnahme ausgeworfen wird, wird sie mit throw auf jeden Fall weitergereicht. Die Bedingung:

 

if(xiScannerIndex > -2)

 

ist durch den Code-Generator immer erfüllt.Dem Compiler gilt der StayAlive-Aufruf aber als erreichbar.

 

Die letzte Zeile des Makros ist erforderlich, damit der Code kompiliert:

 

return returnvalue;

 

Wenn die Produktion keinen Wert zurück gibt bleibt returnvalue leer.Wenn die Produktion aber einen Wert zurück gibt, muss ein Default-Wert für den Rückgabetyp bekannt sein, obwohl die Zeile tatsächlich niemals ausgeführt wird. Dieser Wert kann daher beliebig sein, solange er nur zum entsprechenden Rückgabetyp passt. Für den Interpreter-Code wird der Rückgabewert automatisch generiert. Wenn aber in Code, der nur für den Export bestimmt ist ein Rückgabetyp definiert ist, muss der Default-Wert angegeben werden. Dies kann im Feld für den Rückgabetyp geschehen, indem ein Schrägstrich mit nachfolgendem Wert geschrieben wird. Z.B.:

 

{_ CProduktion* _}/NULL

 

 

 

 

 



Diese Seite gehört zur TextTransformer Dokumentation

Home  Inhalt  English