‟overcq”

Z bloga o OUX/C+

Parser plików tekstowych – “text-syntax.cx”

W module “base” jest dostępny parser plików tekstowych kodowanych w UTF-8.

Do przetworzenia takiego pliku tekstowego są potrzebne dwa pliki:

Wczytywanie opisu składni pliku tekstowego

Najpierw należy utworzyć obiekt pliku opisu składni w menedżerze plików, a następnie utworzyć obiekt składni w module parsera plików procedurą:

N
E_text_syntax_M( I file
, struct E_text_syntax_Z_body **syntax
);

przed wywołaniem której “syntax” należy zadeklarować jako:

struct E_text_syntax_Z_body *syntax;

i podać w wywołaniu procedury wskaźnik do tej zmiennej jak poniżej:

if( !~E_text_syntax_M( file, &syntax ))
    // ...

Parsowanie pliku tekstowego

Wtedy trzeba odczytać i przypisać zmiennym identyfikatory poszczególnych nazw ‘entities’ z pliku opisu składni procedurą:

N
E_text_syntax_R_entity_by_name( struct E_text_syntax_Z_body *syntax
, Pc name
);

które zostaną wykorzystane podczas jego parsowania.

Następnie utworzyć obiekt stanu parsowania, utworzyć obiekt parsowanego pliku tekstowego w menedżerze plików i uruchomić parsowanie pliku tekstowego procedurami:

N
E_text_syntax_Q_state_M( struct E_text_syntax_Z_body *syntax
, struct E_text_syntax_Z_state **state
, N *state_n
);
N
E_text_syntax_Q_state_I_parse( I file
, struct E_text_syntax_Z_body *syntax
, struct E_text_syntax_Z_state **state
, N *state_n
, N (*entities_func)( struct E_text_syntax_Z_body *, struct E_text_syntax_Z_state *, N )
);

A na zakończenie wyrzucić obiekt stanu parsowania procedurą:

void
E_text_syntax_Q_state_W( struct E_text_syntax_Z_state *state
, N state_n
);

Na przykład:

N entities_path = E_text_syntax_R_entity_by_name( syntax, "path" );
N entities_port = E_text_syntax_R_entity_by_name( syntax, "port" );
if( !~entities_path
|| !~entities_port
)
    // ...
struct E_text_syntax_Z_body *syntax;
struct E_text_syntax_Z_state *state;
N state_n;
if( !~E_text_syntax_Q_state_M( syntax, &state, &state_n ))
    // ...
if( !~E_text_syntax_Q_state_I_parse( parsed_file, syntax, &state, &state_n, &entities_func ))
    // ...
E_text_syntax_Q_state_W( state, state_n );

Do parsowania pliku tekstowego potrzeba zdefiniować procedurę parsowania wszystkich nazw ’entities’ z pliku opisu składni, podaną powyżej do procedury parsowania jako “entities_func”.

Procedura parsowania wszystkich nazw ‘entities’

Dla każdego ‘entity’ z pliku opisu składni dopasowanego w parsowanym od początku do końca pliku tekstowym zostanie wywołana podana procedura “entities_func”:

N
entities_func( struct E_text_syntax_Z_body *syntax
, struct E_text_syntax_Z_state *state
, N state_n
);

w której w każdym jej wywołaniu na wierzchołku stosu “state” (czyli w “state[ state_n - 1 ]”) będzie identyfikator i tekst bieżąco dopasowanego ‘entity’. W tej procedurze należy odczytać sobie tekst dopasowania dla rozpoznawanego ‘entity’ i ustawić odpowiedni stan parsowania. Jeśli procedura ta wraca z 0, to parsowanie jest kontynuowane, w przeciwnym przypadku – przerywane.

Polami struktury służącymi do odczytu tych danych są:

struct E_text_syntax_Z_state
{ // ...
  N entities_i; // identyfikator ‘entity’
  Pc s; // tekst dopasowania
  // ...
};

Format pliku opisu składni

Plik zawiera kilkuliniowe ‘entities’ dopasowywane do kolejno czytanych od początku do końca elementów pliku tekstowego.

Przykładowe pliki opisu składni są tutaj:

Pierwsze z ‘entities’ jest tym, które zawiera strukturę całego dokumentu.

‘Entities’ mają format:

nazwa entity:
/ nazwa entity odstępów pomiędzy poniższymi
    nazwa zawartego entity
    dopasowanie wbudowane

Przy czym kolejność linii i ich liczba jest dowolna, a nazwa ‘entity’ odstępów jest opcjonalne.

Nazwa ‘entity’ jest nazwą Unicode, z dozwolonymi odstępami wewnątrz. Ta nazwa użyta w innym ‘entity’ musi być takim samym ciągiem tekstowym.

Dopasowanie wbudowane to jest jedno z:

Tekst jest otaczany znakami podwójnego cudzysłowu, zanegowany tekst dodatkowo poprzedzany znakiem wykrzyknika, wyrażenie regularne otaczane znakami ukośnika, zanegowane wyrażenie regularne dodatkowo poprzedzane znakiem wykrzyknika, wyrażenie wbudowane jest poprzedzane znakiem “@”. Na przykład:

dopasowanie wbudowane:
    "tekst" | !"tekst" | /wyrażenie regularne/ | !/zanegowane wyrażenie regularne/ | @alpha | @digit | @text | @eof

Nazwa ‘entity’ zawartego w ‘entity’ może być zakończona znakiem “?”, wtedy ‘entity’ to jest opcjonalne, albo znakami “...”, wtedy ‘entity’ to może się powtarzać. Oba te ciągi końcowe muszą być poprzedzone pojedynczym odstępem.

W miejscu ‘entity’ zawartego w ‘entity’ może być kilka nazw ‘entities’ rozdzielonych przecinkami lub znakiem pionowej kreski “|”. W pierwszym przypadku mają znaczenie takie jakby były w kolejnych liniach, w drugim przypadku są wobec siebie alternatywnymi dopasowaniami.