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 |