代码之家  ›  专栏  ›  技术社区  ›  Cheeso

尝试为野牛/智者建立C语法

  •  11
  • Cheeso  · 技术社区  · 14 年前

    我以前从来没有做过野牛或智者。
    我怎么开始?

    我的真正目标是为C生成一个有效的明智/语义语法,使C能够在代码完成的情况下在Emacs中进行编辑,以及所有其他功能。 CEDET 好吃的东西。(对于那些不知道的人来说,智慧是一个EmacsLisp港口 GNU Bison ,这包括在CEDET中。 The Wisent 显然是欧洲野牛。而野牛,我认为,是一个关于源自 YACC . cedet是Emacs开发工具的集合。都赶上了?我不会尝试定义Emacs。)

    Microsoft为c_提供bnf语法,包括 language reference document . 我能把它翻译成一个.wy文件,成功编译 semantic-grammar-create-package .

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

    我想我应该退后一步,试着为一种非常简单的语言,一种只有几个关键词的玩具语言,创造一种明智的语法。只是为了获得一些经验。即便如此,这也是一个挑战。

    我看过文法fw的.info文档,而且很聪明,但是…不过,这些事情对我来说并不是很清楚,它们是如何工作的。

    所以

    Q1 在Emacs中调试一个明智的语法有什么建议吗?有没有办法在语法上运行一个“类似线头”的东西,以查明是否有未使用的规则,死胡同之类的东西?能够观察解析器的运行情况呢?有那样的吗?

    Q2 :有没有关于加快野牛/一般聪明的技巧?我所想的是一个工具,它可以让我对规则的工作方式有一些了解。它提供了一些透明度,而不是“它不起作用”的经验,我现在得到了明智的。

    Q3 我应该放弃并成为一个有机农场主,而不是继续与之抗争?


    PS:我知道cedet/semantic的contrib目录中现有的C语法。那东西管用,但是…它不支持最新的C规范,包括LINQ、分部类和方法、yield、匿名方法、对象初始值设定项等。另外,它主要是对一组C代码进行分析。它嗅出类和方法,然后诱饵出来。即使是前臂环也做得不太对。就目前而言,这是好事,但我希望看到情况好转。我要做的是使它成为最新的,并且扩展它来解析更多的C代码。

    2 回复  |  直到 11 年前
        1
  •  4
  •   Gabe Timothy Khouri    13 年前

    您可能需要查看semantic/wisent目录中的calc示例。它非常简单,还演示了如何使用%左右的功能。它将“执行”代码,而不是将其转换为标记。其他一些简单的语法包括cogre中的“dot”语法分析器和srecode中的srecode语法分析器。

    为了进行明智的调试,菜单中有一个冗长的标志,尽管老实说,我没有尝试过。在条目上也有明智的调试,允许您选择一个操作,该操作将导致Emacs调试器在该操作中停止,以便您可以看到值是什么。

    旧的“牛”解析器有一个调试模式,允许您单步执行规则,但它从未被移植到睿智。这是我写明智的解析器时非常想念的一个特性。

        2
  •  2
  •   Tobias    11 年前

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

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

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