λanguage: Написання парсера

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

Наприклад, для такого тексту програми:

sum = lambda(a, b) {
  a + b;
};
print(sum(1, 2));

наш парсер створить наступне AST, як об'єкт JavaScript:

{
  type: "prog",
  prog: [
    // first line:
    {
      type: "assign",
      operator: "=",
      left: { type: "var", value: "sum" },
      right: {
        type: "lambda",
        vars: [ "a", "b" ],
        body: {
          // the body should be a "prog", but because
          // it contains a single expression, our parser
          // reduces it to the expression itself.
          type: "binary",
          operator: "+",
          left: { type: "var", value: "a" },
          right: { type: "var", value: "b" }
        }
      }
    },
    // second line:
    {
      type: "call",
      func: { type: "var", value: "print" },
      args: [{
        type: "call",
        func: { type: "var", value: "sum" },
        args: [ { type: "num", value: 1 },
                { type: "num", value: 2 } ]
      }]
    }
  ]
}

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

  • Пишіть багато функцій і робіть їх невеликими. В кожній функції виконуйте одну річ і робіть це добре.

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

  • Не намагайтеся вгадати. Якщо ви не впевнені, як парсити щось, викидайте помилку і переконайтеся, що повідомлення про помилку містить місце помилки (рядок/стовпчик).


Щоб спростити код, я розбив його на три частини, які далі розділені на багато невеликих функцій:

  1. Потік введення символів

  2. Потік введення токенів (лексер)

  3. Парсер

Поділись своїми ідеями в новій публікації.
Ми чекаємо саме на твій довгочит!
Romashka
Romashka@Romashka

Створюю інтерпретатор Mash Src

65Прочитань
1Автори
1Читачі
На Друкарні з 16 березня

Більше від автора

  • λanguage: Як реалізувати мову програмування на JavaScript

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

    Теми цього довгочиту:

    Мова Программування
  • λanguage: Неформальний опис мови

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

    Теми цього довгочиту:

    Js

Вам також сподобається

Коментарі (0)

Підтримайте автора першим.
Напишіть коментар!

Вам також сподобається