Python源码编译
代码文件 calc.y
%require "3.0"
%language "c"
%{
#include <stdio.h>
#include <stdlib.h>
int yylex();
void yyerror (const char* const s);
%}
%union {
int intval;
}
%token ADD SUB MUL DIV NUMBER
%token LBRAC RBRAC
%token ENDLINE UNKNOWN
%type <intval> NUMBER
%type <intval> line expr term factor
%%
top : line {};
top : top line {};
line : expr ENDLINE {printf("= %d\n", $1);};
line : ENDLINE {};
expr : expr ADD term {$$ = $1 + $3;};
expr : expr SUB term {$$ = $1 - $3;};
expr : term {$$ = $1;};
term : term MUL factor {$$ = $1 * $3;};
term : term DIV factor {$$ = $1 / $3;};
term : factor {$$ = $1;};
factor : NUMBER {$$ = $1;};
factor : LBRAC expr RBRAC {$$ = $2;};
%%
int yylex()
{
int c = fgetc(stdin);
switch (c) {
case EOF:
return 0;
case '+':
return ADD;
case '-':
return SUB;
case '*': case 'x':
return MUL;
case '/':
return DIV;
case '(':
return LBRAC;
case ')':
return RBRAC;
case ' ': case '\t':
return yylex(); // 递归
case '\r': case '\n':
return ENDLINE;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
{
int dig = 0;
do {
dig = dig * 10 + c - '0';
c = fgetc(stdin);
} while (c >= '0' && c <= '9');
ungetc(c, stdin);
yylval.intval = dig;
}
return NUMBER;
default:
return UNKNOWN;
}
return 0;
}
void yyerror(const char* const err)
{
// 遇到无法识别的,一行都废掉
char *line = (char*)malloc(8192);
ungetc(' ', stdin);
fgets(line, 8192, stdin);
free(line);
fprintf(stderr, "Parse error: %s\n", err);
}
int main(int argc, char** argv)
{
for (;;) {
yyparse();
}
return 0;
}
没安装bison的需要先安装bison
yum -y install bison
编译前要先用 bison 生成代码
[root@centos test]# bison -o calc.c -y calc.y
[root@centos test]# gcc -o calc calc.c
[root@centos test]# ./calc
(8 - 5 * 2 + 3) * 17 - 21 / 3 -5
= 5