У чому різниця між абстрактним деревом синтаксису та конкретним деревом синтаксису?


84

Я трохи читав про те, як працюють перекладачі / компілятори, і одна з проблем, де я заплутався, - це різниця між AST і CST. Я розумію, що парсер робить CST, передає його семантичному аналізатору, який перетворює його на AST. Однак я розумію, що семантичний аналізатор просто гарантує дотримання правил. Я насправді не розумію, чому він насправді вносив би зміни, щоб зробити його абстрактним, а не конкретним.

Щось мені не вистачає у семантичному аналізаторі, чи різниця між AST та CST дещо штучна?

Відповіді:


62

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

Проте конкретна граматика та дерево мають багато речей, необхідних для однозначного синтаксичного аналізу вихідного тексту, але не сприяють дійсному змісту. Наприклад, для реалізації пріоритету оператора ваш CFG зазвичай має кілька рівнів компонентів виразу (термін, фактор тощо), при цьому оператори з'єднують їх на різних рівнях (ви додаєте терміни, щоб отримати вирази, терміни складаються з факторів, необов'язково множених тощо). Однак для фактичного тлумачення або компіляції мови це вам не потрібно; вам просто потрібні вузли виразу, які мають оператори та операнди. Абстрактне дерево синтаксису є результатом спрощення конкретного дерева синтаксису аж до речей, які насправді необхідні для відображення значення програми. Це дерево має набагато простіше визначення, і тому його легше обробити на пізніх стадіях виконання.

Зазвичай вам не потрібно фактично будувати конкретне дерево синтаксису. Процедури дій у вашій граматиці YACC (або Antlr, або Menhir, або що завгодно ...) можуть безпосередньо будувати абстрактне дерево синтаксису, тому конкретне дерево синтаксису існує лише як концептуальна сутність, що представляє структуру синтаксичного аналізу вашого вихідного тексту.


2
Додаток: інтерпретатор Python спочатку створює CST, а потім перетворює на AST.
cgsdfc

33

Синтаксис конкретне дерево відповідає тому , що граматика правила говорять синтаксис. Метою абстрактного дерева синтаксису є "просте" представлення того, що є важливим у "дереві синтаксису".

Реальне значення в AST IMHO полягає в тому, що воно менше, ніж CST, і тому його обробка займає менше часу. (Можна сказати, кого це цікавить? Але я працюю з інструментом, де у нас живуть відразу десятки мільйонів вузлів!).

Більшість генераторів аналізаторів, які мають будь-яку підтримку для побудови дерев синтаксису, наполягають на тому, щоб ви особисто вказали, як саме вони будуються, припускаючи, що ваші дерева-вузли будуть "простішими", ніж CST (і в цьому, як правило, вони мають рацію, оскільки програмісти досить ледачий). Можливо, це означає, що вам доводиться кодувати менше функцій відвідувачів дерева, і це також цінне тим, що воно мінімізує енергетичну енергію. Коли у вас є 3500 правил (наприклад, для COBOL), це має значення. І ця «простіша» суть призводить до доброї властивості «маленькості».

Але наявність таких AST створює проблему, якої не було: вона не відповідає граматиці, і тепер вам доведеться подумки відстежувати їх обох. І коли для граматики 3500 правил існує 1500 вузлів AST, це має велике значення. І якщо граматика розвивається (вони завжди це роблять!), Тепер у вас є два гігантські набори речей, які слід синхронізувати.

Інше рішення - дозволити синтаксичному аналізатору просто будувати для вас вузли CST і просто використовувати їх. Це величезна перевага при побудові граматики: немає необхідності винаходити 1500 спеціальних вузлів AST для моделювання 3500 граматичних правил. Подумайте лише про те, що дерево ізоморфне граматиці. З точки зору інженера-граматика, це абсолютно безмозково, що дозволяє йому зосередитись на тому, щоб граматика була правильною, і хакнути її до душі. Можливо, вам доведеться писати більше правил відвідувачів вузлів, але цим можна керувати. Про це далі.

Що ми робимо з набором інструментів реінжинірингу програмного забезпечення DMS, це автоматичне створення CST на основі результатів процесу синтаксичного аналізу (GLR). Потім DMS автоматично створює "стислий" CST з міркувань космічної ефективності, усуваючи нецінні термінали (ключові слова, пунктуація), семантично марні одинарні постановки та формуючи списки для пар граматичних правил, які є списком, як:

    L = e ;
    L = L e ;
    L2 = e2 ;
    L2 = L2  ','  e2 ;

і найрізноманітніші варіації таких форм. Ви думаєте з точки зору граматичних правил та віртуального CST; інструмент працює на стисненому поданні. Легко на мозку, швидше / менше під час роботи.

Що примітно, стислий CST, побудований таким чином, виглядає набагато AST, який ви могли б створити вручну (див. Посилання в кінці прикладів). Зокрема, стислий CST не містить жодних вузлів, які є лише конкретним синтаксисом. Є незначні шматочки незручності: наприклад, хоча конкретні вузли для '(' і ')', класично знайдені в підграмах виразів, відсутні у дереві, "вузол у дужках" справді з'являється у стисненому CST і його потрібно обробляти. Справжній AST цього не мав би. Це здається досить малою ціною, щоб заплатити за зручність, коли не потрібно вказувати конструкцію AST, ніколи. І документація до дерева завжди доступна і правильна: граматика - це документація.

Як нам уникнути "зайвих відвідувачів"? Ми не повністю, але DMS надає бібліотеку AST, яка працює з AST і прозоро обробляє відмінності між CST та AST. DMS також пропонує оцінювач "граматики атрибутів" (AGE), який є методом передачі значень, обчислених вузлами вгору та вниз по дереву; AGE обробляє всі проблеми, пов’язані з представленням дерев, тому інженер-інструмент турбується лише про ефективне написання обчислень безпосередньо на правилах граматики. Нарешті, DMS також надає шаблони "поверхневого синтаксису", що дозволяє фрагментам коду з граматики використовуватись для пошуку конкретних типів піддерев, не знаючи більшості задіяних типів вузлів.

Одна з інших відповідей зазначає, що якщо ви хочете створити інструменти, які можуть регенерувати джерело, ваш AST повинен відповідати CST. Це насправді не правильно, але набагато легше відновити джерело, якщо у вас є вузли CST. DMS генерує більшу частину доситьпринтера автоматично, оскільки він має доступ до обох: -}

Підсумок: AST корисні для малих, як фіскальних, так і концептуальних. Автоматизована побудова AST від CST забезпечує обидва варіанти та дозволяє уникнути проблеми відстеження двох різних наборів.

EDIT березень 2015: Посилання на приклади CST проти "AST", побудовані таким чином


25

Це базується на граматиці Expression Evaluator Терренса Парра.

Граматика для цього прикладу:

grammar Expr002;

options 
{
    output=AST;
    ASTLabelType=CommonTree; // type of $stat.tree ref etc...
}

prog    :   ( stat )+ ;

stat    :   expr NEWLINE        -> expr
        |   ID '=' expr NEWLINE -> ^('=' ID expr)
        |   NEWLINE             ->
        ;

expr    :   multExpr (( '+'^ | '-'^ ) multExpr)*
        ; 

multExpr
        :   atom ('*'^ atom)*
        ; 

atom    :   INT 
        |   ID
        |   '('! expr ')'!
        ;

ID      : ('a'..'z' | 'A'..'Z' )+ ;
INT     : '0'..'9'+ ;
NEWLINE : '\r'? '\n' ;
WS      : ( ' ' | '\t' )+ { skip(); } ;

Вхідні дані

x=1
y=2
3*(x+y)

Розбір дерева

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

Розбір дерева

AST

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

AST

РЕДАГУВАТИ

Для більш детального пояснення див. Компілятори та генератори компіляторів, стор. 23


20

Цей допис у блозі може бути корисним.

Мені здається, що AST "викидає" багато проміжної граматичної / структурної інформації, яка не сприяла б семантиці. Наприклад, вам байдуже, що 3 - це атом - це термін - коефіцієнт - це .... Вас просто турбує те, що це 3коли ви реалізовуєте вираз степенізації або що завгодно.


9

Синтаксичне дерево бетону дотримується правил граматики мови. У граматиці "списки виразів", як правило, визначаються двома правилами

  • вираз_списку може бути: вираз
  • Список_виразів може бути: вираз, список_виразів

Дотримуючись буквально, ці два правила надають форму гребінця будь-якому списку виразів, який з’являється в програмі.

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


2

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


1

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

 

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


Ну, у ньому може бути не вся конкретна інформація. Все, що потрібно, це те, щоб вона могла регенерувати цю інформацію. Дивіться мою відповідь.
Ira Baxter

Прокоментували вчора? ТАК помилка, чи потрібно заробити значок некроманта коментаря, про який я не знаю? :) (PS: але приємно вас почути, ви щойно натрапили на вашу розмову Google Tech на DMS ...)
akuhn

1

Це різниця, яка не має різниці.

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

term: atom (('*' | '/') term )*

тоді як у випадку AST ви використовуєте лише mul_rule та div_rule, які виражають належні арифметичні операції.

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

term: mul_rule | div_rule
mul_rule: atom ('*' term)*
div_rule: atom ('/' term)*

Тепер, коли ви думаєте щодо розбору зверху вниз, тоді другий термін вводить ПЕРШИЙ / ПЕРШИЙ конфлікт між mul_rule та div_rule, з чим парсер LL (1) не може мати справу. Першою формою правила була лівофакторна версія другої, яка фактично ліквідувала структуру. Вам доведеться заплатити якийсь приз за використання LL (1) тут.

Отже, AST - це спеціальна добавка, яка використовується для усунення недоліків граматики та парсерів. Перетворення CST -> AST - це рефакторинг. Ніхто ніколи не турбував, коли в дереві синтаксису зберігається додаткова кома або двокрапка. Навпаки, деякі автори переробляють їх на AST, оскільки їм подобається використовувати AST для проведення рефакторингу замість того, щоб одночасно підтримувати різні дерева або писати додатковий механізм умовиводу. Програмісти лінуються з поважних причин. Насправді вони зберігають інформацію про парні рядки та стовпці, зібрану лексичним аналізом, в AST для повідомлення про помилки. Дійсно дуже абстрактно.


0

CST (Concrete Syntax Tree) - це дерево-представлення Граматики (Правила написання програми). Залежно від архітектури компілятора, аналізатор може використовувати його для створення AST.

AST (Абстрактне дерево синтаксису) - це дерево-представлення проаналізованого джерела, створене частиною аналізатора компілятора. Тут зберігається інформація про лексеми + граматика.

Залежно від архітектури вашого компілятора, CST може бути використаний для створення AST. Справедливо сказати, що КНТ перетворюється на АСТ. Або AST - це багатший CST.

Більше пояснень можна знайти за цим посиланням: http://eli.thegreenplace.net/2009/02/16/abstract-vs-concrete-syntax-trees#id6


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

1
Я змінив -1 на +1. Я вважаю, що наданих Вами роз’яснень достатньо.
Джошуа Хеджес
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.