Написання компілятора компілятора - розуміння використання та функцій


10

Це частина серії запитань, яка присвячена сестринському проекту до проекту абстракції, який має на меті абстрагувати поняття, які використовуються в мовному дизайні у формі рамки. Сестринський проект називається OILexer, який має на меті побудувати аналізатор з граматичних файлів, без використання введення коду на сірники.

Деякі інші сторінки, пов’язані з цими питаннями, пов’язаними зі структурним набором тексту, можна переглянути тут та прості у використанні, які можна знайти тут . Метатему, пов’язану із запитом про рамки та правильне місце для публікації, можна знайти тут .

Я доходжу до того, що я збираюся розпочати видобуток дерева розбору з заданої граматики, а потім рекурсивний аналізатор спуску, який використовує DFA для виявлення прямих шляхів (подібно до LL ANTLR 4 (*)), тому я подумав, що я відкрию це для отримання розуміння.

Які компілятори для аналізатора розглядають, які функції є ідеальними?

Поки тут короткий огляд того, що реалізовано:

  1. Шаблони
  2. Погляньте наперед передбачення, знаючи, що діє в даній точці.
  3. Правило "Делітералізація", що приймає буквари в правила і вирішує, з якого маркера вони походять.
  4. Недетерміновані автомати
  5. Детерміновані автомати
  6. Проста машина лексичного стану для розпізнавання лексем
  7. Методи автоматизації токенів:
    • Сканування - корисно для коментарів: Коментар: = "/ *" Сканування ("* /");
    • Віднімання - корисно для ідентифікаторів: Ідентифікатор: = Віднімання (IdentifierBody, Ключові слова);
      • Переконайтесь, що ідентифікатор не приймає ключові слова.
    • Кодування - Кодує автоматизацію як кількість X переходів базових N.
      • UnicodeEscape: = "\\ u" BaseEncode (IdentifierCharNoEscape, 16, 4);
        • Робить унікод втечі в шістнадцятковому розмірі, з шістнадцятковим 4-переходом. Різниця між цим та: [0-9A-Fa-f] {4} є результатом автоматизації з кодуванням обмежує дозволений набір шістнадцяткових значень на область IdentifierCharNoEscape. Отже, якщо ви надаєте \ u005c, версія кодування не прийме значення. Такі речі мають серйозний застереження: використовуйте економно. Отримана автоматизація може бути досить складною.

Те, що не реалізовано, це генерація CST, мені потрібно налаштувати детерміновані автоматики, щоб переносити належний контекст, щоб це працювало.

Для всіх, хто цікавиться, я завантажив симпатичну надруковану оригінальну форму проекту T * y♯ . Кожен файл повинен посилатися на кожен інший файл, я почав посилатись на окремі правила, щоб дотримуватися їх, але це зайняло б занадто багато часу (було б простіше автоматизувати!)

Якщо потрібен додатковий контекст, будь ласка, опублікуйте його відповідно.

Редагувати 5-14-2013 : Я написав код для створення графіків GraphViz для державних машин у межах заданої мови. Ось графік GraphViz Парламенту AssemblyPart . Члени, пов'язані в описі мови, повинні мати ім'я правила.txt у своїй відносній папці з диграфом для цього правила. Частина опису мови змінилася з моменту розміщення прикладу, це пов’язано зі спрощенням речей про граматику. Ось цікавий графічний образ .


8
Текст стіни Не сприймайте це неправильно, я ціную детально пояснену проблему. У цьому випадку це просто трохи багатослівний. З того, що я зібрав, ви запитуєте, які функції слід включити до граматичного аналізатора чи як зробити його, не починаючи з нуля? Відредагуйте, щоб відповісти на наступні запитання (вам не потрібно переписувати, просто додайте до кінця підсумки): У чому ваша проблема? Якими обмеженнями ви обмежуєте можливі рішення вашої проблеми (вона повинна бути швидкою, вона повинна бути LL * тощо)?
Ніл

1
Я прошу ознайомитися з набором функцій. Основна увага приділяється простоті використання. Складність полягає в тому, щоб отримати того, хто не знає проекту, зрозуміти проект, щоб вони були поінформовані щодо його фокусу. Я не прошу "як це зробити", я запитую, що стосується юзабіліті. Пропозиції щодо того, як обрізати питання, цінуються.
Аллен Кларк Коупленд-молодший

1
Мені не очевидно, про що йдеться у проекті. Наприклад, з часів yacc ми бачили безліч генераторів розбору. Що відрізняється у вашому OILexer? Що нового?
Інго

1
Мета цього проекту - спростити генерацію парсера. Так, YACC / Bison та FLEX / LEX. Основна відмінність полягає в тому, щоб уникнути складності цих програм. Основна мета полягає в тому, щоб бути простим і зрозумілим. Ось чому я створив формат, позбавлений непарних секціонувань, а швидше мета - зробити його подібним до звичайного програмування: лише специфічного для мовного розвитку. Токени визначаються, використовуючи ': =' після їх імені, правила визначаються за допомогою :: = після їх імені. Шаблони використовують '<' і '>' для своїх аргументів, а потім ":: =", оскільки вони поділяють синтаксис правил.
Аллен Кларк Коупленд-молодший

3
Цей пекельний фокус на синтаксичному розборі здається неправильним; це добре вирішена проблема, і вона навряд чи значить, що потрібно для обробки мов програмування. Google для мого реферату на тему "життя після розбору".
Іра Бакстер

Відповіді:


5

Це відмінне запитання.

Я нещодавно працюю над синтаксичним розбором, і одним із ключових особливостей IMHO є:

  • програмний API - тому його можна використовувати з мови програмування, в ідеалі - просто імпортувати бібліотеку. Він також може мати інтерфейс, схожий на GUI або BNF, але ключовим є програмний, тому що ви можете повторно використовувати інструменти, IDE, статичний аналіз, тестування, засоби абстракції мови, знайомство з програмістом, генератор документації, процес збирання, Крім того, ви можете інтерактивно грати з крихітними парсерами, що різко зменшує криву навчання. Ці причини ставлять її в першу чергу мого списку "важливих особливостей".

  • повідомлення про помилки, як згадував @guysherman Коли виявлена ​​помилка, я хочу знати, де була помилка та що відбувалося, коли вона сталася. На жаль, мені не вдалося знайти хороших ресурсів для пояснення того, як генерувати пристойні помилки під час гри. (Хоча коментар @ коментар Sk-логіки нижче).

  • часткові результати. Коли аналіз не вдається, я хочу мати змогу побачити, що було успішно проаналізовано з тієї частини вводу, яка була до місця помилки.

  • абстракція. Ніколи не можна побудувати достатньо функцій, і користувачеві завжди буде потрібно більше, тому намагання розібратися в усіх можливих функціях наперед виправдано на провал. Це ви маєте на увазі під шаблонами?

  • Я згоден з вашим №2 (прогнозування вперед). Я думаю, що це допомагає створювати хороші звіти про помилки. Це корисне для чогось іншого?

  • підтримка побудови дерева розбору під час розбору, можливо:

    • конкретне синтаксичне дерево, для якого структура дерева відповідає безпосередньо граматиці і включає інформацію про компонування для повідомлення про помилки пізніших фаз. У цьому випадку клієнту не слід нічого робити, щоб отримати правильну структуру дерева - це має залежати безпосередньо від граматики.
    • абстрактне синтаксичне дерево. У цьому випадку користувач може поспілкуватися з будь-якими деревами розбору
  • якась вирубка лісу. Я не впевнений у цьому; можливо, показати сліди правил, які спробував аналізатор, або відслідковувати непотрібні жетони, такі як пробіл або коментарі, у випадку, якщо (наприклад) ви хочете використовувати маркери для створення HTML-документації.

  • вміння працювати з контекстно-чутливими мовами. Не впевнений, наскільки це важливо - на практиці здається, більш чітко проаналізувати надмножину мови з граматикою без контексту, а потім перевірити контекстно-залежні обмеження в додаткових пізніших пропусках.

  • спеціальні повідомлення про помилки, щоб я міг настроювати звіти про помилки в конкретних ситуаціях і, можливо, швидше зрозуміти та виправити проблеми.

З іншого боку, я не вважаю виправлення помилок особливо важливим, хоча я не в курсі поточного прогресу. Проблеми, які я помітив, полягають у тому, що можливі виправлення, що надаються інструментами: 1) занадто численні та 2) не відповідають фактичним допущеним помилкам, і тому вони не так корисні. Сподіваємось, ця ситуація покращиться (або, можливо, це вже було зроблено).


Я відредагував тіло запитання, щоб включити посилання на PrecedenceHelper у кулі, що читає "Шаблони". Це дозволяє кортежі масивів параметрів, тому якщо у вас є чотири параметри, кожен масив параметрів шаблон повинен використовуватися в наборах аргументів з чотирьох.
Аллен Кларк Коупленд-молодший

Основна причина, з якої ви побудуєте CST, - це загальна компонування розібраного файлу. Якщо ви хочете гарненько роздрукувати документ, найкраще використовувати CST, оскільки AST, як їх назва, означає відсутність інформації для обробки незвичайного інтервалу, який би захопив CST. Трансформація CST зазвичай досить проста, якщо це хороший CST.
Аллен Кларк Коупленд-молодший

Я знову відредагував питання щодо теми вбудованих функцій, доступних для використання.
Аллен Кларк Коупленд-молодший

Я думаю, що я не підійшов до великої роботи, висловлюючи свою думку щодо шаблонів / функцій: я мав на увазі, що оскільки у вас ніколи не може бути достатньо, система не повинна намагатися розібратися в них заздалегідь: користувачеві потрібно вміти створювати його власний.

1
Я знайшов один підхід особливо корисним для звітування про помилки з нескінченним зворотним відстеженням (Packrat): кожне виробниче правило коментується повідомленнями про помилки (сформульовано як "бла-бла-бла-очікується"), а при відмові таке повідомлення зберігається в потоці однаково як запам’ятовані лексеми. Якщо всі збої не підлягають відновленню (розбір завершується до досягнення кінця потоку), найбільш правильним є повідомлення про помилку (або колекцію таких повідомлень). Це найпростіше зробити, звичайно, є способи їх подальшого уточнення за допомогою більшої кількості анотацій.
SK-логіка

5

Я не маю досвіду в мовному дизайні, але колись, коли я створював і IDE для ігрового двигуна, я писав аналізатор.

Що є важливим для ваших кінцевих користувачів, на мою думку, це повідомлення про помилки, які мають сенс. Я знаю, що це не особливо руйнівна земля, але слідуючи її назад, одним із ключових наслідків цього є те, що вам потрібно вміти уникати помилкових позитивних результатів. Звідки беруться помилкові позитиви? Вони надходять з аналізатора, що потрапляє при першій помилці і ніколи не одужує. C / C ++ для цього відомий (хоча новіші компілятори трохи розумніші).

То що вам натомість потрібно? Я думаю, що замість того, щоб просто знати, що є / не дійсно в певний момент, вам потрібно знати, як прийняти те, що не дійсно, і внести мінімальні зміни, щоб зробити його дійсним - так що ви можете продовжити розбір без генерування помилкових помилок, пов'язаних до вашого рекурсивного походження заплутався. Можливість складання аналізатора, який може генерувати цю інформацію, не тільки дає вам дуже надійний аналізатор, але і відкриває деякі фантастичні можливості для програмного забезпечення, яке споживає аналізатор.

Я усвідомлюю, що, можливо, я пропоную щось дійсно важке або дурно очевидне, вибачте, якщо це так. Якщо це не та річ, яку ви шукаєте, я з радістю видалю свою відповідь.


Це одна з речей, яку я планую робити. Щоб допомогти моїм знанням домену, мій друг запропонував написати фактичний аналізатор вручну, щоб отримати змогу автоматизувати його. Одне я зрозумів досить швидко: парсери складні, і є речі, які ми робимо вручну, які спрощують процес. Правила та шаблони мають однаковий синтаксис; однак є мовні елементи, які дійсні в Шаблонах, але не правила, є внутрішні стани, які справляються з цим завданням. Що придумало ідею: правила повинні мати можливість вказувати посібники для шляху, щоб полегшити спільне використання правил.
Аллен Кларк Коупленд-молодший

... це має бути досить простим для передачі в автоматизацію, але вимагає, щоб автомати мали умови, засновані на державі. Я над цим попрацюю і повернуся до вас. ANTLR використовує автоматику обмеженого стану для обробки циклів скажіть: "T" *, де я буду використовувати його для обробки більшості процесів розбору, оскільки скорочення повинні бути більш чистими, оскільки стани, коли в правилі є 800+ варіацій (це буде розмиватися швидко, як код спагетті у стандартній формі if / else.)
Аллен Кларк Коупленд-молодший,

0

У граматиці не повинно бути обмежень на кшталт "не залишили рекурсивних правил". Смішно, що інструменти, які широко використовуються сьогодні, мають це і розуміють лише смоктання граматики LL - майже через 50 років після того, як yacc зробив це правильно.

Приклад правильної рекурсії (з використанням синтаксису yacc):

list: 
      elem                  { $$ = singleton($1); }
    | elem ',' list         { $$ = cons($1, $2);  }
    ;

Приклад для лівої рекурсії (з використанням синаксису yacc):

funapp:
    term                    { $$ = $1; }
    | funapp term           { $$ = application($1, $2); }
    ;

Тепер це може бути "відновлене" до чогось іншого, але в обох випадках конкретний вид рекурсії - це лише "правильний" спосіб написання цього запису, оскільки (на прикладі мови) списки є право рекурсивними, тоді як додаток функції залишається рекурсивним. .

Від сучасних інструментів можна очікувати, що вони підтримують природний спосіб записувати речі, замість того, щоб вимагати від них «рефактор», щоб все було ліво / право рекурсивної форми, яку інструмент накладає на один.


Так, приємно не мати подібних довільних обмежень. Однак, що є прикладом лівої рекурсії, яку не можна замінити оператором повторення (наприклад, регулярними виразами *або +кванторами)? Я вільно визнаю, що мої знання в цій галузі обмежені, але я ніколи не стикався з використанням лівої рекурсії, яку не можна було б відновити до повторення. І я вважав, що версія повторення також більш чітка (хоча це лише особисті переваги).

1
@MattFenwick Дивіться мої зміни. Зверніть увагу, як синтаксична директива призводить до простих і природних смислових дій (наприклад) для створення синтаксичного дерева. Хоча з повторенням (якого немає в yacc, btw), я думаю, вам часто потрібно перевірити, чи є у вас порожній список, сингл тощо.
Ingo

Дякую за відповідь. Я думаю , що я краще розумію тепер , - я волів би , щоб написати ці приклади , як list = sepBy1(',', elem)і funapp = term{+}(і, звичайно , sepBy1і +буде здійснюватися з точки зору ліво- / рекурсії, і виробляти стандартні синтаксичні дерева). Тож не те, що я вважаю, що ліва та права рекурсія погані, це просто те, що я відчуваю, що вони низькі, і хотів би використовувати абстракцію вищого рівня, де це можливо, щоб зробити речі зрозумілішими. Знову дякую!

1
Вас вітає @MattFenwick. Але тоді це, можливо, справа смаку. Для мене рекурсія (принаймні, в контексті мов, які по суті є рекурсивними або абсолютно нецікавими), більш природний спосіб її думати. Також дерево є рекурсивною структурою даних, тому я не бачу необхідності повертатися до ітерації для імітації рекурсії. Але, звичайно, вподобання різні.
Інго
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.