Подтвердить что ты не робот

CFG/PEG используется для завершения кода?

Мне интересно, можно ли использовать грамматику CFG или PEG в качестве основы для завершения кода напрямую без изменений. Я слышал, что завершение кода в IDE иногда обрабатывается и массируется или даже жестко закодировано, чтобы он работал лучше.

Я хочу скопировать код на небольшой DSL, поэтому я полностью понимаю, что грамматика не может помочь системе завершения кода со знанием библиотечных функций и т.д.

Насколько мне известно, сам синтаксический анализатор должен, по крайней мере, предоставить систему для запроса того, что ожидает следующего.

В частности, меня интересует решение для завершения JavaScript-кода, используя peg.js или jison

4b9b3361

Ответ 1

Довольно легко создать редактор Javascript с завершением кода из грамматики ПЭГ. Я бы описал, как это сделать с помощью PEG.js. Вам необходимо расширить свою грамматику с помощью некоторых слабых правил синтаксического анализа, которые позволят предоставить предложения, когда нарушены предыдущие утверждения. Эти ленивые правила нужно обрабатывать условно или вам понадобятся две отдельные грамматики - одна для анализа источника и вторая для завершения кода. Вы можете сохранить одну грамматику с помощью предикатов Javascript (доступно в PEG.js). Это выглядит как &{return laxParsing}, и это вызывает обработку всего правила, если флаг laxParsing равен true. Вы можете легко переключаться между слабым и строгим синтаксическим разбором, устанавливая внутренний флаг парсера.

Чтобы предоставить предложения пользователю легко, вы должны модифицировать слегка сгенерированный парсер PEG.js (версия 0.5) для получения в структуре структуры ошибки синтаксического анализа (рядом с столбцом и строкой) и список ожиданий (помимо сообщения об ошибке). Вы можете скопировать подготовленный фрагмент из https://gist.github.com/1281239.

Когда у вас есть парсер, вы можете прикрепить его в редакторе, например, нажатие CTRL + SPACE. Когда они нажимаются в текстовом источнике, вам нужно поставить специальный непарный знак вместо курсора (чтобы вызвать ошибку синтаксического анализа) и запустить парсер в слабом режиме. Затем вы получите сообщение об ошибке со списком предложений.

Некоторые из предложений являются не только синтаксисом, но и определяют ссылки (например, сущности, переменные). Вы можете инициировать их поиск, когда определенное ожидание найдено (например, VariableName). Вы можете предоставить список, разыгрывая один и тот же источник в другом режиме разного анализа (фильтрация только имен переменных).

Для рабочего примера и источника этого подхода вы можете проверить https://github.com/mstefaniuk/Concrete-Freetext.

Ответ 2

PEG.js дает вам довольно много контекста, когда он генерирует SyntaxError. Например, если у вас есть грамматика для SQL и напишите ей что-то вроде:

FOO > 10 A

Тогда PEG.js вернет это:

{
  "message": "Expected \"AND\", \"ORDER BY\" or end of input but \"A\" found.",
  "expected": [
    {
      "type": "literal",
      "value": "AND",
      "description": "\"AND\""
    },
    {
      "type": "literal",
      "value": "ORDER BY",
      "description": "\"ORDER BY\""
    },
    {
      "type": "end",
      "description": "end of input"
    }
  ],
  "found": "A",
  "offset": 9,
  "line": 1,
  "column": 10,
  "name": "SyntaxError"
}

Говорят, что он разбирал символы 0-9 строки ( "FOO > 10" ), но затем обнаружил неожиданный токен на символе 10. И он дает вам список следующих токенов, которые он ожидал: FOO > 10 AND, FOO > 10 ORDER BY, FOO > 10. Если вы примените их к действительной части запроса, вы получите хороший набор возможных завершений:

function getCompletions(pegParse, text) {
  var parsedText = pegParse(text);
  var completions = [];
  if (parsedText.expected) {
    var start = text.substr(0, parsedText.offset);
    parsedText.expected.forEach(function(expected) {
      if (expected.type != 'literal') return;
      var completion = start + expected.value;
      if (completion.substr(0, text.length) == text) {
        completions.push(completion);
      }
    });
  }
  return completions;
}

Это довольно упрощенно: реальный автозаполнение будет соответствовать не только литералам, но и каким-то образом использовать контекст, недоступный для грамматики, например. список аргументов функции, вызываемой пользователем.