Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

DeKugelschieber

Community-Fossil

  • »DeKugelschieber« ist der Autor dieses Themas

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

31

09.06.2014, 18:12

Jap value ist ein member und wird an anderer Stelle initialisiert.

Habs gerade mal getestet und gibt mir auch 0:

C-/C++-Quelltext

1
value = ((value & 0x000000FF) << 24 | (value & 0x0000FF00) << 8 | (value & 0x00FF0000) >> 8 | (value & 0xFF000000) >> 24);


Ein anderer Test:

C-/C++-Quelltext

1
2
3
4
5
6
int i = 2;
std::cout<<i<<std::endl;
i = (i&0x00000001)<<8;
std::cout<<i<<std::endl;
i = (i&0x00000100)>>8;
std::cout<<i<<std::endl;


Gibt mit 2 (oder 0x00000002) aus: 2 0 0
Mit 1 (0x00000001): 1 0 1 :D

Ich versteh das nicht...

Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von »DeKugelschieber« (09.06.2014, 18:27)


32

09.06.2014, 18:52

Sicher, dass nicht einfach value 0 ist? Lass ihn dir doch mal direkt vor dem Byte-Swap ausgeben.

33

09.06.2014, 19:06

Im Übrigen, der Grund dafür, dass dein Test nicht funktioniert ist folgender: Du maskierst das erste Bit, setzt aber mittels int i = 2 das zweite Bit. Ändere entweder deine Maske auf (i&0x00000002) oder i auf 1 ;)

DeKugelschieber

Community-Fossil

  • »DeKugelschieber« ist der Autor dieses Themas

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

34

09.06.2014, 19:54

Wups du hast recht, da sollte f stehen. Wohl zu warum heute :P

Und ja ich bin sicher das ein Wert in value steht.

DeKugelschieber

Community-Fossil

  • »DeKugelschieber« ist der Autor dieses Themas

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

35

09.06.2014, 20:21

Ah moment das funktioniert doch, ich hab nur falsch geguckt -.-

Das Problem ist aber, dass ich keine "großen" Zahlen speichern kann!?

Quellcode

1
_a = 9999


Ist nach dem Einlesen 15...

Also lese ich falsch ein oder speichere ich falsch?
Weil das funktioniert:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
char c[] = {0x05, 0x00, 0x00, 0x00};
int i = static_cast<int>(c[0]);
    
std::cout<<i<<std::endl; // = 5

char ca = i&0x000000ff;
    
std::cout<<int(ca)<<std::endl; // = 5

DeKugelschieber

Community-Fossil

  • »DeKugelschieber« ist der Autor dieses Themas

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

36

09.06.2014, 20:39

Ja Problem gelöst. Vertraue niemals dem Internet.
Ich hatte static_cast genommen da ich es einfach haben wollte. Das kann nur keine 4 Byte in einen integer casten ;) Jetzt gehts:

C-/C++-Quelltext

1
2
tmp = code[instruction+3]<<24|code[instruction+2]<<18|code[instruction+1]<<8|code[instruction];
stack.push(tmp);

Evrey

Treue Seele

Beiträge: 245

Beruf: Weltherrscher

  • Private Nachricht senden

37

09.06.2014, 22:07

Y U Endian?
Nutz kein uint8_t, sondern z.B. int32_t. Und weiche Endianess-Problemen z.B. so aus:

C-/C++-Quelltext

1
2
op = static_cast<uint8_t>(instr & 0xFF);
num = static_cast<int32_t>(instr >> 24);

Den Shifts ist es wumpe, wo das MSB und LSB im RAM liegt. Brauchst dann nur beim Serialisieren ein Kontroll-Wort, mit dem du die Datei liest. Z.B.:

C-/C++-Quelltext

1
2
3
4
5
if(control_ == 'ASDF') {
  load_native();
} else if(control_ == 'FDSA') {
  load_byteswap();
} else {assert(false);}

C-/C++-Quelltext

1
2
3
4
int main(int _argc, char** _argv) noexcept {
  asm volatile("lock cmpxchg8b %eax");
  return 0;
} // ::main
(Dieses kleine Biest vermochte einst x86-Prozessoren lahm zu legen.)

=> Und er blogt unter Hackish.Codes D:

DeKugelschieber

Community-Fossil

  • »DeKugelschieber« ist der Autor dieses Themas

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

38

16.06.2014, 10:50

Hmm ich hab noch nicht so ganz verstanden wie der recursive decent parser jetzt Ausdrücke parsen soll die später kommen.

Beispiel:

Quellcode

1
_x = 1-2+3


Ergibt bei mir momentan -4, da der Vorgang momentan so aussieht:

1. _x wird als Variable erkannt und angelegt.
2. = wird als Zuweisung erkannt, das _x wird rechts an den Tree angehangen.
3. 1 wird als Wert erkannt.
4. - wird als Subtraktion erkannt, links wird die 1 angehangen, der halbe Term links an die Zuweisung.
5. 2 wird an die Subtraktion rechts angehangen.
6. + wird erkannt und hinter die Subtraktion gehangen.
7. 3 wird an die Addition gehangen.

So durchläuft der Parser ohne vorher zu wissen was kommt. Um das zu erreichen gibt es pro Ausdruck eine Methode, hier werden (in der Reihenfolge) genutzt: parseVariable(), parseAssign(), parseValue(), parseAdd(), parseValue(), ...
Dass ich so den Ausdruck nicht korrekt einlesen kann ist mir klar, jedoch finde ich auch nur Beispiele die keinen Syntax Tree erstellen, sondern direkt eine Ausgabe erzeugen.

Hier der generierte Syntax Tree in Pseudo-Assembler:

Quellcode

1
2
3
4
5
6
7
val     1
val     2
val     3
add     =        5
sub     =        -4
setID   0
assign


Ihr müsst euch dass als umgedrehten Tree vorstellen. Der würde dann so aussehen:


(Link)


+ und - sind auf Grund des Einlesens vertauscht.
Ich hab gerade keine so gute Vorstellung davon wie ich das jetzt rekursiv beheben kann...
Vor allem wann was wo angehangen werden soll ist schwierig zu handhaben.

Source

Dieses Beispiel habe ich mir mal angesehen, ich verstehe nicht warum das

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
int expression()
{
    int result = term();
    while (peek() == '+' || peek() == '-') // <-
        if (get() == '+')
            result += term();
        else
            result -= term();
    return result;
}


funktioniert, da ich zwischendurch ja noch Werte und Variablen habe, die erkannt werden sollen.

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

39

16.06.2014, 11:12

Ob du direkt ausgibst oder den Baum explizit erzeugst ist von der Logik eigentlich egal. Was du eigentlich machen möchtest ist doch die Subtraktion als linken Parameter für die Addition benutzen. Was sinnvoll sein kann ist wenn du dir beide Möglichkeiten des Parsings als Syntaxbaum aufmalst. Eine Version vom Syntaxbaum hast du ja bereits in deinem Post gezeigt. Bin mir grad nicht sicher, aber du besitzt doch auch den C++ Programmierer oder nicht? Da ist ein Kapitel zum Thema Parser. Da wird auch direkt ausgegeben, aber auf dein Problem müsste da auch eingegangen werden.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

DeKugelschieber

Community-Fossil

  • »DeKugelschieber« ist der Autor dieses Themas

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

40

16.06.2014, 11:30

Wie meinst du das "als linken Parameter"?
Es müsste ja eigentlich so sein dass das + und - getauscht werden, da der Baum von unten nach oben aufgelöst wird, und 1-2+3 nicht das gleiche ist wie 2+3-1 (so wie es im moment ist, theoretisch natürlich schon, aber wenn man "mit Stack denkt" nicht -> push 1 push 2 push 3 add sub Versus push 1 push 2 push 3 sub add).

Jetzt gerade versuche ich sowas hier:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
void Snippet::parseAssign(){
// linker Bereich
    for(auto t : leftTokens){
        std::cout<<t<<std::endl;
    }

// unsere Zuweisung
    std::cout<<"assign"<<std::endl;

// verbleibender rechter Bereich
    do{
        std::cout<<getToken()<<std::endl;
    }while(nextToken());
}

bool Snippet::parse(){
    do{
        if(accept("=")){
            nextToken();
            parseAssign(); // Zuweisung gefunden
        }
        else{
            leftTokens.push_back(getToken()); // noch offen, linker Bereich
        }
    }while(nextToken());

    // clean up
    tokens.clear();

    return true;
}


Bei

Quellcode

1
_x = 1


Bekomme ich dann:

Quellcode

1
2
3
4
_
x
assign
1


Was ja schon mal gut ist. Dann würde ich jetzt den linken Bereich (_x) auswerten und dann den rechten (1). Wobei man hier schon die Grammatik beachten könnte, also links muss eine Variable stehen und rechts irgend ein Ausdruck.
Der Syntax Tree muss dann so aussehen dass die Variable rechts, und der Wert links angehangen wird. Damit die VM dann erst die 1 auf den Stack liest bevor sie die _x ID setzt und zuweist.

Ist meine Logik soweit richtig?

Werbeanzeige