import Foundation
let pattern = ##"(?=[#<>@[\\^{~])(?<=(?<!\\)|(?<!\\)(?:\\{2})+)(?:\[(?:(?:\/?(?:[\*'bcimpstu]|com|ex|lang|ref|trn1?|!trs|su[bp]|url))|(?:m\d|c\x20[a-z]{3,20}|lang\x20(?:id=\d{1,5}|name="[A-Za-z]{5,22}")|ref(?:\x20dict="[^\r\n"]+")|br))\]|[\\@~^]|{{2}[\s\S]*?}{2}|<{2}|>{2}|(?<=^|(?=^\S)[^\r\n]*)\{[^\r\n}]*\}|^#[^\r\n]+)"##
let regex = try! NSRegularExpression(pattern: pattern, options: .anchorsMatchLines)
let testString = ##"""
#NAME "Mostitsky DSL Help (Ru-Ru)"
#INDEX_LANGUAGE "Russian"
#CONTENTS_LANGUAGE "Russian"
{{ Техническая часть }}
{{ / Техническая часть }}
DSL \(команды\)
DSL{ команды}
_теги DSL
теги DSL
[m1][p]спр.[/p]
[m1] Все команды (теги) в языке <<DSL>> имеют вид \[a\], где «a» — определённая команда, или тег (один или несколько символов). Соответствующая ей команда выключения — \[/a\]. Теги должны быть в нижнем регистре, [p]напр.[/p]: \[ref\], но не \[REF\].
[*] [/*]
[m1][b]Список команд[/b]:
[*] [/*]
[m2][b][u]Выделительные[/u][/b]:
[m2] [c lightgray]•[/c] [c darkviolet][b]\[b\][/b][/c], [c darkviolet][b]\[/b\][/b][/c] — полужирный текст. Подробнее [p]см.[/p] <<\[b\]>>.
[m4]Пример [b]полужирного[/b] текста.
[m2] [c lightgray]•[/c] [c darkviolet][b]\[i\][/b][/c], [c darkviolet][b]\[/i\][/b][/c] — курсивный текст. Подробнее [p]см.[/p] <<\[i\]>>.
[m2] [c lightgray]•[/c] [c darkviolet][b]\[u\][/b][/c], [c darkviolet][b]\[/u\][/b][/c] — подчёркнутый текст.
[m4]\{\{ Пример комментария. \}\}
[m2] [c lightgray]•[/c] [c darkviolet][b]\\[/b][/c] — символ экранирования. Обратная косая черта может использоваться перед любым символом и обозначает, что этот символ в карточке используется как текст, а не как специальный символ; сам бэкслэш при этом не виден. Чтобы в карточке бэкслэш был виден, необходимо поставить два бэкслэша подряд (\\\\).
[*] [/*]
[m2][b][u]Команды препроцессора[/u][/b]:
[m2] [c lightgray]•[/c] [c darkviolet][b]\#INDEX_LANGUAGE[/b][/c] — указание языка для индексирования заголовков ([p]син.[/p] исходный язык, язык заголовков).
[m4]Пример использования: \#INDEX_LANGUAGE "English"
(зона) мультимедиа
\\ [c gray]\{\{ <= длинный пробел \}\}[/c]
\[m1\]\[*\]\[s\]picture_name.jpg\[/s\]\[/*\]
\[m1\]\[*\]\[p\]Рис.\[/p\] Название рисунка. \[i\]Изображение: Автор.\[/i\]\[/*\]
[m3] Среди форматов изображений может использоваться анимированное изображение GIF, анимация которого будет показываться в отдельном окне по щелчку на миниатюре.
\@
insided card
[m1][c gray]\{\{ Пример: \}\}[/c]
[m2] dictionary [c gray]\{\{ ← это заголовок карточки \}\}[/c]
[m4]1) словарь [c gray]\{\{ ← это перевод в основной (объемлющей) карточке \}\}[/c]
[m4]2) справочник [c gray]\{\{ ← это перевод в основной (объемлющей) карточке \}\}[/c]
[m4]\@ explanatory dictionary [c gray]\{\{ ← это заголовок подкарточки № 1 \}\}[/c]
[m4]толковый словарь [c gray]\{\{ ← это перевод в подкарточке № 1 \}\}[/c]
[m4]\@ standard dictionary [c gray]\{\{ ← это заголовок подкарточки № 2 \}\}[/c]
[m4]нормативный словарь [c gray]\{\{ ← это перевод в подкарточке № 2 \}\}[/c]
[m4]\@ dictionary making [c gray]\{\{ ← это заголовок подкарточки № 3 \}\}[/c]
[m4]составление словарей [c gray]\{\{ ← это перевод в подкарточке № 3 \}\}[/c]
[m4]\@ [c gray]\{\{ ← конец подкарточки(ек) \}\}[/c]
[m1][c gray]\{\{ Рабочий пример: \}\}[/c]
[m2] dictionary
[m3] 1) словарь
[m3] 2) справочник
[m4]@ explanatory dictionary
[m4]толковый словарь
[m4]@ standard dictionary
[m4]нормативный словарь
[m4]@ dictionary making
[m4]составление словарей
@
кавычки
использование кавычек (в заголовках)
[m1]Если заголовок стоит в кавычках, то их желательно взять в одиночные фигурные скобки, [p]напр.[/p]: \{"\}заголовок\{"\}.
{{ ≡23.04.2014 }}
К{[']}а{[/']}рточка с (заголовком) {[p]}{N}{[/p]}{[p]}X{[/p]}{[p]}(M){[/p]}({[sup]}®{[/sup]})
новый заголовок
sample (test) card
New Heading
NH
[m0][c olive][b][com]New Heading, [p]сокр.[/p] NH[/com][/b][/c] {{ Полная и сокращенная форма заголовка }}
[m0][t]\[əˈθʌˌʤʊ ˈæʧɔːʃɪŋ\][/t] [s]sound.wav[/s] {{ Транскрипция и аудиоклип произношения }}
[m0][c darkviolet]I[/c] {{ Первая римская цифра }}
[m0][p]комп.[/p] [p]прог.[/p] [p]сущ.[/p] {{ Зона помет }}
[m1][c indigo]перев[']о[/']д т[']е[/']рмина п[']е[/']рвый[/c] {{ Перевод }}
[m0][c darkviolet]II[/c] {{ Вторая римская цифра }}
[m0] [p]техн.[/p] [p]гл.[/p] {{ Зона помет }}
[m1][c maroon][b]1.[/b][/c] [c indigo]п[']е[/']рвый перев[']о[/']д т[']е[/']рмина[/c] {{ Перевод }}
[m1][c maroon][b]2.[/b][/c] [c indigo]втор[']о[/']й перев[']о[/']д т[']е[/']рмина[/c] {{ Перевод }}
[*] • • •[/*] {{ Разгрничитель }}
[m1][*][s]press_brake.gif[/s][/*]
[m1][*][p]Аним.[/p] Схема работы. [i][c silver]Изображение: wiki.[/c][/i][/*]
[*] [/*]
[m1] Продолженние любого действия в проявленнном мире происходит в непроявленном мире. Начало любого материального действия происходит в уме, а ещё ранее — в психической сфере (то есть, в непроявленном мире). Графической схемой растения [ref dict="Mostitsky Universal (Ru-Ru)"]малина[/ref] является дерево корнями вверх, кроной вниз.[/com] {{ Комментарий }}
[m2][*][ex]♦ Пример абстрактного предложения на тему словарной статьи. [c lightblue](Иван Петров)[/c][/ex][/*] {{ Пример }}
{{[!trs]}}[*] • • •[/*]{{[/!trs]}} {{ Разграничитель }}
[m0][*][com][p]син.[/p] <<Карточка с заголовком X>>, empty article, sample (test) card[/com][/*] {{ Зона синонимов и антонимов }}
[m0][*][com][p]букв.[/p] буквальный перевод; [p]этим.[/p] dummy («болванка») + entry («запись»); [p]появл.[/p] 1999[/com][/*] {{ Этимология }}
[m0][*]► [i][com]Wiki (Eng):[/com][/i] [url]http://en.wikipedia.org[/url][/*] {{ Внешние ссылки - на сайты }}
[m0][*]► [i][com]Wiki (Eng):[/com][/i] [url]{{http://}}www.en.wikipedia.org[/url][/*]
[m0][*]► [i][com]Сайт (Rus):[/com][/i] [url]www.goo.gl/XLFQnc[/url][/*]
[m0][*][p]см.[/p] <<О словаре>>[/*] {{ Внутренние ссылки. Вариант 1 }}
[m0][*][p]см. тж[/p] {{ Внутренние ссылки. Вариант 2 }}
- <<команды DSL>>
- [ref]вложенная карточка[/ref]
- <<особые статьи словаря>>
- <<контрольная карточка>>
[/*]
[*] [/*] {{ Картинка или фото. Вариант 1 }}
[m1][*][s]Photo.jpg[/s][/*]
[m1][*][com][p]Рис.[/p] Подпись к рисунку [i]с выделением[/i]. [i][c silver]Изображение: Имя Автора.[/c][/i][/com][/*]
[*] [/*] {{ Картинка или фото. Вариант 1 }}
[m1][*][s]MP4_video.avi[/s][/*]
[m1][*][com][p]Видео:[/p] Подпись к видеоклипу [i]MP4[/i]. [i][c silver]Автор: Имя Фамилия.[/c][/i][/com][/*]
[m1][p]▪[/p] [com][c gainsboro]05.04.2015[/c][/com] {{ Дата обработки карточки }}
{{ ≡05.04.2015 }} {{ Зона служебных комментариев }}
"""##
let stringRange = NSRange(location: 0, length: testString.utf16.count)
let matches = regex.matches(in: testString, range: stringRange)
var result: [[String]] = []
for match in matches {
var groups: [String] = []
for rangeIndex in 1 ..< match.numberOfRanges {
let nsRange = match.range(at: rangeIndex)
guard !NSEqualRanges(nsRange, NSMakeRange(NSNotFound, 0)) else { continue }
let string = (testString as NSString).substring(with: nsRange)
groups.append(string)
}
if !groups.isEmpty {
result.append(groups)
}
}
print(result)
Please keep in mind that these code samples are automatically generated and are not guaranteed to work. If you find any syntax errors, feel free to submit a bug report. For a full regex reference for Swift 5.2, please visit: https://developer.apple.com/documentation/foundation/nsregularexpression