编译[3]四则运算语言

42 阅读2分钟

概述

继续利用黑盒工具实现我们的功能。上一篇实现了命令行执行单行四则运算,这一篇改良一下,不用命令行,把多个四则运算写在一个文件上,直接读文档解析执行输出所有运算结果。那也算是做出了一门编程语言,叫四则运算语言。

因为四则运算的功能已经做好,只要修改一下输入输出逻辑就好。

整体分支代码在这里,其实就是另一个分支。

修改

首先修改入口文件main.c

之前通过命令行输入,所以输入来自标准输入流

yyin = stdin;

新的输入来自一个文件,所以执行时需要输入文件名。先定义一个文件指针

FILE *fp;

再要判断命令执行时有没有输入文件名,所以要判断参数个数是否是2,不是2就报错

argc != 2

拿到文件名以读方式打开

fp = fopen(argv[1], "r");

最后把文件指针赋值给yyin,就换了一种输入方式

yyin = fp;

main方法代码如下,新的完整文件在这里

int main(int argc, char **argv) {
    extern int yyparse(void);
    extern FILE *yyin;
    FILE *fp;

    if (argc != 2) {
        fprintf(stderr, "usage:%s filename", argv[0]);
        exit(1);
    }

    fp = fopen(argv[1], "r");
    if (fp == NULL) {
        fprintf(stderr, "%s not found.\n", argv[1]);
        exit(1);
    }

    yyin = fp;
    if (yyparse()) {
        fprintf(stderr, "Error ! \n");
        exit(1);
    }
}

修改词法分析内容

修改nl.l文件,新的完整代码在这里

要多加一个分号(';')token,用来表示一个四则语句的结束。

";" return SEMICOLON;

然后把换行符那个单独识别的token去掉,原来是这行,去掉

"\n" return CR;

把换行符放到空白符号判断里面,让它在分析的时候直接被忽略,中括号是正则表达式的语法,识别到这三个符号任意一个之后,什么都不做,所以后面直接分号结束

[ \t\n] ;

修改语法分析内容

修改nl.y文件,新的完整代码在这里

token定义加上分号的token名SEMICOLON,去掉之前换行的token名CR

%token SEMICOLON ADD SUB MUL DIV LP RP MOD

语法规则加上语句列表(statement_list)的定义,语句列表可以是单个语句(statement),也可以是另一个列表后面跟一个语句,其实就是多个语句

statement_list
    : statement
    | statement_list statement
    ;

还要有语句的定义,定义成表达式(expression)后面跟一个分号(SEMICOLON),每当解析到一个语句时,计算其中的表达式,并打印它的值

statement
    : expression SEMICOLON
    {
        NL_Value v = nl_eval_expression($1);
        nl_print_value(&v);
    }
    ;

而表达式的定义就改成了单个加法表达式

expression
    : add_expression
    ;

其它地方都没有变。这样就修改完毕了,录个屏看看效果。要是能放视频就太好了。

四则语言执行.gif

结束

这篇十分短,但目的达到了,下一篇,尝试支持变量,用变量存储一些值,让我们可以复用一些值。