Я пишу парсер для языка разметки, который я создал (пишу на python, но это не совсем относится к этому вопросу - на самом деле, если это кажется плохой идеей, я хотел бы предложить вариант для лучшего пути) ,
Я читаю о синтаксических анализаторах здесь: http://www.ferg.org/parsing/index.html и работаю над написанием лексера, который, если я правильно понял, разделил содержимое на токены. Мне трудно понять, какие типы токенов мне следует использовать или как их создавать. Например, типы токенов в приведенном мной примере:
- STRING
- ИДЕНТИФИКАТОР
- ЧИСЛО
- WHITESPACE
- КОММЕНТАРИЙ
- EOF
- Многие символы, такие как {и (считаются их собственным типом токена
У меня проблема в том, что более общие типы токенов кажутся мне немного произвольными. Например, почему STRING имеет свой собственный отдельный тип токена и IDENTIFIER. Строка может быть представлена как STRING_START + (IDENTIFIER | WHITESPACE) + STRING_START.
Это также может быть связано с трудностями моего языка. Например, объявления переменных пишутся как {var-name var value}
и развертываются с помощью {var-name}
. Похоже , что '{'
и '}'
должно быть их собственные маркеры, но var_name и VAR_VALUE правомочные лексем типа, или же они оба падают под IDENTIFIER? Более того, VAR_VALUE может содержать пробелы. Пробел после var-name
используется для обозначения начала значения в объявлении. Любой другой пробел является частью значения. Становится ли этот пробел собственным токеном? Пустое пространство имеет только это значение в этом контексте. Более того, {
может не быть началом объявления переменной ... это зависит от контекста (это слово снова!). {:
начинает объявление имени, и{
может даже использоваться как часть некоторого значения.
Мой язык похож на Python в том, что блоки создаются с отступом. Я читал о том, как Python использует лексер для создания токенов INDENT и DEDENT (которые служат более или менее так же, как {
и }
во многих других языках). Python утверждает, что он не зависит от контекста, что означает для меня, что, по крайней мере, лексеру не нужно заботиться о том, где он находится в потоке, при создании токенов. Откуда лексер Python знает, что он создает токен INDENT определенной длины, не зная о предыдущих символах (например, предыдущая строка была новой строкой, поэтому начните создавать пробелы для INDENT)? Я спрашиваю, потому что мне тоже нужно это знать.
Мой последний вопрос - самый глупый: зачем нужен лексер? Мне кажется, что синтаксический анализатор может идти посимвольно и выяснять, где он находится и чего он ожидает. Добавляет ли лексер преимущество простоты?