Попытка построить грамматику C # для бизона / зубра - PullRequest
11 голосов
/ 05 июня 2010

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

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

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

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

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

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

So

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

Q2 : Есть ли у вас какие-либо советы по поводу скорости на зубре / зубре в целом? Я думаю, что это инструмент, который позволит мне понять, как работают правила. Что-то, что обеспечивает некоторую прозрачность, вместо опыта «это не сработало», которое я получаю сейчас с Wisent.

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


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

Ответы [ 2 ]

4 голосов
/ 05 июня 2010

Возможно, вы захотите посмотреть пример calc в каталоге semantic / wisent. Это довольно просто, а также показывает, как использовать функции% left и% right. Он будет «исполнять» код, а не преобразовывать его в теги. Некоторые другие простые грамматики включают парсер 'dot' в cogre и парсер srecode в srecode.

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

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

2 голосов
/ 04 сентября 2013

Относительно Q1: 1-й убедитесь, что действительно используется wisent parser:

(fetch-overload 'semantic-parse-stream)

должен вернуть wisent-parse-stream.

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

(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 синтаксического анализатора. В следующий раз, когда вы повторно анализируете буфер с помощью wisent-parser, он выводит отладочную информацию в буфер * wisent debug *. Буфер * wisent debug * не отображается автоматически, но вы можете найти его через меню буфера. Чтобы избежать переполнения * wisent debug *, вы должны отключить функцию «Повторная обработка при простое». Время от времени вы должны очищать буфер * wisent debug * с помощью erase-buffer.

...