kubawal Temat założony przez niniejszego użytkownika |
[boost::regex] Bałagan z backslash'ami » 2013-12-23 16:49:57 Witam! Piszę sobie parser na potrzeby mojej własnej gry i regex'y jak zwykle odmawiają pomocy :/ Dane wejściowe do parsera są w formacie: TYP nazwa: dane
I to mi działa. Dodałem także obsługę tablic w formacie: TABLE(TYP) nazwa: { 0: dane0 1: dane1 2: dane2 }
I to mi nie działa. Korzystam z kodu: string node;
regex reg( "(\\w+) ([\\w\\d]+): (.+)" ); regex regTbl( "^TABLE\\((\\w+)\\) ([\\w\\d]+):$" "^(\\{$" "^((\\d+): (.+)$)+" "^\\})$" );
if( !regex_match( node, m, reg ) ) { if( !regex_match( node, m, regTbl ) ) error( "Parser: Nie można dopasować węzła z wartości:\n" + node ); else { }
I przy danych np. TABLE(INT) t1: { 0: 8 1: 9 2: 10 }
Wyświetla mi się: Parser: Nie można dopasować węzła z wartości: TABLE(INT) t1: { 0: 8 1: 9 2: 10 }
Kiedy wyświetlam wzorzec na węzeł tablicowy, to wyświetla się mniej więcej takie coś: ^TABLE\((\w+)\) ([\w\d]+):$^(\{$^((\d+): (.+)$)+^\})$ Podejrzewam, że to jakiś problem z zastosowaniem backslashów. PS: Używam boost::regex |
|
kubawal Temat założony przez niniejszego użytkownika |
» 2013-12-23 16:55:41 |
|
Monika90 |
» 2013-12-24 08:06:14 Na backslashe mogą pomóc Raw String Literals, ale to nie backslashe są tu problemem. Chodzi o to, że $ dopasowuje się w stringu przed znakiem \n, a ^ po, co znaczy, że pomiędzy końcem linii, a początkiem następnej jest jeszcze new-line. Więc zamiast ^$ powinieneś użyć ^\n$, albo po prostu \n, a najlepiej dopuścić w tych miejscach dowolny (także pusty) ciąg białych znaków, czyli \\s*. Drugi problem jest taki, że jak masz grupę, która może się powtarzać np.: (jakiś-wzorzec)+, to po dopasowaniu będziesz miał dostęp tylko do ostatniego podciągu, który pasował do wzorca w nawiasach. Np. dla takiego tekstu: TABLE(INT) t1: { 0: 8 1: 9 2: 10 } i wzorca TABLE\\((\\w+)\\) ([\\w\\d]+):\n(\\{\n((\\d+): (.+)\n)+^\\})m[4] będzie zawierało "2: 10\n", m[5] "2", a m[6] "10", ale "0: 8\n" i "1: 9\n" nigdzie się nie zapiszą. Z tym że biblioteka boost pozwala to zmienić za cenę spadku wydajności - trzeba ją rekompilować z opcją BOOST_REGEX_MATCH_EXTRA, co jest opisane tu http://www.boost.org/doc/libs/1_55_0/libs/regex/doc/html/boost_regex/captures.html#boost_regex.captures.repeated_captures. Porada dnia: Nie warto kombinować z wyrażeniami regularnymi, prościej jest napisać parser w C++. |
|
|
kubawal Temat założony przez niniejszego użytkownika |
» 2013-12-24 13:19:26 to po dopasowaniu będziesz miał dostęp tylko do ostatniego podciągu |
Ja sobie tylko sprawdzam, czy on pasuje do tablicy, a później wyciągam wartości z poszczególnych wierszy za pomocą regex'a (\\d+): (.+)\n)Porada dnia:
Nie warto kombinować z wyrażeniami regularnymi, prościej jest napisać parser w C++. |
|
No właśnie w tym problem, że piszę uniwersalny parser i regex'y są chyba najlepszym rozwiązaniem. Poza tym regex'y boost'a będą na pewno szybsze, niż jakiekolwiek moje rozwiązanie. |
|
Elaine |
» 2013-12-24 13:40:50 No właśnie w tym problem, że piszę uniwersalny parser i regex'y są chyba najlepszym rozwiązaniem. |
Regeksy prawie nigdy nie są najlepszym rozwiązaniem. Nadają się tylko do gramatyk regularnych, dla bardziej skomplikowanych są po prostu zbyt mało ekspresywne. Poza tym są strasznie nieczytelne do wszystkiego poza najprostszymi rzeczami – chyba, że piszesz w Lispie i możesz sobie zrobić makro (a tak naprawdę użyć istniejącego), które przerobi bardziej czytelną formę przypominającą trochę parser combinator na ciąg znaków z tymi wszystkimi krzaczkami. Ale ty nie piszesz w Lispie. Poza tym regex'y boost'a będą na pewno szybsze, niż jakiekolwiek moje rozwiązanie. |
Regeksy są wolne w porównaniu do rozsądnie napisanego ręcznego parsera. Rozsądnie napisać parser jest łatwo. |
|
« 1 » |