|
-
Ich wollte das Programm auch mal ausprobieren. Ich erhalte folgende Fehlermeldung:
[
Custom(
Declaration
),
Custom(
MissingSemi
),
Char
]
Parsed 890 files
Error in file "D:\\Program Files (x86)\\JoWood\\Gothic II Gold\\_work\\data\\Scripts\\Content\\AI\\MAGIC\\Spells\\Spell_MagParade.d" in line 67: Missing semicolon
parsing took 0.897 seconds
Stimmt aber nicht §hmm
Hier das File:
Code:
/*
* Spell_MagParade.d
* Erstelle irgendwo nach C_BodyStateContains, z.B. hier:
* Pfad: _work\data\Scripts\AI\Magic\Spells\Spell_MagParade.d
*
* Falls es schon eine "Mainloop" gibt, kann man den Inhalt von
* Spell_MagParade(), anstatt separat, besser dort einfügen, dann hat man
* nicht zu viele FrameFunctions nebeneinander laufen.
*
*/
// ***************************
// Spell_MagParade (mud-freak)
// ***************************
var int PLAYER_TALENT_MagParade; // Einbauen in Items oder als Talent.
var int MagParade_Overlay;
const int MagParade_Cost = 5; // Mana fürs Blocken
/* Loop-Funktion, um das Parrieren für Zauber abzufragen.
*
* Die Funktion läuft ohne Probleme und sehr zuverlässig. Die Abarbeitung der
* einzelnen Fälle habe ich nicht mehr überarbeitet (stammt aus 2010).
* Vielleicht könnte man hier noch optimieren - funktionieren tuts aber gut.
* Ausnahmefälle ungetestet: Was passiert wenn man während dem Parrieren
* speichert und läd?
* Verbessern könnte man ausserdem, dass das eigentliche Blocken nicht einfach
* über das Ausschalten der Kollision geklärt ist, weil der Schild
* schliesslich nur vor dem Hero ist und er von den anderen Seiten noch an-
* greifbar sein sollte. Ein Tipp dazu: C_CanNpcCollideWithSpell.d
*/
func void Spell_MagParade() {
// Nur mit gezogendem Zauber möglich (wie beim Schwertkampf ja auch).
if (!Npc_IsInFightMode(hero, FMODE_MAGIC))
|| (!PLAYER_TALENT_MagParade) {
return;
};
var oCNpc her; her = Hlp_GetNpc(hero);
// Kollision wieder anschalten
if (C_BodyStateContains(hero, BS_PARADE))
&& !(her.bitfield[4] & oCNpc_bitfield4_m_bAniMessageRunning)
&& !(her._zCVob_bitfield[0] & zCVob_bitfield0_collDetectionDynamic) {
her._zCVob_bitfield[0] = (her._zCVob_bitfield[0]
| zCVob_bitfield0_collDetectionDynamic);
}
else if (!C_BodyStateContains(hero, BS_PARADE))
&& !(her._zCVob_bitfield[0] & zCVob_bitfield0_collDetectionDynamic) {
her._zCVob_bitfield[0] = (her._zCVob_bitfield[0]
| zCVob_bitfield0_collDetectionDynamic);
};
// Bewegung wieder freisetzen
if (MagParade_Overlay == 2)
&& (!C_BodyStateContains(hero, BS_PARADE)) {
Mdl_RemoveOverlayMDS(hero, "Humans_MagDisable.mds");
MagParade_Overlay = 0;
};
// Hole gedrückte Tasten
var int returnState_down1;
var int returnState_down2;
var int returnState_action1;
var int returnState_action2;
returnState_down1 = MEM_KeyState(MEM_GetKey("keyDown"));
returnState_down2 = MEM_KeyState(MEM_GetSecondaryKey("keyDown"));
returnState_action1 = MEM_KeyState(MEM_GetKey("keyAction"));
returnState_action2 = MEM_KeyState(MEM_GetSecondaryKey("keyAction"));
// KEY_HOLD wird nicht abgefragt: Das wird per Mds-Overlay geregelt.
// Ist blockieren gerade gewünscht/erlaubt
if (((returnState_action1 == KEY_PRESSED // Aktionstaste gedrückt
|| returnState_action1 == KEY_HOLD)
|| (returnState_action2 == KEY_PRESSED // Aktionstaste gedrückt
|| returnState_action2 == KEY_HOLD))
&& (returnState_down1 == KEY_PRESSED // Down-Taste neu gedrückt
|| returnState_down2 == KEY_PRESSED))
&& (!C_BodyStateContains(hero, BS_PARADE))
&& (!C_BodyStateContains(hero, BS_FALL))
&& (!C_BodyStateContains(hero, BS_SWIM))
&& (!C_BodyStateContains(hero, BS_DIVE))
&& (!C_BodyStateContains(hero, BS_JUMP))
&& (!C_BodyStateContains(hero, BS_SIT))
&& (!C_BodyStateContains(hero, BS_LIE))
&& (!C_BodyStateContains(hero, BS_STUMBLE))
&& (!C_BodyStateContains(hero, BS_UNCONSCIOUS))
&& (!C_BodyStateContains(hero, BS_DEAD))
&& (!C_BodyStateContains(hero, BS_CRAWL))
&& (!C_BodyStateContains(hero, BS_CLIMB)) {
// Ist genug Mana fürs Blocken da
if (hero.attribute[ATR_MANA] >= MagParade_Cost) {
// Erfolgreich blocken
hero.attribute[ATR_MANA] = (hero.attribute[ATR_MANA]
- MagParade_Cost);
// Schränke während dem Block die Bewegung ein
Mdl_ApplyOverlayMds(hero, "Humans_MagDisable.mds");
MagParade_Overlay = 1;
// Parade Animation
AI_PlayAniBS(hero, "S_MAGPARADE", BS_PARADE);
// Kollision ausschalten
her._zCVob_bitfield[0] = (her._zCVob_bitfield[0]
& ~ zCVob_bitfield0_collDetectionDynamic);
} else {
// Nicht genug Mana
AI_PlayAniBS (hero, "T_CASTFAIL", BS_STAND);
};
} else if (MagParade_Overlay) // Overlay an UND...
&& ((returnState_down1 == KEY_HOLD // ...ENTWEDER:
|| returnState_down2 == KEY_HOLD) // Down-Taste gedrückt
&& (returnState_action1 == KEY_RELEASED // Aktionstaste nicht
|| returnState_action2 == KEY_RELEASED))
|| ((returnState_action1 == KEY_HOLD // ...ODER:
|| returnState_action2 == KEY_HOLD) // Aktionstaste gedrückt
&& (returnState_down1 == KEY_RELEASED // Down-Taste nicht
|| returnState_down2 == KEY_RELEASED))
|| ((returnState_action1 == KEY_RELEASED // ...ODER:
|| returnState_down2 == KEY_RELEASED) // Down-Taste nicht
&& (returnState_down1 == KEY_RELEASED // Aktionstaste auch nicht
|| returnState_down2 == KEY_RELEASED)) {
// Overlay wird abgeschaltet siehe oben.
// Noch nicht hier abschalten, weil die Animation evtl. noch läuft.
MagParade_Overlay = 2;
};
};
Zeile 67 ist fett gedruckt.
Geändert von Fisk2033 (30.08.2018 um 21:03 Uhr)
-
Liegt wahrscheinlich am selben "Problem" wie bei mir
Ne, lag am Namen der Variable: Parsiphae hat (fälschlicherweise) versucht, das als Return-Statement zu parsen. Ist schon behoben, dafür gibt es jetzt 3 Keywords (var, if, return) die nicht als Bezeichner verwendet werden können.
Edit: Also die Variable "returnState" entsprechend anders benennen
Geändert von Dada (30.08.2018 um 21:18 Uhr)
-
Genau. Die verlinkte Binary ist nicht ganz aktuell. In 6 Wochen bin ich mit meiner Bachelorarbeit durch, dann habe ich wieder Zeit, die ich in dieses Projekt stecken kann.
Edit: Und markier die Zeile nächstes mal lieber rot, ich hab nach dreimal durchscrollen aufgegeben und den Code in einen Texteditor kopiert
-
Ich habe wieder ein bisschen Zeit für dieses Projekt gefunden und die (Parser-)Logik in eine Bibliothek ("Crate" in Rust-Lingo) extrahiert. Es gibt zwar noch keine Dokumentation und es fehlen noch ein paar Sachen, die das ganze ergonomischer machen, aber es ist ein Anfang
Außerdem gibt es jetzt bereits ein nutzbares Interface, um den AST ein wenig zu analysieren. Hier mal ein (sehr einfaches) Beispiel, um alle Klassendefinitionen zu sammeln:
Code:
extern crate parsiphae;
/* Hier noch ein paar use-Anweisungen wegen namespace-kram */
#[derive(Debug)]
pub struct ClassCollector {
class_defs: HashMap<PrintableByteVec, types::Class>,
}
impl ClassCollector {
pub fn new() -> Self {
ClassCollector {
class_defs: HashMap::new(),
}
}
}
impl VisitorMut for ClassCollector {
fn visit_class_decl(&mut self, decl: &types::Class) {
self.class_defs.insert(
PrintableByteVec(decl.name.as_bytes().to_vec()),
decl.clone(),
);
}
}
fn main() {
let mut collector = ClassCollector::new();
let asts: Vec<types::AST> = asts_from_src("foo/bar.src"); // Diese Funktion fehlt noch, mehr oder weniger
for ast in asts {
visit_ast(&ast, &mut collector);
}
}
Geändert von Lehona (28.10.2018 um 10:30 Uhr)
-
Frage: möchtest du nicht lieber auch auf dem existierenden Deadalus ParseTree Compiler aufsetzen?
Damit kriegst du realtiv einfach sämtliche Instanzen und Funktionen zusammen.
Bin gespannt in welche Richtung du gehst, Ich glaube Ich habe was ähnliches angefangen
-
Zitat von Multithread
Frage: möchtest du nicht lieber auch auf dem existierenden Deadalus ParseTree Compiler aufsetzen?
Damit kriegst du realtiv einfach sämtliche Instanzen und Funktionen zusammen.
Bin gespannt in welche Richtung du gehst, Ich glaube Ich habe was ähnliches angefangen
Nö, ich mach das hier ja zum Spaß. Wo ist der Spaß, wenn man andere die Arbeit machen lässt?
Das geht irgendwann in Richtung Compiler Aber so (bzw. wenn ich die API noch ein bisschen aufbügel) sind meine Ergebnisse immerhin theoretisch schonmal nutzbar und ich könnte relativ schnell kleine Analyseprogramme schreiben (das kam in letzter Zeit immer mal wieder auf). Und irgendwann gibt es vielleicht Syntaxerweiterungen, aber damit bin ich erstmal vorsichtig.
-
G1 U:PAR: Error DoStack. (line 0)
Hello Lehona,
I am getting this error 'U:PAR: Error DoStack. (line 0)' when starting my mod via GothicStarter.exe (GothicStarter_mod.exe with ticked Repase scripts works okay) - and I found this thread:
https://forum.worldofplayers.de/foru...1#post11264208
in which you explain that strings should not contain any breaklines. I already searched within items\Written.d and soon I found 2 such cases in which I had strings with breaklines - I have fixed that, but still getting this error. Which means, I have probably somewhere else in scripts same situation. Problem is I have 1413 files at the moment - and don't know any fast enough method which would help me here.
And here I was hoping - in case you would have some time - would it be possible for you to add new feature to Parsiphae tool - which would recognize these strings with breaklines? Thank you!
-
Zitat von F a w k e s
Problem is I have 1413 files at the moment - and don't know any fast enough method which would help me here.
You can try searching with a regular expression:
https://forum.worldofplayers.de/foru...1#post25359187
-
-
Most if not all feature a "Search in files..." functionality, so you probably could have saved a lot of time there At least Notepad++ also has an extension filter, in case you only want to search through *.d-files. NicoDE's post contains a screenshot of where to find it in Notepad++ (and usually you can invoke the form via Ctrl+Shift+F).
-
Geändert von F a w k e s (09.01.2019 um 21:53 Uhr)
-
Zitat von F a w k e s
LOL I should have paid more attention to that screenshot - I just took regex expression and went for it
Still believe - this could be a nice feature in your tool though
Yes, that should be simple to include as one of (hopefully many!) other checks to ensure that the produced Gothic.dat is actually sane.
-
Ich hab Parsiphae mal ausprobiert und mir einen automatisierten Buildjob eingerichtet damit. An sich eine richtig feine Sache. Hab aber auch direkt einen Bug gefunden. Folgender Code wird von Parsiphae nicht als falsch erkannt:
Code:
FUNC VOID Foo() {
if (SomeVariable) {
}
};
Gothic bemängelt dann das fehlende Semikolon vom if.
-
Zitat von Bonne6
Ich hab Parsiphae mal ausprobiert und mir einen automatisierten Buildjob eingerichtet damit. An sich eine richtig feine Sache. Hab aber auch direkt einen Bug gefunden. Folgender Code wird von Parsiphae nicht als falsch erkannt:
Code:
FUNC VOID Foo() {
if (SomeVariable) {
}
};
Gothic bemängelt dann das fehlende Semikolon vom if.
Lehona hat mir das mal erklärt
Zitat von Lehona
...
So einfach kannst wie ich kannst du es dir leider nicht machen. Da mein Plan ist in Zukunft aus dem AST auch selber eine .dat zu erzeugen (und den Gothic Parser so zu umgehen), kann ich die Grammatik einfach anpassen, solange eine Übermenge von gültigem Daedalus bei mir ebenfalls gültig ist. In deinem Fall wird der User jetzt nicht mehr gewarnt, falls er ein Semikolon hinter einem If-Block vergessen hat, das vom Parser aber benötigt wird. Wenn du das Problem wirklich lösen möchtest (und nicht einfach überall ein Semikolon erwartest, was vollkommen nachvollziehbar wäre), wirst du erstmal herausfinden müssen, welchen Regeln der Parser überhaupt wirklich folgt.
....
-
Zitat von Bonne6
Ich hab Parsiphae mal ausprobiert und mir einen automatisierten Buildjob eingerichtet damit. An sich eine richtig feine Sache. Hab aber auch direkt einen Bug gefunden. Folgender Code wird von Parsiphae nicht als falsch erkannt:
Code:
FUNC VOID Foo() {
if (SomeVariable) {
}
};
Gothic bemängelt dann das fehlende Semikolon vom if.
Ah, sorry das ich die PN nicht beantwortet habe, war etwas mit meiner Gesundheit beschäftigt
Der Unterschied war mir - glaube ich - bewusst, denn dieses Semikolon wird nicht immer gebraucht, soll heißen, manchmal lässt Gothic das durch auch wenn es fehlt. Ich bin mir nicht ganz sicher, wann Gothic das akzeptiert (vielleicht bei einer Else-Klausel?), aber da die Grammatik auch ohne Semikolon eindeutig ist, habe ich das in Parsiphae erlaubt. Da Parsiphae mal ein alternativer Parser werden sollte, macht es Sinn, ein Superset von Daedalus zu erlauben, aber als CI-Tool ist das natürlich eher doof.
Ich werde demnächst beruflich wahrscheinlich etwas mehr mit Parsern zu tun haben, es gibt also die Chance, dass ich demnächst die Entwicklung wieder aufnehme. Dann vermutlich aber ohne Parser-Combinators (die sind v.a. für binäre Formate geeignet, habe ich das Gefühl) und stattdessen mit einem handgeschrieben recursive-descent Parser. Das wird vermutlich für bessere Fehlermeldungen sorgen und es wäre auch kein Problem, einen strict-mode einzubauen.
Edit: Ich sehe, Kirides hat die Antwort schon vorweg genommen.
-
Zitat von Lehona
....
Dann vermutlich aber ohne Parser-Combinators (die sind v.a. für binäre Formate geeignet, habe ich das Gefühl) und stattdessen mit einem handgeschrieben recursive-descent Parser. Das wird vermutlich für bessere Fehlermeldungen sorgen und es wäre auch kein Problem, einen strict-mode einzubauen.
...
Ich habe letztens irgendwo eine Präsentation von einem selbst geschriebenen Parser combinator framework gesehen. Damit waren schon echt wirklich top Fehlermeldungen möglich, ebenfalls mit recovery.
Der Code war in GO geschrieben und sah auch echt gut aus von der Struktur her.
Auf jeden Fall angenehmer anzusehen als Antlr Code mit seinen ganzen interfaces, listenern und dem getrennten Lexer und Parser.
-
Zitat von Lehona
Ah, sorry das ich die PN nicht beantwortet habe, war etwas mit meiner Gesundheit beschäftigt
Kein Ding, hab's ja gefunden
Zitat von Lehona
Der Unterschied war mir - glaube ich - bewusst, denn dieses Semikolon wird nicht immer gebraucht, soll heißen, manchmal lässt Gothic das durch auch wenn es fehlt. Ich bin mir nicht ganz sicher, wann Gothic das akzeptiert (vielleicht bei einer Else-Klausel?), aber da die Grammatik auch ohne Semikolon eindeutig ist, habe ich das in Parsiphae erlaubt. Da Parsiphae mal ein alternativer Parser werden sollte, macht es Sinn, ein Superset von Daedalus zu erlauben, aber als CI-Tool ist das natürlich eher doof.
Ja, nicht ganz praktisch, aber immer noch besser so als komplett ohne Checks. Ist mir nur aufgefallen, weil das eben durchgerutscht ist trotz Code Review (weil natürlich alle Sprachen, die ich sonst so nutze, kein Semikolon brauchen).
Zitat von Lehona
Ich werde demnächst beruflich wahrscheinlich etwas mehr mit Parsern zu tun haben, es gibt also die Chance, dass ich demnächst die Entwicklung wieder aufnehme. Dann vermutlich aber ohne Parser-Combinators (die sind v.a. für binäre Formate geeignet, habe ich das Gefühl) und stattdessen mit einem handgeschrieben recursive-descent Parser. Das wird vermutlich für bessere Fehlermeldungen sorgen und es wäre auch kein Problem, einen strict-mode einzubauen.
Das wäre natürlich ideal.
-
Zitat von Kirides
Auf jeden Fall angenehmer anzusehen als Antlr Code mit seinen ganzen interfaces, listenern und dem getrennten Lexer und Parser.
Ja, ANTLR ist ziemlich übel was geparsten Code angeht, auch von der Struktur nachher.
-
Nach langer langer Zeit habe ich dieses Projekt mal wieder hervorgekramt und nennenswerten Fortschritt gemacht! Typechecking ist zu ca. 80% implementiert und schöne Fehlermeldungen gibt es auch schon:
Auch abgesehen von der Code Generation, für die noch gar nichts gemacht wurde, ist allerdings noch viel zu tun. Binarys werde ich erstmal nicht bereitstellen, dafür ist es noch zu sehr WiP und zu viel ändert sich regelmäßig. Wer damit rumspielen will kann es sich von GitHub ziehen.
-
Es freut mich, dass es weitergeht. Die Fehlernachrichten sehen schick aus! Danke, dass du dich wieder ransetzt. Bin gespannt auf weitere Neuerungen!
Berechtigungen
- Neue Themen erstellen: Nein
- Themen beantworten: Nein
- Anhänge hochladen: Nein
- Beiträge bearbeiten: Nein
|
|