美文网首页程序员C/C++知识点
自己动手制作C 语言编译器(7):语句

自己动手制作C 语言编译器(7):语句

作者: Python编程导师 | 来源:发表于2019-01-15 10:42 被阅读1次

    整个编译器还剩下最后两个部分:语句和表达式的解析。它们的内容比较多,主要涉及如何将语句和表达式编译成汇编代码。这章讲解语句的解析,相对于表达式来说它还是较为容易的。

    语句

    C 语言区分“语句”(statement)和“表达式”(expression)两个概念。简单地说,可以认为语句就是表达式加上末尾的分号。

    在我们的编译器中共识别 6 种语句:

    1.if (...) <statement> [else <statement>]

    2.while (...) <statement>

    3.{ <statement> }

    4.return xxx;

    5.<empty statement>;

    6.expression;(expression end with semicolon)

    它们的语法分析都相对容易,重要的是去理解如何将这些语句编译成汇编代码,下面我们逐一解释。如果想一起交流的可以加这个群:941636044 ,有什么问题可以群里面交流,群里面也有一些方便学习C语言C++编程的资料可以给你利用哦!

    IF 语句

    IF 语句的作用是跳转,跟据条件表达式决定跳转的位置。我们看看下面的伪代码:

    if (...) <statement> [else <statement>]

      if (<cond>)                   <cond>

                                    JZ a

        <true_statement>   ===>     <true_statement>

      else:                         JMP b

    a:                           a:

        <false_statement>           <false_statement>

    b:                           b:

    对应的汇编代码流程为:

    执行条件表达式<cond>。

    如果条件失败,则跳转到a的位置,执行else语句。这里else语句是可以省略的,此时a和b都指向 IF 语句后方的代码。

    因为汇编代码是顺序排列的,所以如果执行了true_statement,为了防止因为顺序排列而执行了false_statement,所以需要无条件跳转JMP b。

    对应的 C 代码如下:

    if (token == If) {

        match(If);

        match('(');

        expression(Assign);  // parse condition

        match(')');

        *++text = JZ;

        b = ++text;

        statement();         // parse statement

        if (token == Else) { // parse else

            match(Else);

            // emit code for JMP B

            *b = (int)(text + 3);

            *++text = JMP;

            b = ++text;

            statement();

        }

        *b = (int)(text + 1);

    }

    While 语句

    While 语句比 If 语句简单,它对应的汇编代码如下:

    a:                     a:

       while (<cond>)        <cond>

                             JZ b

        <statement>          <statement>

                             JMP a

    b:                     b:

    没有什么值得说明的内容,它的 C 代码如下:

    else if (token == While) {

        match(While);

        a = text + 1;

        match('(');

        expression(Assign);

        match(')');

        *++text = JZ;

        b = ++text;

        statement();

        *++text = JMP;

        *++text = (int)a;

        *b = (int)(text + 1);

    }

    Return 语句

    Return 唯一特殊的地方是:一旦遇到了 Return 语句,则意味着函数要退出了,所以需要生成汇编代码LEV来表示退出。

    else if (token == Return) {

        // return [expression];

        match(Return);

        if (token != ';') {

            expression(Assign);

        }

        match(';');

        // emit code for return

        *++text = LEV;

    }

    其它语句

    其它语句并不直接生成汇编代码,所以不多做说明,代码如下:

    else if (token == '{') {

        // { <statement> ... }

        match('{');

        while (token != '}') {

            statement();

        }

        match('}');

    }

    else if (token == ';') {

        // empty statement

        match(';');

    }

    else {

        // a = b; or function_call();

        expression(Assign);

        match(';');

    }

    小结

    本章讲解了如何将语句编译成汇编代码,内容相对容易一些,关键就是去理解汇编代码的执行原理。

    同时值得一提的是,编译器的语法分析部分其实是很简单的,而真正的难点是如何在语法分析时收集足够多的信息,最终把源代码转换成目标代码(汇编)。我认为这也是初学者实现编译器的一大难点,往往比词法分析/语法分析更困难。

    所以建议如果没有学过汇编,可以学习学习,它本身不难,但对理解计算机的原理有很大帮助。如果想一起交流的可以加这个群:941636044 ,有什么问题可以群里面交流,群里面也有一些方便学习C语言C++编程的资料可以给你利用哦!

    相关文章

      网友评论

        本文标题:自己动手制作C 语言编译器(7):语句

        本文链接:https://www.haomeiwen.com/subject/ozkddqtx.html