Autor Téma: Návrh typu pro regex - problém s vnořením do sebe sama  (Přečteno 1480 krát)

Offline vangog

  • Hrdina
  • ****
  • Příspěvků: 370
  • Karma: 0
    • Verze Delphi: 7
Připomínám, že píšu v Delphi 7.

Pracuji teď na třídě, která má vytvářet regulární výrazy a později snad s nimi pracovat. Něco mám už napsané, ale teď jsem se dostal do kritického bodu, kdy se musím rozhodnout jestli budu pracovat jen s jednou úrovní předloh nebo s vícero. S jednou úrovní je to jednoduché.

Nejdříve terminologie, kterou jsem si pro třídu vytvořil.

Sekcí nazývám úsek regulárního výrazu:
a) celý výraz bez alternativ a vnořených předloh:
např. 'abc\w{1,3}'
b) sekce alternativ, příklad dvou úseků. 'ano|ne'
c) sekce s vnořenýma předlohama, příklad: '(ano|ne)/(ne|ano)'

Třídou znaku nazývám jakýkoliv zástupný znak, představující více znaků, např. \w, \s, \d
Pod to spadá, "klasická třída znaku": []

Jednotky obsahují buďto samostatné písmeno nebo zástupný znak reprezentovaný třídou. (Tohle asi budu měnit, že by písmeno mohlo být zařazeno přímo pod sekcí).

Tak a teď ke kořenu problému. Návrh typu TRegex_sec pro jednu úroveň předloh:

Kód: Delphi [Vybrat]
  1. type TRegex_sec = record
  2.   hasUnits: boolean;
  3.   units: Array of TRegex_unit;
  4.   len: word; // délka units
  5. end;
  6.  

V případě, že bych chtěl udělat víceúrovňové předlohy bych potřeboval něco podobného, což nelze nadefinovat:

Kód: Delphi [Vybrat]
  1. type TRegex_sec = record
  2.   secs: Array of TRegex_secs;
  3.   secLen: byte;  // length of the units
  4.   hasSections: boolean;
  5.   hasUnits: boolean;
  6.   units: Array of TRegex_unit;
  7.   unitsLen: byte;  // length of the units
  8. end;
  9.  

Při parsování by to vypadalo tato:
předloha: 'a(b)|b(c)'
sec('a(b)')->sec('b');
sec('a(b)')->sec('b');
sec('b(c)')->sec('c');

nebo složitěji:

předloha: 'a(b|bc)|b(c|ab)'
sec('a(b|bc)')->sec('b|bc')->sec('b');
sec('a(b|bc)')->sec('b|bc')->sec('c');
sec('b(c|ab)')->sec('c|ab')->sec('c');
sec('b(c|ab)')->sec('c|ab')->sec('ab');

takto by se dalo postupovat víc a víc do hloubky, ale jak vidíte při definici je problém v tom jak v definici typu použít něco co ještě nebylo nadefinováno... Totiž jakýsi odkaz na sebe sama.

type TRegex_sec = record
  secs: Array of TRegex_secs;
end;
« Poslední změna: 11-06-2019, 08:34:15 od vangog »

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 4397
  • Karma: 39
    • Verze Delphi: XE7 professional
Re:Návrh typu pro regex - problém s vnořením do sebe sama
« Odpověď #1 kdy: 11-06-2019, 09:20:11 »
Asi píšem zle, ale aj tak. Aj hlúposť môže nakopnúť správnym smerom.
Pri objektoch sa bežne používa "dopredná" deklarácia. Netuším či to je použiteľné na record. Tie vôbec neovládam.
Delphi XE7, FireBird
Expert na kladenie nejasne formulovaných otázok.

Offline vangog

  • Hrdina
  • ****
  • Příspěvků: 370
  • Karma: 0
    • Verze Delphi: 7
Re:Návrh typu pro regex - problém s vnořením do sebe sama
« Odpověď #2 kdy: 11-06-2019, 09:31:11 »
Forward mě taky napadnul, ale to znám jen na procedury:

Google mi napověděl toto:

Citace
In a unit's implementation section or in the body of a program or library, you can declare a function or procedure before you call it by declaring the header (name, parameters, and return type) with the forward directive. Delphi compiles a file by reading from its beginning to the end.

Dočetl jsem se ještě toto:
https://stackoverflow.com/questions/32848994/forward-declarations-for-record-types-or-arrays

že by to možná šlo udělat přes pointer, ale nevím jak, v pointerech jsem amatér a obávám se aby z toho ve výsledku nebyl guláš.
« Poslední změna: 11-06-2019, 09:33:49 od vangog »

Offline vangog

  • Hrdina
  • ****
  • Příspěvků: 370
  • Karma: 0
    • Verze Delphi: 7
Re:Návrh typu pro regex - problém s vnořením do sebe sama
« Odpověď #3 kdy: 11-06-2019, 11:08:43 »
Nevím jak to udělat, u pointerů je problém, že musíš deklarovat typ na který to odkazuje. Takže zase typ, který ještě nebyl deklarovaný.

Offline vandrovnik

  • Guru
  • *****
  • Příspěvků: 754
  • Karma: 42
    • Verze Delphi: 10.3
Re:Návrh typu pro regex - problém s vnořením do sebe sama
« Odpověď #4 kdy: 11-06-2019, 12:44:57 »
Excellent
Rated 1 time
Nevím jak to udělat, u pointerů je problém, že musíš deklarovat typ na který to odkazuje. Takže zase typ, který ještě nebyl deklarovaný.

Pointery mají výjimku :-) Tohle projde:

Kód: Delphi [Vybrat]
  1. type
  2.      pPokus=^tPokus;
  3.  
  4.      tPokus=record
  5.       a, b: integer;
  6.      end;
  7.  

Ale to píšu jen k těm pointerům, nedíval jsem se, jak moc se pointery hodí pro Tvůj případ.

Offline vangog

  • Hrdina
  • ****
  • Příspěvků: 370
  • Karma: 0
    • Verze Delphi: 7
Re:Návrh typu pro regex - problém s vnořením do sebe sama
« Odpověď #5 kdy: 11-06-2019, 12:52:06 »
Díky moc!

Kód: Delphi [Vybrat]
  1. type
  2.   pTRegex_sec=^TRegex_sec;
  3.   TRegex_sec = record
  4.   secs: Array of pTRegex_sec;
  5.   len: byte;  // length of the sections
  6.   hasSections: boolean;
  7.   hasUnits: boolean;
  8.   units: Array of TRegex_unit;
  9. end;
  10.  

Je to fakt síla, tenhle kód, to by mě v životě nenapadlo, že se to dá napsat pod jeden typ. Já to píšu vždy odděleně.

A jak vlastně k tomu přistupovat? Kam mám dát tu stříšku ^?

Mohu k tomu přistupovat přímo, když nastavuju to pole?
Kód: Delphi [Vybrat]
  1. procedure TTrackerRegex.incSection;
  2. begin
  3.   setlength(Assertions.secs, Assertions.len+1);
  4.   Inc(Assertions.len);
  5. end;
  6.  

Kód: Delphi [Vybrat]
  1. with Assertions.secs[info.sec].units[info._unit].charClasses[info.charClass] do ...
  2.  

Radši se ptám, aby mi to nekde nepřetékalo.
« Poslední změna: 11-06-2019, 13:06:20 od vangog »

Offline vangog

  • Hrdina
  • ****
  • Příspěvků: 370
  • Karma: 0
    • Verze Delphi: 7
Re:Návrh typu pro regex - problém s vnořením do sebe sama
« Odpověď #6 kdy: 11-06-2019, 17:11:49 »
Mohl by mi někdo ukázat jak přidělit paměť, když chci navýšit sekci z 0 na délku 1?

Zkoušel jsem použít GetMem, ale dostávám chybu "Incompatible types": Assertions.secs[info.sec]

Kód: Delphi [Vybrat]
  1. procedure TTrackerRegex.incSection;
  2. begin
  3.   info.sec := Assertions.len;
  4.   setlength(Assertions.secs, Assertions.len+1);
  5.   GetMem(Assertions.secs[info.sec], SizeOf(TRegex_sec));
  6.   Inc(Assertions.len);
  7. end;
  8.  
« Poslední změna: 11-06-2019, 17:13:23 od vangog »

Offline vandrovnik

  • Guru
  • *****
  • Příspěvků: 754
  • Karma: 42
    • Verze Delphi: 10.3
Re:Návrh typu pro regex - problém s vnořením do sebe sama
« Odpověď #7 kdy: 11-06-2019, 18:31:46 »
Kód: Delphi [Vybrat]
  1. New(Assertions.secs[info.sec]);

Offline vangog

  • Hrdina
  • ****
  • Příspěvků: 370
  • Karma: 0
    • Verze Delphi: 7
Re:Návrh typu pro regex - problém s vnořením do sebe sama
« Odpověď #8 kdy: 11-06-2019, 18:46:50 »
Následoval jsem návod zde:
https://hub.packtpub.com/delphi-memory-management-techniques-for-parallel-programming/

jim to funguje. Mě ne.

Tvůj návod mi ale dělá úplně stejnou chybu.

Offline vandrovnik

  • Guru
  • *****
  • Příspěvků: 754
  • Karma: 42
    • Verze Delphi: 10.3
Re:Návrh typu pro regex - problém s vnořením do sebe sama
« Odpověď #9 kdy: 11-06-2019, 18:59:03 »
Třeba je problém ještě jinde. Tohle by mělo normálně fungovat:

Kód: Delphi [Vybrat]
  1. type tZaznam=record
  2.       a, b: integer;
  3.      end;
  4.  
  5.      pZaznam=^tZaznam;
  6.  
  7. var Prom: pZaznam;
  8.  
  9. new(Prom);
  10. Prom^.a:=1;
  11. Prom^.b:=2;
  12.  

Offline vangog

  • Hrdina
  • ****
  • Příspěvků: 370
  • Karma: 0
    • Verze Delphi: 7
Re:Návrh typu pro regex - problém s vnořením do sebe sama
« Odpověď #10 kdy: 11-06-2019, 19:17:54 »
Ptal jsem se taky na stacku, a tam mi bylo vysvětleno, že tu alokaci prý udělal ten setlenght.

https://stackoverflow.com/questions/56548289/how-to-allocate-memory-to-pointer-to-a-record-delphi-7

A tvůj příklad funguje.

Nicméně dneska jsem už příliš unavený, takže dnes už nic nevyzkouším.
« Poslední změna: 11-06-2019, 19:19:43 od vangog »

Offline vandrovnik

  • Guru
  • *****
  • Příspěvků: 754
  • Karma: 42
    • Verze Delphi: 10.3
Re:Návrh typu pro regex - problém s vnořením do sebe sama
« Odpověď #11 kdy: 11-06-2019, 19:50:31 »
Řekl bych, že setlength jen alokuje prostor pro ten ukazatel, ale ne tu odkazovanou proměnnou jako takovou.
Ostatně můžeš se podívat, jako hodnotu obsahuje Assertions.secs[info.sec] poté, co uděláš setlength(Assertions.secs, Assertions.len+1) - tipuju, že nil, tzn. proměnná není alokovaná, dokud nepoužiješ New.

Ono je teda otázkou, jestli vlastně chceš mít pole ukazatelů (tak to máš teď - Array of pTRegex_sec), nebo rovnou pole hodnot (Array of TRegex_sec - pak bys New nepoužíval).

Offline vangog

  • Hrdina
  • ****
  • Příspěvků: 370
  • Karma: 0
    • Verze Delphi: 7
Re:Návrh typu pro regex - problém s vnořením do sebe sama
« Odpověď #12 kdy: 11-06-2019, 21:26:52 »
No tak jasně že pole hodnot by bylo lepší, než pole ukazatelů. Dal jsem to jako pole ukazatelů abych to mohl nadeklarovat.
« Poslední změna: 11-06-2019, 21:33:36 od vangog »

Offline vandrovnik

  • Guru
  • *****
  • Příspěvků: 754
  • Karma: 42
    • Verze Delphi: 10.3
Re:Návrh typu pro regex - problém s vnořením do sebe sama
« Odpověď #13 kdy: 11-06-2019, 21:29:46 »
Tohle ale normálně projde:

Kód: Delphi [Vybrat]
  1.      tPokus=record
  2.       Test: array of tPokus;
  3.      end;
  4.  

Offline vangog

  • Hrdina
  • ****
  • Příspěvků: 370
  • Karma: 0
    • Verze Delphi: 7
Re:Návrh typu pro regex - problém s vnořením do sebe sama
« Odpověď #14 kdy: 11-06-2019, 21:33:56 »
Tak jsem to vyzkoušel:
setlength(Assertions.secs, Assertions.len+1);
Kód: Delphi [Vybrat]
  1. setlength(Assertions.secs, Assertions.len+1);
  2. // sec:
  3. // (((), 0, False, False, ()))
  4.  

Tohle nevypadá jak ukazatel.

Dnes už nedokážu uvažovat.