Я пишу аналізатор для створеної мною мови розмітки (пишу в python, але це не дуже важливо для цього питання - адже, якщо це здається поганою ідеєю, я хотів би запропонувати кращий шлях) .
Я читаю про парсери тут: http://www.ferg.org/parsing/index.html , і я працюю над написанням лексеру, який повинен, якщо я правильно зрозумів, розділити вміст на лексеми. У мене виникають проблеми з розумінням, які типи токенів я повинен використовувати або як їх створити. Наприклад, типи токенів у прикладі, до якого я пов’язаний, є:
- STRING
- ІДЕНТИФІЄР
- НОМЕР
- БІЛИЙ ПРОСТІР
- КОМЕНТАР
- 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)? Я запитую, бо мені це теж потрібно знати.
Моє остаточне запитання найглупіше: чому лексеру навіть потрібно? Мені здається, що аналізатор міг би пройти персонаж за персонажем і зрозуміти, де він є і що його очікує. Чи додає лексеру користь від простоти?