试图为bison / wisent构建一个C#语法

时间:2010-06-04 20:34:06

标签: c# emacs yacc bison

我以前从未做过Bison或Wisent 我该如何开始?

我的真正目标是为C#生成一个有效的Wisent / Semantic语法,允许在带有代码完成的emacs中编辑C#,以及所有其他CEDET个好东西。 (对于那些不知道的人,Wisent是GNU Bison的emacs-lisp端口,它被包含在CEDET中。The Wisent显然是欧洲野牛。而Bison,我认为它是一个游戏-on-words来自YACC。而CEDET是Emacs开发工具的集合。所有人都赶上了?我不打算尝试定义emacs。)

Microsoft在language reference document中为C#提供了BNF语法,包括所有LINQ扩展。我能够将其转换为.wy文件,该文件与semantic-grammar-create-package成功编译。

但编译后的语法并没有“起作用”。在某些情况下,语法“找到”enum声明,但不是class声明。为什么?我不知道。我无法识别属性。 我发现语法的“调试”并不容易。

我以为我会退后一步,尝试为一种简单易懂的语言制作一种明智的语法,这种语言只有几个关键词。只是为了获得一些经验。即便如此,这也是一个挑战。

我已经看过关于语法fw的.info文档,并且很明智,但是......仍然有些事情并没有真正为我澄清,这些东西是如何真正起作用的。

所以

Q1 :有关在emacs中调试明智语法的任何提示吗?有没有办法在语法上运行一个“类似lint”的东西来找出是否有未使用的规则,这样的死胡同?如何能够观察解析器的运行情况呢?有这样的吗?

Q2 :关于加速野牛/一般情况的任何提示?我正在考虑的是一种工具,可以让我深入了解规则的运作方式。提供一些透明度的东西,而不是“我没有工作”的经验,我现在正在使用Wisent。

Q3 :我应该放弃并成为一名有机农民,而不是继续打击这一点吗?


ps:我知道CEDET / semantic的contrib目录中现有的C#语法。这件事有效,但是......它不支持最新的C#规范,包括LINQ,部分类和方法,yield,匿名方法,对象初始化器等等。此外,它主要解析一堆C#代码。它嗅出了类和方法,然后挽救了。即使是foreach循环也没有做得很好。尽管它很好,但我希望看到它更好。我正在尝试做的是使它成为当前的,并且还扩展它以解析更多的C#代码。

2 个答案:

答案 0 :(得分:4)

您可能希望查看语义/明智目录中的calc示例。它非常简单,还展示了如何使用%left和%right功能。它将“执行”代码而不是将其转换为标记。其他一些简单的语法包括cogre中的'dot'解析器和srecode中的srecode解析器。

对于明智的调试,菜单中有一个详细的标志,但说实话,我没有尝试过。还有一个明智的调试输入,它允许您选择一个动作,使Emacs调试器在该动作中停止,这样您就可以看到值是什么。

较旧的“牛”解析器具有允许您逐步执行规则的调试模式,但它从未被移植到合适的位置。这是我写的明智的解析器时我非常想念的一个功能。

答案 1 :(得分:2)

关于Q1: 首先确保实际使用了明智的解析器:

(fetch-overload 'semantic-parse-stream)

应该返回wisent-parse-stream

运行以下elisp-snippet:

(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.")
      )))

它在Development-menu中创建一个新的Wisent-Debug条目。单击此条目可切换明智解析器的调试。下次使用wisent-parser重新分析缓冲区时,它会将调试信息输出到缓冲区* wisent debug *。缓冲区*明智的调试*不会自动显示,但您可以通过缓冲区菜单找到它。 为了避免*明智的调试*泛滥,你应该禁用“空闲时重新分析”。 有时你会用擦除缓冲区清除缓冲区*明智的调试*。