写在前面:这本书相当于给没有什么编译原理基础又想要做一个玩具的程序猿做的一个很浅的科普。但它确确实实能走一遍流程。
昨天翻了翻《龙书》,实在受不了,对菜逼太不友好了。网上一搜,有人推荐这本书。好在手头有这个玩意儿,都快蒙灰了,就拉出来看看,简直感动要哭,真的是一步一步喂到嘴里,最重要的是它简单哈哈。话不多说,上教程。
准备工作 :linux
在windows当中安装虚拟机然后下载linux镜像的教程:
https://jingyan.baidu.com/article/c275f6ba07e269e33d756714.html
借用一下百度经验里面的。
VM10.0.6下载地址:https://pan.baidu.com/s/1eUcYyR4 密码:4fy3
ubuntu16.04下载地址 : http://cn.ubuntu.com/download/
两个命令 sudo apt install flex
sudo apt install bison
完成 flex和bison的安装后就可以开始写啦。
1、词法分析。
词法分析就是把一堆字符分析成为有意义的单词。对于四则计算器有单词就是数值以及加减乘除换行符的符号了。所以词法分析要做的事情就是把用户输入的词,选择有意义分析出来。
于是新建 mycalc.c文件
%{
#include
#include"y.tab.h"
int yywrap(void)
{
return 1;
}
%}
%%
"+" return ADD;
"-" return SUB;
"*" return MUL;
"/" return DIV;
"\n" return CR;
([1-9][0-9]*)|0|([0-9]+\.[0-9]+) {
double temp;
sscanf(yytext,"%lf",&temp);
yylval.double_value = temp;
return DOUBLE_LITERAL;
}
[ \t];
. {
fprintf(stderr,"lexical error.\n");
exit(1);
}
%%
————————————————————————我是分界线——————————————
%{
#include
#include"y.tab.h"
int yywrap(void)
{
return 1;
}
%}
词法分析器将会把这部分代码原模原样输出。
%%
"+" return ADD;
"-" return SUB;
"*" return MUL;
"/" return DIV;
"\n" return CR;
([1-9][0-9]*)|0|([0-9]+\.[0-9]+) {
double temp;
sscanf(yytext,"%lf",&temp);
yylval.double_value = temp;
return DOUBLE_LITERAL;
}
[ \t];
. {
fprintf(stderr,"lexical error.\n");
exit(1);
}
%%
筛选加减乘除反斜杠换行符以及使用正则表达式筛选整数和小数
2、语法分析
既然单词分析完了,就应该把单词连成有意义的短句
%{
#include
#include
#define YYDEBUG 1
%}
%union { /* 声明非终结符种类 */
int int_value;
double double_value;
}
%token DOUBLE_LITERAL
%token ADD SUB MUL DIV CR
%type expression term primary_expression /* 非终结符有这些 */
%%
line_list /* 多行的规则 */
: line
| line_list line
;
line /* 单行*/
: expression CR
{
printf(">>%lf\n",$1);
}
expression /* 表达式*/
: term
| expression ADD term
{
$$=$1 + $3;
}
| expression SUB term
{
$$=$1 - $3;
}
;
term /* 和项的规则 */
: primary_expression
| term MUL primary_expression
{
$$=$1 * $3;
}
| term DIV primary_expression
{
$$=$1 / $3;
}
;
primary_expression /* 一元表达式 */
: DOUBLE_LITERAL
;
%%
int yyerror( char const *str)
{
extern char *yytext;
fprintf(stderr,"parser error near %s\n",yytext);
return 0;
}
int main(void) /* 驱动程序*/
{
extern int yyparse(void);
extern FILE *yyin;
yyin = stdin;
if(yyparse()){
fprintf(stderr,"Error!Error! Error!\n");
exit(1);
}
}
————————————————————————我是分界线——————————————
执行命令
测试