Giter Site home page Giter Site logo

buaa-simple-c0-compiler's Introduction

Simple-C0-Compiler

一个C0语言(C语言的一个子集)的简单编译器,包含优化,目标代码是MIPS汇编语言(使用Mars运行)

这样写编译器

这个编译器是写的很烂的,不要学习,虽然靠着一些技巧,在编译优化方面,能跑的比较快。

主要的缺点就是没有实现抽象语法树(AST),且中间代码设计很差,与llvm ir有很大的差距

所以,参考llvm官方的基础教程,我对课程的小编译器的设计建议是:

  • 分离语法分析与语义分析,也就是一定要有AST树来表示语法结构,方便差查错和代码翻译,并且可以提高扩展性
  • 对于中间代码,可以参考llvm ir的设计思路,抽象出 模块--函数--基本块--语句 这几个层次,方便中间代码向目标代码的翻译,与优化
  • 优化部分,写成不同的优化pass函数,方便排查错误,解耦代码
  • 对于AST,设计一个公共的接口/父类,所有的各类AST继承这个类,通过统一的接口(虚函数)调用
  • 静态单一赋值SSA可以考虑实现
  • 前端可以参考llvm的官方教程的实现方法 http://llvm.org/docs/tutorial/MyFirstLanguageFrontend/index.html 构造lexer, parser, AST, codegen
  • 后端设计不再赘述

关于运算表达式的算符优先级的扩展

用递归下降来间接体现算符优先级,在运算符较少的情况下显然是没问题的。

而出于扩展性考虑,下面推荐一种基于实现优先级定义的表达式翻译方法。

参考自LLVM官方文档,对于更多运算符可自行扩展。

static std::unique_ptr<ExprAST> ParseBinOpRHS(int ExprPrec,
                                              std::unique_ptr<ExprAST> LHS) {
  // If this is a binop, find its precedence.
  while (true) {
    int TokPrec = GetTokPrecedence();

    // If this is a binop that binds at least as tightly as the current binop,
    // consume it, otherwise we are done.
    if (TokPrec < ExprPrec)
      return LHS;

    // Okay, we know this is a binop.
    int BinOp = CurTok;
    getNextToken(); // eat binop

    // Parse the primary expression after the binary operator.
    auto RHS = ParsePrimary();
    if (!RHS)
      return nullptr;

    // If BinOp binds less tightly with RHS than the operator after RHS, let
    // the pending operator take RHS as its LHS.
    int NextPrec = GetTokPrecedence();
    if (TokPrec < NextPrec) {
      RHS = ParseBinOpRHS(TokPrec + 1, std::move(RHS));
      if (!RHS)
        return nullptr;
    }

    // Merge LHS/RHS.
    LHS =
        std::make_unique<BinaryExprAST>(BinOp, std::move(LHS), std::move(RHS));
  }
}

int main() {
  // Install standard binary operators.
  // 1 is lowest precedence.
  BinopPrecedence['<'] = 10;
  BinopPrecedence['+'] = 20;
  BinopPrecedence['-'] = 20;
  BinopPrecedence['*'] = 40; // highest.
  // ......
  // ......
}

文法

<加法运算符> ::= +|-
<乘法运算符>  ::= *|/
<关系运算符>  ::=  <|<=|>|>=|!=|==
<字母>   ::= _|a|...|z|A|...|Z
<数字>   ::= 0|<非零数字>
<非零数字>  ::= 1|...|9
<字符>    ::=  '<加法运算符>'|'<乘法运算符>'|'<字母>'|'<数字>'
<字符串>   ::=  "{十进制编码为32,33,35-126的ASCII字符}"
<程序>    ::= [<常量说明>][<变量说明>]{<有返回值函数定义>|<无返回值函数定义>}<主函数>
<常量说明> ::=  const<常量定义>;{ const<常量定义>;}
<常量定义>   ::=   int<标识符>=<整数>{,<标识符>=<整数>}
                  | char<标识符>=<字符>{,<标识符>=<字符>}
<无符号整数>  ::= <非零数字>{<数字>}| 0
<整数>        ::= [+|-]<无符号整数>
<标识符>    ::=  <字母>{<字母>|<数字>}
<声明头部>   ::=  int<标识符> |char<标识符>
<变量说明>  ::= <变量定义>;{<变量定义>;}
<变量定义>  ::= <类型标识符>(<标识符>|<标识符>'['<无符号整数>']'){,(<标识符>|<标识符>'['<无符号整数>']' )} 
                 //<无符号整数>表示数组元素的个数,其值需大于0
<类型标识符>      ::=  int | char
<有返回值函数定义>  ::=  <声明头部>'('<参数表>')' '{'<复合语句>'}'
<无返回值函数定义>  ::= void<标识符>'('<参数表>')''{'<复合语句>'}'
<复合语句>   ::=  [<常量说明>][<变量说明>]<语句列>
<参数表>    ::=  <类型标识符><标识符>{,<类型标识符><标识符>}| <空>
<主函数>    ::= void main'('')''{'<复合语句>'}'
<表达式>    ::= [+|-]<项>{<加法运算符><项>}   //[+|-]只作用于第一个<项>
<项>     ::= <因子>{<乘法运算符><因子>}
<因子>    ::= <标识符>|<标识符>'['<表达式>']'|'('<表达式>')'|<整数>|<字符>|<有返回值函数调用语句>         
<语句>    ::= <条件语句>|<循环语句>| '{'<语句列>'}'| <有返回值函数调用语句>;|<无返回值函数调用语句>;|<赋值语句>;|<读语句>;|<写语句>;|<空>;|<返回语句>;
<赋值语句>   ::=  <标识符>=<表达式>|<标识符>'['<表达式>']'=<表达式>
<条件语句>  ::= if '('<条件>')'<语句>[else<语句>]
<条件>    ::=  <表达式><关系运算符><表达式>|<表达式> //表达式为0条件为假,否则为真
<循环语句>   ::=  while '('<条件>')'<语句>| do<语句>while '('<条件>')' |for'('<标识符>=<表达式>;<条件>;<标识符>=<标识符>(+|-)<步长>')'<语句>
<步长>::= <无符号整数>  
<有返回值函数调用语句> ::= <标识符>'('<值参数表>')'
<无返回值函数调用语句> ::= <标识符>'('<值参数表>')'
<值参数表>   ::= <表达式>{,<表达式>}|<空>
<语句列>   ::= {<语句>}
<读语句>    ::=  scanf '('<标识符>{,<标识符>}')'
<写语句>    ::= printf '(' <字符串>,<表达式> ')'| printf '('<字符串> ')'| printf '('<表达式>')'
<返回语句>   ::=  return['('<表达式>')']

MARS模拟器

MARS is a lightweight interactive development environment (IDE) for programming in MIPS assembly language, intended for educational-level use with Patterson and Hennessy’s Computer Organization and Design.

http://courses.missouristate.edu/kenvollmar/mars/

项目的编译与运行

clang与vs2019,C++17及以上

buaa-simple-c0-compiler's People

Contributors

tsemo4917 avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar

Forkers

mmt-at sikikok6

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.