Prawdopodobnie najważniejszą rzeczą, która go rzuca, jest \s
dopasowanie do przestrzeni poziomej i pionowej. Aby dopasować tylko poziomą przestrzeń, wykorzystanie \h
i dopasować tylko pionową przestrzeń, \v
.
Jednym małym zaleceniem, które chciałbym zrobić, jest unikanie umieszczania nowego wiersza w tokenie. Możesz także użyć operatorów naprzemiennych %
lub %%
, ponieważ są one zaprojektowane do obsługi tego typu pracy:
grammar Parser {
token TOP {
<headerRow> \n
<valueRow>+ %% \n
}
token headerRow { <.ws>* %% <header> }
token valueRow { <.ws>* %% <value> }
token header { \S+ }
token value { \S+ }
token ws { \h* }
}
Wynik Parser.parse($dat)
tego jest następujący:
「ID Name Email
1 test test@email.com
321 stan stan@nowhere.net
」
headerRow => 「ID Name Email」
header => 「ID」
header => 「Name」
header => 「Email」
valueRow => 「 1 test test@email.com」
value => 「1」
value => 「test」
value => 「test@email.com」
valueRow => 「 321 stan stan@nowhere.net」
value => 「321」
value => 「stan」
value => 「stan@nowhere.net」
valueRow => 「」
co pokazuje nam, że gramatyka z powodzeniem przeanalizowała wszystko. Skupmy się jednak na drugiej części pytania, która ma być dostępna w zmiennej dla Ciebie. Aby to zrobić, musisz podać klasę działań, która jest bardzo prosta dla tego projektu. Po prostu tworzysz klasę, której metody pasują do metod twojej gramatyki (chociaż te bardzo proste, takie jak value
/ header
które nie wymagają specjalnego przetwarzania poza rygoryzacją, mogą zostać zignorowane). Istnieje kilka bardziej kreatywnych / kompaktowych sposobów radzenia sobie z przetwarzaniem, ale postaram się zastosować dość podstawowe podejście do ilustracji. Oto nasza klasa:
class ParserActions {
method headerRow ($/) { ... }
method valueRow ($/) { ... }
method TOP ($/) { ... }
}
Każda metoda ma sygnaturę, ($/)
która jest zmienną dopasowania wyrażenia regularnego. Więc teraz zapytajmy, jakie informacje chcemy od każdego tokena. W wierszu nagłówka chcemy każdej wartości nagłówka z rzędu. Więc:
method headerRow ($/) {
my @headers = $<header>.map: *.Str
make @headers;
}
Dowolny znak z kwantyfikatorem na nim będą traktowane jako Positional
, więc mogliśmy również dostęp do każdego indywidualnego meczu z nagłówka $<header>[0]
, $<header>[1]
itp Ale to są obiekty mecz, więc po prostu szybko stringify im. make
Komenda pozwala innym tokeny dostępu do tej szczególnej dane, które mamy utworzone.
Nasz wiersz wartości będzie wyglądał identycznie, ponieważ $<value>
dbamy o tokeny.
method valueRow ($/) {
my @values = $<value>.map: *.Str
make @values;
}
Kiedy przejdziemy do ostatniej metody, będziemy chcieli utworzyć tablicę z skrótami.
method TOP ($/) {
my @entries;
my @headers = $<headerRow>.made;
my @rows = $<valueRow>.map: *.made;
for @rows -> @values {
my %entry = flat @headers Z @values;
@entries.push: %entry;
}
make @entries;
}
Tutaj możesz zobaczyć, w jaki sposób uzyskujemy dostęp do rzeczy, w których przetwarzaliśmy headerRow()
i valueRow()
: Używasz .made
metody. Ponieważ istnieje wiele wierszy wartości, aby uzyskać każdą z ich made
wartości, musimy zrobić mapę (jest to sytuacja, w której mam tendencję do pisania gramatyki po prostu <header><data>
w gramatyce i definiowania danych jako wielu wierszy, ale jest to dość proste, nie jest tak źle).
Teraz, gdy mamy nagłówki i wiersze w dwóch tablicach, wystarczy po prostu zrobić z nich tablicę skrótów, co robimy w for
pętli. Po flat @x Z @y
prostu interpoluje elementy, a przypisanie skrótu robi to, co mamy na myśli, ale istnieją inne sposoby uzyskania tablicy w haszu, którą chcesz.
Gdy skończysz, po prostu make
to, a następnie będzie dostępny w made
parsowaniu:
say Parser.parse($dat, :actions(ParserActions)).made
-> [{Email => test@email.com, ID => 1, Name => test} {Email => stan@nowhere.net, ID => 321, Name => stan} {}]
Dość powszechne jest zawijanie ich w metodę, taką jak
sub parse-tsv($tsv) {
return Parser.parse($tsv, :actions(ParserActions)).made
}
W ten sposób możesz po prostu powiedzieć
my @entries = parse-tsv($dat);
say @entries[0]<Name>; # test
say @entries[1]<Email>; # stan@nowhere.net
Nil
. Jeśli chodzi o opinie, to jest dość jałowe, prawda? W celu debugowania pobierz przecinek, jeśli jeszcze tego nie zrobiłeś i / lub zobacz Jak poprawić raportowanie błędów w gramatyce? . MaszNil
swój wzorzec zakładający semantykę cofania. Zobacz moją odpowiedź na ten temat. Polecam unikać powrotu. Zobacz odpowiedź @ user0721090601 na ten temat. Po prostu praktyczność i szybkość, patrz odpowiedź JJ. Również Wstępna ogólna odpowiedź na „Chcę przeanalizować X z Raku. Czy ktoś może pomóc?” .