如何制作函数式语言编译器

时间:2013-05-23 00:30:04

标签: c compiler-construction functional-programming ebnf parse-tree



我正在研究为夏季项目编写语言和编译器,并且很难找到有关如何使用解析树或BNF / EBNF来编写编译器的信息。总体目标是编写一个将简化的函数式语言语法解析为c的编译器。我目前正计划用c语言编写这个编译器,但如果有人认为这是一个更好的主意,我不介意在别的东西上做。 (我确实想用手工做,不使用像LEX这样的工具)

例如,如果我想创建语言ADD并将其语法定义为(+ 3 4),则很容易为其生成EBNF:

    Program   -> {Function}
    Function  -> Operator Integer Integer
    Operator  -> +
    Integer   -> Digit {Digit}
    Digit     -> 0|1|2|3|4|5|6|7|8|9 

并且更容易制作解析树:

         Function
             |
     -------------------
     |       |         |
  Operator  Integer  Integer

但你怎么样:

  1. 用C
  2. 表示EBNF或解析树
  3. 使用此数据获取有效的C代码
  4. 我觉得如果我能看到一个非常简单的工作示例,那就足以让我开始朝着正确的方向前进。我有一种感觉,你们很多人会建议我阅读Dragon Book(似乎是编译器的标准资源),所以我想告诉你它已经订购并发货了。

    提前感谢您可以获得的任何亮光!

    -vikingsheepman

1 个答案:

答案 0 :(得分:1)

从龙书中,一种表示EBNF的方法是使用枚举来对节点的类型进行分组。例如:

typedef enum { StmtK , ExpK} NodeKind;
typedef enum { IfK, AssignK, ... } StmtKind;
typedef enum { OpK, ConstK} ExpKind;

typedef enum { Void, Integer } ExpType;

以这种方式定义树的节点

typedef struct treeNode {
    struct treeNode * child[MAXCHILDREN];
    struct treeNode * sibling;
    int lineNo;
    NodeKind nodekind;
    union { StmtKind stmt; ExpKind exp; } kind; //Use union to save space
    union { TokenType op;
            int val;
            char * name; } attr;
    ExpType type; //To verify expression types
} TreeNode;

生成C代码还有很长的路要走,但实质上你需要对生成的树(语法,语义......)进行一些检查,然后生成代码。怎么做取决于你正在构建的编译器的类型(一个或多个传递)。如果您订购了龙书,肯定会在那里找到所有这些。