Prawdopodobnie najważniejszą rzeczą, która go rzuca, jest \sdopasowanie do przestrzeni poziomej i pionowej. Aby dopasować tylko poziomą przestrzeń, wykorzystanie \hi 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/ headerktó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. makeKomenda 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 .mademetody. Ponieważ istnieje wiele wierszy wartości, aby uzyskać każdą z ich madewartoś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 forpętli. Po flat @x Z @yprostu 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 maketo, a następnie będzie dostępny w madeparsowaniu:
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? . MaszNilswó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?” .