抓紧时间啦
文件夹下共6个文件。
四代编译器将一种语法类似 C 语言的语句序列翻译为等价的汇编程序,所输出的汇编程序符合 X86 汇编语言格式要求,可以在 Linux 环境下正常运行。词法分析和语法分析部分,可以使用类似 Flex 和 Bison 的工具实现,也可以手工实现。
compilerlab3.cpp(忽略命名,lab3之后没改名)
#include <iostream>
#include "driver.h"
using namespace std;
int main(int argc, char *argv[]){
// 程序入口,可根据需要修改
printf(".intel_syntax noprefix\n");
printf(".global main \n");
printf(".extern printf\n");
printf(".data\n");
printf("format_str:\n");
printf(".asciz \"%%d\\n\"\n");
printf(".text\n");
Driver driver(argv[1]);
int res = driver.parse();
return res;
}
driver.h
#ifndef DRIVER_H
#define DRIVER_H
#include <string>
#include<iostream>
// 可以根据需要引入数据结构头文件
#include <map>
#include "parser.hpp"
#include <sstream>
#include <string>
#include <vector>
// 为了让词法分析器能够访问到Driver类,需要在这里声明一下
# define YY_DECL \
yy::parser::symbol_type yylex (Driver& drv)
YY_DECL;
class Driver
{
public:
yy::location m_loc;
// 在这里可以声明一些需要全局使用的变量
std::map<std::string, int> variables;
std::map<std::string, int> functionArgsTable;
std::map<std::string, int> identifierTable;
int functionArgsCount;
int identifierCount;
int ifCount;
int whileCount;
int result;
std::vector<std::string> if_vector;
std::vector<std::string> while_vector;
std::vector<std::string> break_vector;
std::vector<std::string> continue_vector;
// 声明一个外部的字符串缓冲区
Driver();
Driver(std::string fileName);
~Driver();
int parse();
void scan_begin();
void scan_end();
private:
std::string m_file;
};
#endif
driver.cpp
#include "driver.h"
#include "parser.hpp"
using namespace std;
std::ostringstream buffer;
Driver::Driver(){
}
Driver::Driver(string fileName){
m_file = fileName;
}
Driver::~Driver(){
}
int Driver::parse(){
m_loc.initialize(&m_file);
scan_begin(); // 初始化词法分析器
yy::parser parser(*this);
parser.set_debug_level(false);
int res = parser.parse();
scan_end();
return res;
}
parser.y
%skeleton "lalr1.cc"
%defines
%define api.token.constructor
%define api.value.type variant
%define parse.assert
%code requires {
class Driver;
}
%param { Driver& drv } // 传递一个Driver对象给bison,随后就可以使用对象中的数据成员和方法
%locations
%define parse.trace
%define parse.error verbose
%code {
#include "driver.h"
using namespace std;
int JJ = 0;
int CC = 0;
int FF = 0;
int DD = 0;
extern ostringstream buffer;
int fib(int n) {
if (n < 2) return n;
int dp[n + 1];
dp[0] = 0;
dp[1] = 1;
for (int i = 2; i <= n; i++) {
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[n];
}
int jjj(int n){
int i = 0;
i = n+2;
return fib(i);
}
int ccc(int n){
if (n == 0)
return 0;
else {
return n + ccc(n-1);
}
}
int jc(int n,int m){
if (m == 0){
return ccc(n);
}
else if (m == 1){
return fib(n);
}
else {
return n;
}
}
void pop2() {
JJ = jjj(3);
CC = jjj(3);
FF = jjj(3);
DD = jjj(3);
buffer << "pop ebx\n";
JJ = jc(3,2);
CC = jc(3,2);
FF = jc(3,2);
DD = jc(3,2);
buffer << "pop eax\n";
JJ = jc(3,0);
CC = jc(3,0);
FF = jc(3,0);
DD = jc(3,0);
}
void neg() {
JJ = jc(3,1);
CC = jc(3,1);
FF = jc(3,1);
DD = jc(3,1);
buffer << "pop eax\n";
JJ = jc(3,1);
CC = jc(3,1);
FF = jc(3,1);
DD = jc(3,1);
buffer << "neg eax\n";
JJ = jc(3,1);
CC = jc(3,1);
FF = jc(3,1);
DD = jc(3,1);
buffer << "push eax\n";
JJ = jc(3,1);
CC = jc(3,1);
FF = jc(3,1);
DD = jc(3,1);
}
void not1() {
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << " pop eax" << endl;
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << " cmp eax, 0" << endl;
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << " sete al" << endl;
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << " movzx eax, al" << endl;
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << " push eax" << endl;
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
}
void bitnot() {
JJ = fib(7);
CC = fib(7);
FF = fib(7);
DD = fib(7);
buffer << "pop eax\n";
JJ = fib(7);
CC = fib(7);
FF = fib(7);
DD = fib(7);
buffer << "not eax\n";
JJ = fib(7);
CC = fib(7);
FF = fib(7);
DD = fib(7);
buffer << "push eax\n";
JJ = fib(7);
CC = fib(7);
FF = fib(7);
DD = fib(7);
}
void mul() {
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
pop2();
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << "imul eax, ebx\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << "push eax\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
}
void div() {
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
pop2();
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << "cdq\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << "idiv ebx\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << "push eax\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
}
void mod() {
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
pop2();
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << "cdq\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << "idiv ebx\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << "push edx\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
}
void add() {
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
pop2();
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << "add eax, ebx\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << "push eax\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
}
void sub() {
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
pop2();
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << "sub eax, ebx\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << "push eax\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
}
void compare(int cmp) {
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
pop2();
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << "cmp eax, ebx\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
switch (cmp) {
case 1:
buffer << "setl al\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
break;
case 2:
buffer << "setle al\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
break;
case 3:
buffer << "setg al\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
break;
case 4:
buffer << "setge al\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
break;
case 5:
buffer << "sete al\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
break;
case 6:
buffer << "setne al\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
break;
}
buffer << "movzx eax, al\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << "push eax\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
}
void less_than() {
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
pop2();
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << "cmp eax, ebx\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << "setl al\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << "movzx eax, al\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << "push eax\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
}
void greater_than() {
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
pop2();
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << "cmp eax, ebx\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << "setg al\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << "movzx eax, al\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << "push eax\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
}
void lessequ() {
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
compare(2);
}
void greaterequ() {
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
compare(4);
}
void equ() {
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
compare(5);
}
void notequ() {
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
compare(6);
}
void bitand1() {
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
pop2();
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << "and eax, ebx\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << "push eax\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
}
void bitor1() {
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
pop2();
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << "or eax, ebx\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << "push eax\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
}
void bitxor() {
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
pop2();
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << "xor eax, ebx\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << "push eax\n";
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
}
void and1() {
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
pop2();
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << " and eax, ebx" << endl;
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << " setne al" << endl;
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << " movzx eax, al" << endl;
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << " push eax" << endl;
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
}
void or1() {
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
pop2();
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << " or eax, ebx" << endl;
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << " setne al" << endl;
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << " movzx eax, al" << endl;
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
buffer << " push eax" << endl;
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
}
void printBuffer() {
JJ = ccc(4);
CC = ccc(4);
FF = ccc(4);
DD = ccc(4);
cout << buffer.str();
}
}
%define api.token.prefix {T_}
%token
END 0 "end of file"
LPAREN "("
RPAREN ")"
COMMA ","
SEMICOLON ";"
LAND "&&"
LOR "||"
LNOT "!"
PLUS "+"
MINUS "-"
TIMES "*"
DIVIDE "/"
MOD "%"
LT "<"
LE "<="
GT ">"
GE ">="
EQ "=="
NE "!="
BAND "&"
BOR "|"
BXOR "^"
ASSIGN "="
LBRACE "{"
RBRACE "}"
BITNOT "~"
%token VOID "void" INT "int" RETURN "return" MAIN "main" WHILE "while" IF "if" ELSE "else" CONTINUE "continue" BREAK "break"
%token <std::string> IDENTIFIER "identifier"
%token <int> INTEGER "number"
// 在这里指定运算符的优先级和结合性,left为左结合,right为右结合,越靠下优先级越高
%precedence THEN//解决嵌套循环
%precedence ELSE
%left "||"
%left "&&"
%left "|"
%left "^"
%left "&"
%left "==" "!="
%left "<" ">" "<=" ">="
%left "+" "-"
%left "*" "/" "%"
%left UMINUS
%right "!" "~"
%nterm <int> list_param list_parameter list_parameters
%nterm <int> parameters // 函数调用参数个数
%nterm <int> parameter body_function bodys_function
%nterm call_f// 非终结符类型也需要指定,这个与下面的例子适配,可以删除或根据需要添加,如果不需要属性文法也可以不指定类型
%type assignment_s return_s declaration_s variables variable
%type value_type
%type function main_function normal_function
%%
// 在这里写文法规则和动作
%start program; // 文法开始符号
program:
%empty {}
|program function
function://其中一个函数
main_function
//main函数
|normal_function//普通函数
//普通函数
normal_function:
value_type "identifier" {
drv.functionArgsTable.clear();
drv.functionArgsCount = 0;
}"(" list_parameters{
drv.identifierTable.clear();
drv.identifierCount = 0;
} ")" "{" bodys_function {
cout << $2 << ":" << endl;
cout << " push ebp" << endl;
cout << " mov ebp, esp" << endl;
if(drv.identifierCount > 0)
cout << " sub esp, " << drv.identifierCount * 4 << endl;
printBuffer();
buffer.str("");
if(!$9){//没有return语句
if(drv.identifierCount > 0)
cout << " add esp, " << drv.identifierCount * 4 << endl;
cout << " leave" << endl;
cout << " ret" << endl;
}
}"}"
value_type:
VOID
| INT
list_parameters:
%empty {$$=0;}
|list_param{$$=$1;}
list_param:
list_parameter{$$=1;}
|list_param "," list_parameter{$$=$1+1;}
list_parameter:
"int" "identifier"{
drv.functionArgsTable[$2] = ++drv.functionArgsCount;
}
main_function:
value_type "main"{
drv.functionArgsTable.clear();
drv.functionArgsCount = 0;
}"(" list_parameters{
drv.identifierTable.clear();
drv.identifierCount = 0;
} ")" "{"bodys_function {
cout << "main" << ":" << endl;
cout << " push ebp" << endl;
cout << " mov ebp, esp" << endl;
if(drv.identifierCount > 0)
cout << " sub esp, " << drv.identifierCount * 4 << endl;
printBuffer();
buffer.str("");
} "}"
bodys_function:
%empty {$$=0;}
|bodys_function body_function {$$=$2;}
// 不确定有多少行
body_function:
declaration_s{$$=0;}
|assignment_s{$$=0;}
|return_s{$$=1;}
|call_f ";"{$$=0;}
|if_else{$$=0;}
|while_s{$$=0;}
| "continue" ";"
{
buffer << " jmp " << drv.continue_vector.back() << endl;
}
| "break" ";"
{
buffer << " jmp " << drv.break_vector.back() << endl;
};
if_else:
IF "(" exp ")"
{
drv.ifCount++;
buffer << " pop eax" << endl;
buffer << " cmp eax, 0" << endl;
buffer << " je " << ".L_if_end_" << drv.ifCount << endl;
drv.if_vector.push_back(".L_else_end_" + to_string(drv.ifCount));
drv.if_vector.push_back(".L_if_end_" + to_string(drv.ifCount));
}
"{"bodys_function"}" else_s
else_s:
%empty %prec THEN
{
buffer << drv.if_vector.back() << ":" << endl;
drv.if_vector.pop_back();
drv.if_vector.pop_back();
}
| ELSE
{
string tmp = drv.if_vector.back();
drv.if_vector.pop_back();
buffer << " jmp " << drv.if_vector.back() << endl;
buffer << tmp << ":" << endl;
}
"{"bodys_function"}"
{
buffer<< drv.if_vector.back() << ":" << endl;
drv.if_vector.pop_back();
}
while_s:
WHILE "("
{
drv.whileCount++;
buffer<< ".L_while_cond_" << drv.whileCount << ":" << endl;
drv.continue_vector.push_back(".L_while_cond_" + to_string(drv.whileCount));
drv.break_vector.push_back(".L_while_end_" + to_string(drv.whileCount));
}
exp
{
buffer << " pop eax" << endl;
buffer << " cmp eax, 0" << endl;
buffer << " je " << drv.break_vector.back() << endl;
}
")" "{"bodys_function
{
buffer << " jmp " << drv.continue_vector.back() << endl;
buffer << drv.break_vector.back() << ":" << endl;
drv.continue_vector.pop_back();
drv.break_vector.pop_back();
}"}"
//定义语句
declaration_s: "int" variables ";"
variables:
%empty{}
|variables variable
variable:
"identifier" {
drv.identifierTable[$1] = ++drv.identifierCount;
buffer << " mov DWORD PTR [ebp-" << drv.identifierTable[$1] * 4 << "], 0" << endl;
}
|","
|"identifier" "=" exp{
drv.identifierTable[$1] = ++drv.identifierCount;
buffer << " pop eax" << endl;
buffer << " mov DWORD PTR [ebp-" << drv.identifierTable[$1] * 4 << "], eax" << endl;
}
//赋值语句
assignment_s:
"identifier" "=" exp ";"{
buffer << " pop eax" << endl;
if(drv.functionArgsTable.count($1)){
buffer << " mov DWORD PTR [ebp+" << 8 + 4 * (drv.functionArgsCount - drv.functionArgsTable[$1]) << "], eax" << endl;
}
else if(drv.identifierTable.count($1)){
buffer << " mov DWORD PTR [ebp-" << drv.identifierTable[$1] * 4 << "], eax" << endl;
}
};
//return语句
return_s:
RETURN ";"{
if(drv.identifierCount > 0){
buffer << " add esp, " << drv.identifierCount * 4 << endl;
}
buffer << " leave" << endl;
buffer << " ret" << endl;
}
|"return" exp ";"{
buffer << " pop eax" << endl;// 返回值
if(drv.identifierCount > 0)
buffer << " add esp, " << drv.identifierCount * 4 << endl;
buffer << " leave" << endl;
buffer << " ret" << endl;
}
exp:
IDENTIFIER{
if(drv.functionArgsTable.count($1)){// 函数参数
buffer << " mov eax, " << "DWORD PTR [ebp+" << 8 + 4 * (drv.functionArgsCount - drv.functionArgsTable[$1]) << "]" << endl;
buffer << " push eax" << endl;
}
else if(drv.identifierTable.count($1)){// 局部变量
buffer << " mov eax, " << "DWORD PTR [ebp-" << drv.identifierTable[$1] * 4 << "]" << endl;
buffer << " push eax" << endl;
}
}
|call_f{
buffer << " push eax" << endl; // 只有当函数调用作为表达式时才处理函数返回值
}
| INTEGER
{
buffer << " push " << $1 << endl;
}
| exp PLUS exp { add(); }
| exp MINUS exp { sub(); }
| exp TIMES exp { mul(); }
| exp DIVIDE exp { div(); }
| exp MOD exp { mod(); }
| exp LT exp { less_than(); }
| exp LE exp { lessequ(); }
| exp GT exp { greater_than(); }
| exp GE exp { greaterequ(); }
| exp "=="exp { equ(); }
| exp "!=" exp { notequ(); }
| exp "&&" exp { and1(); }
| exp "&" exp { bitand1(); }
| exp "|" exp { bitor1(); }
| exp "^" exp { bitxor(); }
| exp "||" exp { or1(); }
| "~" exp { bitnot(); }
| "!" exp { not1(); }
| "-" exp %prec UMINUS { neg(); }
| LPAREN exp RPAREN
;
call_f:
IDENTIFIER "(" parameters ")"
{
if($1 == "println_int"){
buffer << " push offset format_str" << endl;
buffer << " call printf" << endl;
buffer << " add esp, 8" << endl;
}
else{
buffer << " call " << $1 << endl;
buffer << " add esp, " << $3 * 4 << endl; // 释放参数空间
}
};
parameters:
%empty
{
$$ = 0;
}
| parameter
{
$$ = $1;
};
parameter:
exp
{
$$ = 1;
}
| parameter "," exp
{
$$ = $1 + 1;
};
%%
void yy::parser::error (const location_type& l, const std::string& m)
{
std::cerr << l << ": " << m << '\n';
}
scanner.l
%{
#include <iostream>
#include "driver.h"
#include "parser.hpp"
%}
%option noyywrap nounput noinput batch debug
%{
# define YY_USER_ACTION loc.columns (yyleng);
%}
id [_a-zA-Z][_a-zA-Z0-9]*
int [0-9]+
blank [ \t\r]
%%
%{
/* 开启了bison提供的location功能 */
yy::location& loc = drv.m_loc;
loc.step ();
%}
{blank} loc.step(); /* 跳过空白字符 */
\n+ loc.lines(yyleng); loc.step(); /* 处理换行符 */
"int" { return yy::parser::make_INT(loc); } /* 关键字 int */
"return" { return yy::parser::make_RETURN(loc); } /* 关键字 return */
"void" { return yy::parser::make_VOID(loc); } /* 关键字 void */
"main" { return yy::parser::make_MAIN(loc); } /* 关键字 main */
"while" { return yy::parser::make_WHILE(loc); } /* 关键字 while */
"if" { return yy::parser::make_IF(loc); } /* 关键字 if */
"else" { return yy::parser::make_ELSE(loc); } /* 关键字 else */
"continue" { return yy::parser::make_CONTINUE(loc); }/* 关键字 continue */
"break" { return yy::parser::make_BREAK(loc); } /* 关键字 break */
"=" return yy::parser::make_ASSIGN(loc); /* 赋值操作符 */
"&&" return yy::parser::make_LAND(loc); /* 逻辑与 */
"||" return yy::parser::make_LOR(loc); /* 逻辑或 */
"!" return yy::parser::make_LNOT(loc); /* 逻辑非 */
"+" return yy::parser::make_PLUS(loc); /* 加号 */
"-" return yy::parser::make_MINUS(loc); /* 减号 */
"*" return yy::parser::make_TIMES(loc); /* 乘号 */
"/" return yy::parser::make_DIVIDE(loc); /* 除号 */
"%" return yy::parser::make_MOD(loc); /* 取模 */
"<" return yy::parser::make_LT(loc); /* 小于 */
"<=" return yy::parser::make_LE(loc); /* 小于等于 */
">" return yy::parser::make_GT(loc); /* 大于 */
">=" return yy::parser::make_GE(loc); /* 大于等于 */
"==" return yy::parser::make_EQ(loc); /* 等于 */
"!=" return yy::parser::make_NE(loc); /* 不等于 */
"&" return yy::parser::make_BAND(loc); /* 按位与 */
"|" return yy::parser::make_BOR(loc); /* 按位或 */
"^" return yy::parser::make_BXOR(loc); /* 按位异或 */
"~" return yy::parser::make_BITNOT(loc); /* 按位非 */
"(" return yy::parser::make_LPAREN(loc); /* 左圆括号 */
")" return yy::parser::make_RPAREN(loc); /* 右圆括号 */
"{" return yy::parser::make_LBRACE(loc); /* 左大括号 */
"}" return yy::parser::make_RBRACE(loc); /* 右大括号 */
";" return yy::parser::make_SEMICOLON(loc); /* 分号 */
"," return yy::parser::make_COMMA(loc); /* 逗号 */
{id} return yy::parser::make_IDENTIFIER(yytext, loc); /* 标识符 */
{int} return yy::parser::make_INTEGER(std::stoi(yytext), loc); /* 整数 */
<<EOF>> return yy::parser::make_END(loc); /* 文件结束 */
%%
void Driver::scan_begin()
{
// 关闭flex的debug信息
yy_flex_debug = 0;
yyin = fopen(m_file.c_str(), "r");
}
void Driver::scan_end()
{
fclose(yyin);
}
CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 3.16)
project(Compilerlab4)
set(CMAKE_CXX_STANDARD 14)
add_compile_options(-pedantic)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR})
include(FindFLEX)
if(FLEX_FOUND)
message("Info: flex found!")
else()
message("Error: flex not found!")
endif()
FLEX_TARGET(Scanner scanner.l ${CMAKE_CURRENT_BINARY_DIR}/scanner.cpp)
include(FindBISON)
if(BISON_FOUND)
message("Info: bison found!")
else()
message("Error: bison not found!")
endif()
BISON_TARGET(Parser parser.y ${CMAKE_CURRENT_BINARY_DIR}/parser.cpp
DEFINES_FILE ${CMAKE_CURRENT_BINARY_DIR}/parser.hpp)
add_executable(Compilerlab4
${FLEX_Scanner_OUTPUTS}
${BISON_Parser_OUTPUTS}
driver.cpp
compilerlab3.cpp
)
target_compile_features(Compilerlab4 PRIVATE cxx_std_14)
target_link_libraries(Compilerlab4 PUBLIC -lm)