Что именно является работой лексера? - PullRequest
0 голосов
/ 28 февраля 2019

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

Наиболее распространенное определение лексера заключается в том, что он преобразует входной поток символов в выходнойпоток токенов .

Input         →  Output 
(characters)     (tokens)

Поначалу это звучит довольно просто, но возникает вопрос: насколько семантическая интерпретация Лексер должен это сделать, прежде чем передать свои выходные данные токенов парсеру.


Возьмите этот пример синтаксиса Markdown:

### Headline
*This* is an emphasized word.

Он может быть переведен лексером в следующие сериииз токенов:

Вывод Lexer 1

.headline("Headline")
.emphasis("This")
.text"(" is an emphasized word.")

Но он также может быть переведен на более детальный уровень, в зависимости от используемой грамматики (или набора лексем):

Вывод Lexer 2

.controlSymbol("#")
.controlSymbol("#")
.controlSymbol("#")
.text(" Headline")
.controlSymbol("*")
.text("This")
.controlSymbol("*")
.text"(" is an emphasized word.")

Кажется, гораздо более практично, чтобы лексер выдавал вывод, аналогичный выводу Lexer 1 , потому что парсер будет тогда выполнять более легкую работу,Но это также означает, что лексеру нужно семантически понять , что означает код.Это не просто сопоставление последовательности символов токену.Нужно смотреть в будущее и выявлять закономерности.(Например, он должен уметь различать **Hey* you* и **Hey** you. Он не может просто перевести двойную звездочку ** в .openingEmphasis, поскольку это зависит от следующего контекста.)

Согласно этой записи Stackoverflow и определению CommonMark , кажется, имеет смысл сначала разбить вход Markdown на несколько блоков (представляющих одну или несколько строк) изатем проанализируйте содержимое каждого блока на втором этапе.В приведенном выше примере это будет означать следующее:

.headlineBlock("Headline")
.paragraphBlock("*This* is an emphasized word.")

Но это не будет считаться допустимой последовательностью токенов, потому что некоторые лексемы ("*") еще не были проанализированы, и этоПравильно передать это paragraphBlock парсеру.


Так вот мой вопрос:

Где вы рисуете линию?

Сколько семантикиработу должен делать лексер?Есть ли какое-то сложное определение лексера, о котором я не знаю?

Как лучше всего определить грамматику для лексера?

...