Produktionen als Funktionen

Top  Previous  Next

Einführung > Produktionen als Funktionen

 

Der folgende Text ist für Benutzer gedacht, die schon über einige Programmiererfahrungen verfügen. Allen anderen wird das Nachvollziehen der Beispiele empfohlen.

 

Eine Produktion kann als eine Spezifikation zur Erzeugung einer Funktion angesehen werden, die einen Textabschnitt parst. Bei der Codeerzeugung entsteht aus dieser Spezifikation tatsächlich eine Funktion. Insofern können einer Produktion Parameter übergeben werden und sie selbst kann einen Wert zurück liefern. Innerhalb des Funktionskörpers der Produktion können Variablen und Konstanten definiert werden, die wiederum an andere Produktionen übergeben werden können, die wie Funktionen aufgerufen werden. Die aufgerufenen Produktionen parsen Unterabschnitte des Textabschnitts, den die aufrufende Produktion parst.

 

Beispiel

 

Im folgenden Beispiel ruft die Outer-Produktion die Inner-Produktion auf und erhält von letzterer einen String zurückgeliefert, der den Text enthält, den die Inner-Produktion erkannt hat.

 

Outer = 

"a"

{{str s = }}

Inner[s]

{{out << "found a and " << s;}}

 

 

Inner =

( "b" | "c" )

{{ return xState.str(); }}

 

 

Ist die Eingabe: "a b", dann

ist die Ausgabe: found: a and b

 

Ist die Eingabe: "a c", dann

ist die Ausgabe: found: a and c

 

 

Bei der Codeerzeugung erhält man (aufs Wesentliche verkürzt):

 

typedef std::string::const_iterator cts; )

 

 

// token ordered by symbol numbers

// ----------------------------------------------------

// Name               SymNo     regular expression

// ----------------------------------------------------

...

// a                      (  6 )         "a"

// b                      (  7 )         "b"

// c                      (  8 )         "c"

 

 

void COuterParser::Outer(cts xtBegin, cts xtEnd, plugin_type xpPlugin /*=NULL*/) 

{  

  sps xState(xtBegin, xtEnd);

  // ... falls xpPlugin == NULL neues lokale Plugin, sonst xpPlugin in xState einsetzen

  if( m_apOuterScanner->GetNext(xState, false))

  {

    Outer(xState, NULL, false);

  }

}   

 

//------------------------------------------------

void COuterParser::Outer(sps& xState, ...)

{

  m_apT0_a_of_OuterScanner->GetNext(xState, false);

 

  string s = 

  Inner(xState, ... );

  out << "found: a and " << s;

}

 

//-------------------------------------------------

std::string COuterParser::Inner(sps& xState, ...)

{

 

  switch ( Alt0_of_Inner( xState.Sym() ) )

  {

    case 7:  // "b"

    m_apT1_b_of_InnerScanner->GetNext(xState, true);

    break;

    case 8:  // "c"

    m_apT2_c_of_InnerScanner->GetNext(xState, true);

    break;

    default :

    throw tetra::CTT_ErrorUnexpected( ...);

  }

 

  return xState.str(); 

}

 

Die Scanner enthalten jeweils die Information, welche Token zulässig sind und die Zustandsvariable xState enthält die Information darüber, welches Token erkannt wurde, und welches erwartet wird.

 

 

Anmerkung:

Die Klammern um "b" | "c" sind notwendig, da sonst bei der ersten Alternative ein undefinierter Wert zurückgegeben wird.

 



Diese Seite gehört zur TextTransformer Dokumentation

Home  Inhalt  English