Попытка построить С# грамматику для bison/wisent

Я никогда раньше не делал Bison или Wisent.
как я могу начать?

Моя реальная цель - создать рабочую грамматику Wisent/Semantic для С#, чтобы разрешить редактирование С# в emacs с завершением кода, а все остальные CEDET. (Для тех, кто не знает, Wisent - это порт emacs- lisp GNU Bison, который включен в CEDET. The Wisent, по-видимому, является европейским бизоном. И, как я понимаю, Bison - это игра-на-словах, происходящие из YACC И CEDET - это сборник Emacs Development Tools. Все догнал? Я не буду пытаться определить emacs.)

Microsoft предоставляет грамматику BNF для С#, включая все расширения LINQ, в справочном документе по языку. Я смог перевести это в .wy файл, который успешно компилируется с помощью semantic-grammar-create-package.

Но скомпилированная грамматика не работает. В некоторых случаях грамматика "находит" enum объявления, но не объявления class. Зачем? Я не знаю. Я не смог распознать атрибуты. Я не считаю, что "отладка" грамматики очень проста.

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

Я видел документы .info на грамматике fw и wisent, но... все же эти вещи не совсем разъясняют мне, как материал действительно работает.

Итак,

Q1: какие-либо советы по отладке разумной грамматики в emacs? Есть ли способ запустить "грамматику" в стиле "ворсинок", чтобы узнать, есть ли неиспользованные правила, такие тупики? Как насчет возможности наблюдать за парсером в действии? Что-нибудь подобное?

Q2: Какие-нибудь подсказки о том, чтобы приступить к скорости на bison/wisent вообще? Я думаю, что это инструмент, который позволит мне получить представление о том, как работают правила. Что-то, что обеспечивает некоторую прозрачность, вместо опыта "это не работает", я получаю сейчас с Wisent.

Q3: вместо того, чтобы продолжать бороться с этим, я должен отказаться и стать органическим фермером?


ps: Я знаю о существующей грамматике С# в каталоге contrib CEDET/semantic. Эта вещь работает, но... Она не поддерживает последнюю спецификацию С#, включая LINQ, частичные классы и методы, доходность, анонимные методы, инициализаторы объектов и т.д. Также он в основном воспроизводит партию кода С#. Он вынюхивает классы и методы, а затем выручает. Даже петли foreach сделаны не совсем правильно. Это хорошо, насколько это возможно, но я бы хотел, чтобы это было лучше. То, что я пытаюсь сделать, это сделать его текущим, а также расширить его, чтобы проанализировать больше кода С#.

Ответ 1

Вы можете посмотреть пример calc в семантической/wisent-директории. Это довольно просто, а также показывает, как использовать% left и% right. Он будет "исполнять" код, а не конвертировать его в теги. Некоторые другие простые грамматики включают "точечный" синтаксический анализатор в cogre и парсер srecode в srecode.

Для разумной отладки в меню есть флаг вербности, хотя, честно говоря, я не пробовал. Существует также wisent-debug-on-entry, который позволяет вам выбрать действие, которое заставит отладчик Emacs остановиться в этом действии, чтобы вы могли видеть, что это за значения.

У более старого "бычьего" парсера есть режим отладки, который позволяет вам пройти через правила, но он никогда не был перенесен на wisent. Это особенность, которую я очень пропустил, когда пишу убедительные парсеры.

Ответ 2

Что касается Q1: 1-й убедитесь, что на самом деле используется wisent parser:

(fetch-overload 'semantic-parse-stream)

должен возвращать wisent-parse-stream.

Запустите следующий фрагмент эскиза:

(easy-menu-add-item semantic-mode-map '(menu-bar cedet-menu) ["Wisent-Debug" wisent-debug-toggle :style toggle :selected (wisent-debug-active)])
(defun wisent-debug-active ()
  "Return non-nil if wisent debugging is active."
  (assoc 'wisent-parse-action-debug (ad-get-advice-info-field 'wisent-parse-action 'after)))
(defun wisent-debug-toggle ()
  "Install debugging of wisent-parser"
  (interactive)
  (if (wisent-debug-active)
      (ad-unadvise 'wisent-parse-action)
    (defadvice wisent-parse-action (after wisent-parse-action-debug activate)
      (princ (format "\ntoken:%S;\nactionList:%S;\nreturn:%S\n"
             (eval i)
             (eval al)
             (eval ad-return-value)) (get-buffer-create "*wisent-debug*"))))
  (let ((fileName (locate-file "semantic/wisent/wisent" load-path '(".el" ".el.gz")))
    fct found)
    (if fileName
    (with-current-buffer (find-file-noselect fileName)
      (goto-char (point-max))
      (while (progn
           (backward-list)
           (setq fct (sexp-at-point))
           (null
            (or
             (bobp)
             (and
              (listp fct)
              (eq 'defun (car fct))
              (setq found (eq 'wisent-parse (cadr fct))))))))
      (if found
          (eval fct)
        (error "Did not find wisent-parse.")))
      (error "Source file for semantic/wisent/wisent not found.")
      )))

Он создает новую запись Wisent-Debug в меню "Разработка". Щелчок по этой записи позволяет отладить отладку синтаксического анализатора. В следующий раз, когда вы перепрофилируете буфер с помощью wisent-parser, он выводит информацию об отладке в буфер * wisent debug *. Буфер * wisent debug * не отображается автоматически, но вы найдете его через буферное меню. Чтобы избежать наводнения * wisent debug *, вы должны отключить "Reparse when idle". Время от времени вы снимаете очистку буфера * wisent debug * с помощью erase-buffer.