185 похожих чатов

@Zukaboo спасибо за очень важные замечания. А как вам такой

вариант?
______________
Очень часто разбор текста и построение из него дерева разбора (parse tree) удобно разбить на две фазы. В первой фазе используется близкая к регулярной, но не регулярная грамматика (грамматика, описываемая регулярными выражениями), во второй фазе - контекстно-свободная. Это разбиение, в принципе, не обязательно, но крайне удобно и быстро.

В первой фазе текст пропускается через некоторую программу (*лексер*), которая читает текст программы посимвольно (UTF8 или ASCII символы), составляя из этих символов слова (так называемые tokens) используя регулярные выражения. Грамматика языка, разбираемого лексером отличается от регулярной тем, что в случае альтернативы выбирается не первый подходящий вариант, а тот, что даёт наиболее длинный префикс (жадный выбор). Важно, что получающееся дерево разбора *вырождено*, то есть, это просто список, и, таким образом, поток символов ASCII превращается в поток token'ов. С формальной точки зрения и то, и другое - _символы_, но разных языков.
_______________

То есть, подчёркиваем, что грамматика не регулярная, но близкая к ней. Отличается от регулярной тем, что выбор альтернатив жадный. Поскольку это всё равно разбор, пусть и экзотического неназванного класса грамматик, это парсер.

11 ответов

50 просмотров

> Это разбиение, в принципе, не обязательно, но крайне удобно и быстро. Нет, это разбиение строго обязательно для разбора подавляющего большинства практически используемых ЯП с помощью CFG (и parser generators, особенно широко используемых LALR / LR), т.е. сделать это без него тупо невозможно. > составляя из этих символов слова (так называемые tokens) используя регулярные выражения. Нет, чаще всего lexer-ы используют не только регулярные выражения (в том числе в этом и суть их применения). Тут уже приводили примеры — мне кажется, или Вы их все проигнорировали? :( > Грамматика языка, разбираемого лексером По-моему, это вообще не разбор. Если открыть любой учебник по parsers (или формальной лингвистике), или даже погуглить определение этого понятия (и того, что такое recognition, вообще) — очевидно, что то, что делают lexers — это, в общем (практическом!) случае, не он: "Parsing is the process of structuring a linear representation in accordance with a given grammar." "The task of parsing is to reconstruct the derivation tree (or graph) for a given input string." "To parse a string according to a grammar means to reconstruct the production tree (or trees) that indicate how the given string can be produced from the given grammar." "Parsing, syntax analysis, or syntactic analysis is the process of analyzing a string of symbols, either in natural language, computer languages or data structures, conforming to the rules of a formal grammar. " Обратите внимание, что во всех определениях есть строка символов, и parsing определяет, какое дерево (или деревья, или графы) разбора соответствуют ей целиком, понимаете? Т.е. даже грамматика языка, получаемого последовательными вызовами gettoken() для строки (до победного конца), хотя эта функция использует исключительно longest DFA matching — не регулярная! > Важно, что получающееся дерево разбора Там может вообще не получаться ни дерева разбора, ни потока или массива tokens, в практическом случае. Поступать так на практике для одного языка не принято... но про lexer hack (из C) все слышали, вроде? ;) А при language composition (т.е. например, "смешивании" C и SQL в один язык) с использованием lexers сами выделяемые tokens будут контекстно-зависимы, т.е. модель "поток/массив токенов" тут неприменима. > то есть, это просто список, и, таким образом, поток символов ASCII превращается в поток token'ов. Но это, в самом деле, распространённая "абстрактная" модель для [упрощения изложения темы] parsing. Только к практике она относится далеко не всегда. > Поскольку это всё равно разбор, пусть и экзотического неназванного класса грамматик, это парсер. Для некоторых случаев это "сойдёт", см. выше.

Yaroslav Schekin
> Это разбиение, в принципе, не обязательно, но кр...

Вы очень долго распространялись на тему, чем лексеры НЕ являются, но чем же они являются и как определяются осталось совершенно непонятным, как минимум мне.

Konstantin-Romanov Автор вопроса
Yaroslav Schekin
> Это разбиение, в принципе, не обязательно, но кр...

1. Спасибо за упоминание того, что учёт контекста в лексере позволяет убрать учёт контекста в парсере. Александр упоминал про контекстно-зависимые грамматики второй фазы, но я забыл это вставить. 2. Да, в лексерах используют не только регулярные выражения. Я сознательно замёл это под ковёр. Обычно это всё-таки делает малая доля правил. 3. > По-моему, это вообще не разбор. Список лексем - это тоже дерево, просто очень частный вид. Грамматика, упрощённая вот - регулярная + жадность. 4. > Там может вообще не получаться ни дерева разбора, ни потока или массива tokens, в практическом случае. Ну конкретно flex не может выдать ничего другого, кроме потока, на вход парсера.

Alexander Chichigin
Вы очень долго распространялись на тему, чем лексе...

Это, в общем случае, такая штука, которая для текущей (или заданной) позиции во входном потоке (почти всегда — потоке символов), и, возможно, внутреннего (хранимого) состояния и передаваемых ему parser-ом параметров возвращает очередной token.

Konstantin Romanov
1. Спасибо за упоминание того, что учёт контекста ...

> Обычно это всё-таки делает малая доля правил. "Обычно" Вы без этого почти ни один практический язык не разберёте. Т.е. Вы ребёнка под ковёр замели выплеснули вместе с водой. ;( > Список лексем - это тоже дерево, просто очень частный вид. Если он вообще есть. Покажете нам, как создать "список лексем" для типичного LALR-parser для C, не используя parser? > Ну конкретно flex не может выдать ничего другого, кроме потока, на вход парсера. Вы вообще не поняли, что я имел в виду. :( То, что выдаёт flex на вход parser, может зависеть (хоть целиком определяться!) теми параметрами, с которыми его вызывает parser, а не входным потоком символов, понимаете?

Yaroslav Schekin
> Это разбиение, в принципе, не обязательно, но кр...

> т.е. сделать это без него тупо невозможно integer = digit | digit integer digit = '0' | … Не вижу невозможности.

Konstantin-Romanov Автор вопроса
suhr
> т.е. сделать это без него тупо невозможно integ...

Вопрос с жадностью остаётся открытым.

Konstantin Romanov
Вопрос с жадностью остаётся открытым.

Этот вопрос появляется при лексинге, а не при разборе одной огромной грамматики.

Реальные языки часто даже не контекстно-свободные. Но я могу взять какой-нибудь Oberon, и тогда просветление не состоится.

Похожие вопросы

Обсуждают сегодня

Господа, а что сейчас вообще с рынком труда на делфи происходит? Какова ситуация?
Rꙮman Yankꙮvsky
29
А вообще, что может смущать в самой Julia - бы сказал, что нет единого стандартного подхода по многим моментам, поэтому многое выглядит как "хаки" и произвол. Короче говоря, с...
Viktor G.
2
30500 за редактор? )
Владимир
47
а через ESC-код ?
Alexey Kulakov
29
Гайс, вопрос для разносторонее развитых: читаю стрим с юарта, нада выделять с него фреймы с определенной структурой, если ли чо готовое, или долбаться с ринг буффером? нада у...
Vitaly
9
Чёт не понял, я ж правильной функцией воспользовался чтобы вывести отладочную информацию? но что-то она не ловится
notme
18
У меня есть функция где происходит это: write_bit(buffer, 1); write_bit(buffer, 0); write_bit(buffer, 1); write_bit(buffer, 1); write_bit(buffer, 1); w...
~
14
Добрый день! Скажите пожалуйста, а какие программы вы бы рекомендовали написать для того, чтобы научиться управлять памятью? Можно написать динамический массив, можно связный ...
Филипп
7
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
длина пакета фиксированная, или меняется?
Okhsunrog
7
Карта сайта