Коли люди кажуть, що "X не складає", те, що вони означають під "скласти", насправді означає "скласти разом", а що і як ви складаєте їх, може бути дуже різним, залежно від того, що саме "X".
Крім того, коли вони кажуть "не складається", вони можуть означати деякі дещо різні речі:
- Ви не можете скласти два X разом, період.
- Ви можете помістити два хрестики разом, але результат не може бути X (IOW: X НЕ замкнуто щодо композиції .)
- Можна скласти два X разом, але отриманий X може не працювати так, як ви очікували.
Прикладом №1 є парсери зі сканерами / лексерами. Ви можете почути фразу "сканери / лексеми не складають". Це насправді не так. Що вони означають, це "аналізатори, які використовують окремий етап лексингу, не складають".
Навіщо ви хочете складати парсери? Ну, уявіть, ви такий продавець IDE, як JetBrains, Eclipse Foundation, Microsoft або Embarcadero, і ви хочете створити IDE для веб-рамок. У типовій веб-розробці ми часто змішуємо мови. У вас є HTML-файли з <script>
елементами, що містять ECMAScript і<style>
елементи, що містять CSS. У вас є файли шаблонів, що містять HTML, деяку мову програмування та метасинтаксис мови мови шаблонів. Ви не хочете писати різні підсвічувачі синтаксису для "Python", "Python, вбудований у шаблон", "CSS", "CSS у HTML", "ECMASCript", "ECMAScript у HTML", "HTML", "HTML у межах шаблон "і так далі тощо. Ви хочете написати підсвічувач синтаксису для Python, один для HTML, один для мови шаблону, а потім скласти три в підсвічувач синтаксису для файлу шаблону.
Однак лексери розбивають весь файл на потік лексем, що має сенс лише для цієї однієї мови. Аналізатор іншої мови не може працювати з лексемами, якими передається лексера. Наприклад, парсери Python, як правило, написані таким чином, що лексери відслідковують відступ і вводять підроблені INDENT
та DEDENT
лексеми в потік токенів, таким чином дозволяючи парсеру бути без контексту, хоча синтаксис Python насправді не є. Однак лексер HTML повністю ігнорує пробіли, оскільки він не має значення в HTML.
Однак сканер без сканера, який просто зчитує символи, може передати потік символів на інший аналізатор, який потім може повернути його назад, тим самим полегшивши їх композицію.
Прикладом №2 є рядки з запитами SQL. Ви можете мати два рядки, у кожному з яких є синтаксично правильний SQL-запит, але якщо ви об'єднаєте два рядки, результат може бути не синтаксично правильним запитом SQL. Ось чому ми маємо запит алгебру , як ARel
, які роблять складати.
Замки - приклад №3. Якщо у вас є дві програми з блокуваннями, і ви об'єднали їх в одну програму, у вас все ще є програма з блокуваннями, але навіть якщо дві оригінальні програми були повністю коректними, без тупиків і перегонів, отримана програма не обов'язково має це майно. Правильне використання блокування - це загальна властивість всієї програми та властивість, яка не зберігається під час створення програм. Це відрізняється від, наприклад, операції, що роблять складати. Програма, яка правильно використовує транзакції, може складатися з іншою такою програмою і дасть комбіновану програму, яка правильно використовує транзакції.