Коротко
Здається, що швидке рішення вашої проблеми полягає у визначенні REGEX, або FSA (автомат з обмеженим станом), який розпізнає всі можливі початки документів (помилкові позитиви дозволені, що фактично не відповідало б документу). Потім ви можете запустити його дуже швидко на своєму введенні, щоб визначити наступне місце, де документ може починатися з кількох помилок. Це може спричинити кілька помилкових позицій для запуску документа, але вони будуть розпізнані парсером і залишені.
Тож Finite State Automaton може бути назвою парсера, якого ви шукали. :)
Проблема
Завжди важко зрозуміти практичну проблему, особливо коли словниковий запас може мати багато тлумачень. Слово "розбір лісу" було придумано (afaik) для безтекстового розбору неоднозначних речень, які мають кілька дерев розбору. Це може бути дещо узагальнено для розбору решітки речень або до інших типів граматики. Звідси всі відповіді про Ерлі, GLR, Marpa та похідні аналізатори (є багато інших), які не були актуальними в даному випадку.
Але це, мабуть, не те, що ви маєте на увазі. Ви хочете проаналізувати унікальний рядок, який є послідовністю однозначних документів, і отримати дерево розбору для кожного , або якесь структуроване представлення, оскільки ви насправді не говорите, як визначається синтаксис ваших документів, де він стоїть формальна мовна точка зору. У вас є алгоритм та таблиці, які будуть виконувати завдання розбору при запуску на початку документа. Тож нехай так.
Справжня проблема полягає в тому, що ваш потік документів містить багато сміття, яке розділяє документи. І здається, що ваша складність полягає в тому, щоб сканувати це сміття досить швидко. Ваша поточна техніка полягає в тому, щоб почати спочатку, і спробувати сканувати з першого символу, і переходити до перезавантаження наступного символу, коли він не виходить, поки ви не скануєте весь документ. Потім ви повторюєте заяву від першого символу після того, як документ щойно просканований.
Це також рішення, запропоноване @amon у другій частині своєї відповіді .
Це може бути не дуже швидким рішенням (я не маю можливості перевірити), тому що навряд чи код аналізатора буде оптимізований, щоб дуже ефективно запуститись на початку документа. При звичайному використанні це робиться лише один раз, так що це не гаряча точка з точки зору оптимізації. Отже, ваше помірне щастя з цим рішенням не надто дивно.
Тож вам справді потрібен алгоритм, який дозволяє швидко знайти початок документа, який починається з маси сміття. І вам пощастило: такі алгоритми існують. І я впевнений, що ви це знаєте: це називається пошук REGEX.
Просте рішення
Що вам потрібно зробити, це проаналізувати специфікацію ваших документів, щоб знайти, як починаються ці документи. Я не можу точно сказати вам, як я не впевнений, як їх специфікація синтаксису організована. Можливо, всі вони починаються з якогось слова з кінцевого списку, можливо, змішаного з деякими розділовими знаками чи цифрами. Це вам потрібно перевірити.
Що вам потрібно зробити, це визначити автоматику з кінцевим станом (FSA) або рівнозначно для більшості програмістів регулярний вираз (REGEX), який може розпізнати перші кілька символів документа: чим більше, тим краще, але це не повинно бути дуже великий (тому що це може зайняти час і місце). Це можна зробити порівняно легко із специфікації ваших документів, і, ймовірно, це можна зробити автоматично за допомогою програми, яка зчитує специфікацію ваших документів.
Після того, як ви створили свій регулярний геть, ви можете запустити його у вхідному потоці, щоб дуже швидко перейти до початку першого (або наступного) документа, як описано нижче:
Я припускаю:
- docstart
це регулярний вираз, який відповідає початку всіх документів,
- search(regex, stream)
це функція, яка шукає stream
підрядку, яка відповідає regex
. Коли він повертається, потік зменшується до підпотоку суфіксу, починаючи з початку першого підрядного збігу, або до порожнього потоку не знайдено відповідності.
- parse(stream)
намагається проаналізувати документ з початку потоку (те, що від нього залишилося), і поверне дерево розбору в будь-якому форматі або не вдасться. Коли він повертається, потік зменшується до підпотоку суфіксу, починаючи з позиції, безпосередньо після закінчення проаналізованого документа. Він називає виняток, якщо аналіз не вдається.
forest = empty_forest
search(docstart, stream)
while stream is not empty:
try:
forest = forest + parse(stream)
except
remove first character from stream
search(docstart, stream)
Зауважте, що видалення першого символу необхідно, щоб наступний пошук знову не знайшов ту саму відповідність.
Звичайно, вкорочення потоку - це зображення. Це може бути просто індекс на потоці.
Остаточне зауваження полягає в тому, що ваш регулярний вираз не повинен бути надто точним, якщо він розпізнає всі початки. Якщо він час від часу розпізнає рядок, який не може бути початком документа (помилково позитивний), то єдиним штрафом є вартість одного марного дзвінка на аналізатор.
Тож це, можливо, допоможе спростити регулярний вираз, якщо це корисно.
Про можливість швидшого вирішення
Вищеописане рішення має працювати досить добре у більшості випадків. Однак якщо у вас дійсно багато сміття та терабайт файлів для обробки, можуть бути інші алгоритми, які працюють швидше.
Ідея походить від алгоритму пошуку рядків Боєра-Мура . Цей алгоритм може надзвичайно швидко шукати потік для однієї струни, оскільки використовує структурний аналіз рядка, щоб пропустити читання більшої частини потоку, перестрибуючи фрагменти, навіть не дивлячись на них. Це найшвидший алгоритм пошуку для однієї струни.
Трудність полягає в тому, що його адаптація до пошукового регулярного виразу, а не однієї струни, здається дуже делікатною і може працювати не так добре, залежно від особливостей регексу, який ви розглядаєте. Це, в свою чергу, може залежати від синтаксису документів, які ви розбираєте. Але не дуже довіряйте мені з цього приводу, оскільки я не встиг уважно прочитати знайдені документи.
Я залишаю вас з одним або двома вказівниками, які я знайшов в Інтернеті, включаючи той, який, мабуть, є реферованим науково-дослідним документом , але ви повинні вважати це більш спекулятивним, можливо, дослідницьким, яке слід розглядати лише у тому випадку, якщо у вас виникли сильні проблеми з роботою. І, мабуть, немає програми полиць, яка б це зробила.