#1 22.10.2007 16:36:33

simon
ProMember
Ort: Düsseldorf
Registriert: 03.06.2006
Beiträge: 168

strings interpretieren

Hi,

hab bis jetzt eigentlich recht wenig mit "string's" herum experimentiert und hab jetzt ein kleines Problem. sad
Ich möchte nun zB einige Aktionen ausführen, dabei aber nicht in den Sourcecode eingreifen.
Solange die Textdatei mit einfachen Aktionen "gefüllt" ist, ist das kein Problem.
zB:

reload_player
reload_gui
destroy_ai

da lese ich die Zeile aus und mache einfach nur: "if fstring = 'reload_player' then script.reload_player;"

so, wie komme ich aber nun damit zurecht?:
CREATE_TOWN(2, "2248.68,2240.36", "PLAYER_TWO", 6, "GREEK")
natürlich kann das auch anders aussehen - wenn es denn einfacher zu bearbeiten ist zb:
create_TOWN 2 2248.68 2240.36 player_two 6 greek
gibt es bei so was Hilfe wie bei Ini Dateien ??

Beitrag geändert von simon (22.10.2007 17:05:06)


grrr

Offline

 

#2 22.10.2007 17:30:20

Chris
ExtremeMember
Ort: Erlangen, Bay
Registriert: 24.01.2005
Beiträge: 694
Web-Seite

Re: strings interpretieren

du kannst auf einen String zugreifen wie auf ein Array:

Code:

s := 'Hallo';

//s[1] ist dann 'H' s[2] ist 'a'

s[5] := 'ö'; //gibt 'Hallö'

Also ich würde mit einer Schleife durch die einzelnen Strings rennen und dann die Parameter rausschreiben. ein Komma ist dabei das Trennzeichen.
Was du also versuchst ist einen Parser für Strings zu schreiben. Das ist gar nicht so einfach. Ich hab das grade für meine Facharbeit gemacht, und der unterstützt auch bloß die einfachsten Dinge. Proceduren mit Paramertern aufrufen. Sonst eigentlich nicht viel.
Mit einigen Tricks kann man nach Procedure-Namen suchen dann fällt das "if s='ReloadPlayer' then reloadplayer(); weg. Dann kann man einfach Execute('ReloadPlayer') aufrufen. Wenn dich das interessiert solltest du dir:

1. Die TypInfo.pas anschauen
2. Weiter fragen stellen.

mfg Chris


Nimm meinen Rat an - ich brauch ihn sowieso nicht

Offline

 

#3 22.10.2007 17:46:04

Dreamworld
UltraMember
Ort: Karlsruhe
Registriert: 06.12.2005
Beiträge: 368

Re: strings interpretieren

Wahrscheinlich kapier ich das Problem mal wieder ned, weil ich seh keins smile
aber du kannst doch einfach eine Zeile einlesen, und dann mit PosEx nach nem Leerzeichen suchen bis die ganze Zeile abgearbeitet ist, oder über Copy die Länge inkrementieren bis Leerzeichen, usw.

grml natürlich war wer schneller, aba egal

Beitrag geändert von Dreamworld (22.10.2007 17:46:38)

Offline

 

#4 22.10.2007 20:12:09

Coolcat
ProGuru
Ort: Aachen, NRW
Registriert: 24.01.2005
Beiträge: 2780
Web-Seite

Re: strings interpretieren

Vielleicht ein wenig Background wie man an sowas rangeht:

Ein Parser ist vom Prinzip ein sog. endlicher Automat. Zunächst einmal hast du eine gewisse Anzahl von Zuständen, z.B.

  • "Beginn einer Zeile" (Startzustand)
  • "Lese Befehlsname"
  • "Erwarte öffnende Klammer für Parameterliste"
  • "Lese Parameterliste"
  • "Lese Parameter vom Typ Integer"
  • ...


Nun definierst du noch ich welchen Zustand du wechselst, wenn du ein Zeichen a liest während du im Zustand q bist. Nebenbei speicherst du noch Dinge wie die Anfangsposition eines Parameters den du gerade ließt. Wenn du am Ende eines Parameters ankommst kopierst du einfach den String von der gemerkten Position bis zur aktuellen Position.

smile


My software never has bugs. It just develops random features.

Offline

 

#5 22.10.2007 20:21:32

Coolcat
ProGuru
Ort: Aachen, NRW
Registriert: 24.01.2005
Beiträge: 2780
Web-Seite

Re: strings interpretieren

Hier ein XML-Parser den ich mal in C++ geschrieben hab. Ich hab ne Menge rausgekürzt, aber das Prinzip sollte klar werden. smile

Code:

int CConfigReader::loadXMLStream(CConfigNode* pNode, std::vector<char>& vcNodeData,
                                      SParserData* pParserData, const unsigned uiDepth)
{
  // ...Parameter-Check...

  // Zustände des Automaten
  enum EXMLState {
    ES_BEGIN, ES_TAGBEGIN, ES_TAGEND, ES_TAGNAME, ES_TAGSHORT, ES_TAG,
    ES_ATTRDATA_EQ, ES_ATTRDATA_BEG, ES_ATTRDATA, ES_ATTRDATA_ESC, ES_ATTRDATA_END,
    ES_ATTRTYPE_EQ, ES_ATTRTYPE_BEG, ES_ATTRTYPE, ES_ATTRTYPE_END,
    ES_DATA_OR_COMMENT, ES_COMMENT_BEG, ES_COMMENT, ES_COMMENT_END1, ES_COMMENT_END2,
    ES_DATA_BEG1, ES_DATA_BEG2, ES_DATA_BEG3, ES_DATA_BEG4, ES_DATA_BEG5, ES_DATA_BEG6, 
    ES_DATA, ES_DATA_END1, ES_DATA_END2 };

  // Hilfsvariablen initialisieren
  char c = 0;
  uint32 u = 0;
  EXMLState state = ES_BEGIN;
  uint32& uiPos = pParserData->uiPos;
  uint32& uiLine = pParserData->uiLine;
  const unsigned BUFFERSIZE = 32;
  char pNameBuffer[BUFFERSIZE];
  char pTypeBuffer[BUFFERSIZE];
  std::vector<char> vcData;

  // Stream einlesen
  while (uiPos < pParserData->uiLength) {
    c = pParserData->pData[uiPos++];

    switch (state) {
      
      // Tag-Begin
      
      case ES_BEGIN:
        if (c == '<') {
          pNameBuffer[0] = 0;
          pTypeBuffer[0] = 0;
          state = ES_TAGBEGIN; 
        }
        else if (!isspace(c)) {
          m_output << "WARNING: CConfigReader::loadXMLStream(), unexpected char, line: " << uiLine << "\n";
        }
        break;
      case ES_TAGBEGIN:
        if (isalnum(c)) {
          u = 0;
          pNameBuffer[u++] = c;
          if (u >= BUFFERSIZE) {
            pNameBuffer[BUFFERSIZE-1] = 0;
            m_output << "ERROR: CConfigReader::loadXMLStream(), too long tagname\n"
                     << "       '" << pNameBuffer << "', line: " << uiLine << "\n";
            return 1;
          }
          vcData.clear();
          state = ES_TAGNAME;
        }
        else if (c == '/') { u = 0; state = ES_TAGEND; }
        else if (c == '!') { state =  ES_DATA_OR_COMMENT; }
        else {
          m_output << "ERROR: CConfigReader::loadXMLStream(), unexpected char, line: " << uiLine << "\n";
          return 1;
        }
        break;
      case ES_DATA_OR_COMMENT:
        if (c == '-')      { state = ES_COMMENT_BEG; }
        else if (c == '[') { state = ES_DATA_BEG1; }
        else {
          m_output << "ERROR: CConfigReader::loadXMLStream(), unexpected char, line: " << uiLine << "\n";
          return 1;
        }
        break;

      // normaler Tag

      case ES_TAGNAME:
        if (isalnum(c)) {
          pNameBuffer[u++] = c;
          if (u >= BUFFERSIZE) {
            pNameBuffer[BUFFERSIZE-1] = 0;
            m_output << "ERROR: CConfigReader::loadXMLStream(), too long tagname\n"
                     << "       '" << pNameBuffer << "', line: " << uiLine << "\n";
            return 1;
          }
          state = ES_TAGNAME;
        }
        else if (c == '>') {
          pNameBuffer[u] = 0;
          uint16 uiId = CConfigNameTable::getInstance()->getIdFromName(pNameBuffer);
          if (pTypeBuffer[0]) {
            uiId |= CConfigNameTable::getInstance()->getIdFromName(pTypeBuffer);
          }
          if (uiId == CConfigNameTable::CNT_ID_ERROR) {
            m_output << "ERROR: CConfigReader::loadXMLStream(), illegal id, line: " << uiLine << "\n";
            return 1;
          }
          CConfigNode* pSubNode = new CConfigNode(uiId);
          pNode->push_back(pSubNode);
          int iError = loadXMLStream(pSubNode, vcData, pParserData, uiDepth+1);
          if (iError) { return iError; }
          state = ES_BEGIN;
        }
        else if (c == ' ' || c == '\t') {
          pNameBuffer[u] = 0;
          state = ES_TAG;
        }
        else {
          m_output << "ERROR: CConfigReader::loadXMLStream(), unexpected char, line: " << uiLine << "\n";
          return 1;
        }
        break;
      case ES_TAG:
        if (c == '>') {
          uint16 uiId = CConfigNameTable::getInstance()->getIdFromName(pNameBuffer);
          if (pTypeBuffer[0]) {
            uiId |= CConfigNameTable::getInstance()->getIdFromName(pTypeBuffer);
          }
          if (uiId == CConfigNameTable::CNT_ID_ERROR) {
            m_output << "ERROR: CConfigReader::loadXMLStream(), illegal id, line: " << uiLine << "\n";
            return 1;
          }
          CConfigNode* pSubNode = new CConfigNode(uiId);
          pNode->push_back(pSubNode);
          int iError = loadXMLStream(pSubNode, vcData, pParserData, uiDepth+1);
          if (iError) { return iError; }
          state = ES_BEGIN;
        }
        else if (c == ' ' || c == '\t') { state = ES_TAG; }
        else if (c == '/')              { state = ES_TAGSHORT; }
        else if (c == 'd')              { state = ES_ATTRDATA_EQ; }
        else if (c == 't')              { state = ES_ATTRTYPE_EQ; }
        else {
          m_output << "ERROR: CConfigReader::loadXMLStream(), unexpected char, line: " << uiLine << "\n";
          return 1;
        }
        break;
      case ES_TAGSHORT:
        if (c == '>') {
          uint16 uiId = CConfigNameTable::getInstance()->getIdFromName(pNameBuffer);
          if (pTypeBuffer[0]) {
            uiId |= CConfigNameTable::getInstance()->getIdFromName(pTypeBuffer);
          }
          if (uiId == CConfigNameTable::CNT_ID_ERROR) {
            m_output << "ERROR: CConfigReader::loadXMLStream(), illegal id, line: " << uiLine << "\n";
            return 1;
          }
          CConfigNode* pSubNode = new CConfigNode(uiId, vcData);
          pNode->push_back(pSubNode);
          state = ES_BEGIN;
        }
        else {
          m_output << "ERROR: CConfigReader::loadXMLStream(), unexpected char, line: " << uiLine << "\n";
          return 1;
        }
        break; 

      // ...
      // ganz viel mehr Zustände
      // ...

      // Schluß-Tag

      case ES_TAGEND:
        if (isalnum(c)) {
          pNameBuffer[u++] = c;
          if (u >= BUFFERSIZE) {
            pNameBuffer[BUFFERSIZE-1] = 0;
            m_output << "ERROR: CConfigReader::loadXMLStream(), too long tagname\n"
                     << "       '" << pNameBuffer << "', line: " << uiLine << "\n";
            return 1;
          }
          state =  ES_TAGEND;
        }
        else if (c == '>') {
          pNameBuffer[u] = 0;
          uint16 uiId = CConfigNameTable::getInstance()->getIdFromName(pNameBuffer);
          if (uiId == (pNode->getId() & 0x07FF)) {
            // korrekter End-Tag gefunden
            pNode->setData(vcNodeData);
            return 0; 
          }
          else {
            m_output << "ERROR: CConfigReader::loadXMLStream(), unexpected end-tag '</" << pNameBuffer
                     << ">', line: " << uiLine << "\n";
            return 1;
          }
        }
        else {
          m_output << "ERROR: CConfigReader::loadXMLStream(), unexpected char, line: " << uiLine << "\n";
          return 1;
        }
        break;
      
      // ...
      // ganz viel mehr Zustände
      // ...
    }

    // Zeilen zählen
    if (c == '\n') {
      ++uiLine;
    }
  }

  // ...
}

My software never has bugs. It just develops random features.

Offline

 

#6 22.10.2007 21:19:12

simon
ProMember
Ort: Düsseldorf
Registriert: 03.06.2006
Beiträge: 168

Re: strings interpretieren

phu ok big_smile das muss ich mir erst mal ansehen - und dann kommen eventuell noch Fragen yikes


grrr

Offline

 

Brett Fußzeile

Powered by PunBB
© Copyright 2002–2005 Rickard Andersson