diff --git a/src/classes.cpp b/src/classes.cpp
index f3bea5eec1b4e3fbade151e52212e20eb3382200..b6cd697b4388e027c77c660aff37e7adb7dd4580 100644
--- a/src/classes.cpp
+++ b/src/classes.cpp
@@ -51,12 +51,12 @@ void UnaryExpAST::Dump(std::stringstream& out) const{
         break;
     case '-':
         base_value_num++;
-        out<<"%"<<base_value_num<<" = "<<"sub 0, "<<temp_ss<<endl;
+        out<<"%"+to_string(base_value_num)<<" = "<<"sub 0, "<<temp_ss<<endl;
         exp_value="%"+to_string(base_value_num);
         break;
     case '!':
         base_value_num++;
-        out<<"%"<<base_value_num<<" = "<<"eq "<<temp_ss<<", 0"<<endl;
+        out<<"%"+to_string(base_value_num)<<" = "<<"eq "<<temp_ss<<", 0"<<endl;
         exp_value="%"+to_string(base_value_num);
         break;
     default:
@@ -130,4 +130,107 @@ void MulExpAST::Dump(std::stringstream& out) const{
         }
         exp_value=temp_ss;
     }
+}
+//RelExp EqExp LAndExp LOrExp
+void RelExpAST::Dump(std::stringstream& out) const{
+    string SubExp_ss;
+    string NextExp_ss;
+    string temp_ss;
+    if(tag==ADD)
+        SubExp->Dump(out);
+    else
+    {
+        NextExp->Dump(out);
+        NextExp_ss=exp_value;
+        SubExp->Dump(out);
+        SubExp_ss=exp_value;
+        base_value_num++;
+        temp_ss="%"+to_string(base_value_num);
+        switch(op)
+        {
+            case L:
+                out<<temp_ss<<" = lt "<<NextExp_ss<<", "<<SubExp_ss<<endl;
+                break;
+            case G:
+                out<<temp_ss<<" = gt "<<NextExp_ss<<", "<<SubExp_ss<<endl;
+                break;
+            case LE:
+                out<<temp_ss<<" = le "<<NextExp_ss<<", "<<SubExp_ss<<endl;
+                break;
+            case GE:
+                out<<temp_ss<<" = ge "<<NextExp_ss<<", "<<SubExp_ss<<endl;
+                break;
+            default:
+                break;
+        }
+        exp_value=temp_ss;
+    }
+}
+void EqExpAST::Dump(std::stringstream& out) const{
+    string SubExp_ss;
+    string NextExp_ss;
+    string temp_ss;
+    if(tag==REL)
+        SubExp->Dump(out);
+    else
+    {
+        NextExp->Dump(out);
+        NextExp_ss=exp_value;
+        SubExp->Dump(out);
+        SubExp_ss=exp_value;
+        base_value_num++;
+        temp_ss="%"+to_string(base_value_num);
+        switch(op)
+        {
+            case EQ:
+                out<<temp_ss<<" = eq "<<NextExp_ss<<", "<<SubExp_ss<<endl;
+                break;
+            case NE:
+                out<<temp_ss<<" = ne "<<NextExp_ss<<", "<<SubExp_ss<<endl;
+                break;
+            default:
+                break;
+        }
+        exp_value=temp_ss;
+    }
+}
+void LAndExpAST::Dump(std::stringstream& out) const{
+    string SubExp_ss;
+    string NextExp_ss;
+    if(tag==EQ)
+        SubExp->Dump(out);
+    else
+    {
+        NextExp->Dump(out);
+        NextExp_ss=exp_value;
+        SubExp->Dump(out);
+        SubExp_ss=exp_value;
+        base_value_num++;
+        out<<"%"+to_string(base_value_num)<<" = "<<"ne "<<NextExp_ss<<", 0"<<endl;
+        base_value_num++;
+        out<<"%"+to_string(base_value_num)<<" = "<<"ne "<<SubExp_ss<<", 0"<<endl;
+        base_value_num++;
+        out<<"%"+to_string(base_value_num)<<" = "<<"and "<<"%"+to_string(base_value_num-2)<<", "<<"%"+to_string(base_value_num-1)<<endl;
+        exp_value="%"+to_string(base_value_num);
+    }
+}
+void LOrExpAST::Dump(std::stringstream& out) const{
+    string SubExp_ss;
+    string NextExp_ss;
+    if(tag==LA)
+        SubExp->Dump(out);
+    else
+    {
+        NextExp->Dump(out);
+        NextExp_ss=exp_value;
+        SubExp->Dump(out);
+        SubExp_ss=exp_value;
+        base_value_num++;
+        out<<"%"+to_string(base_value_num)<<" = "<<"ne "<<NextExp_ss<<", 0"<<endl;
+        base_value_num++;
+        out<<"%"+to_string(base_value_num)<<" = "<<"ne "<<SubExp_ss<<", 0"<<endl;
+        base_value_num++;
+        out<<"%"+to_string(base_value_num)<<" = "<<"or "<<"%"+to_string(base_value_num-2)<<", "<<"%"+to_string(base_value_num-1)<<endl;
+        exp_value="%"+to_string(base_value_num);
+    }
 }
\ No newline at end of file
diff --git a/src/classes.h b/src/classes.h
index 422a8d86c44594ea1eee0c8e3b776e1cef76e2ee..d556b6a48b2df5cab8b60403eefbc3994e0ffeb0 100644
--- a/src/classes.h
+++ b/src/classes.h
@@ -94,4 +94,39 @@ class MulExpAST: public BaseAST{
     enum {UNA,OP} tag;
     void Dump(std::stringstream& out) const override;
 };
+//RelExp EqExp LAndExp LOrExp
+class RelExpAST: public BaseAST{
+    public:
+    std::unique_ptr<BaseAST> SubExp;
+    std::unique_ptr<BaseAST> NextExp;
+    enum {L,G,LE,GE} op;
+    enum {ADD,OP} tag;
+    void Dump(std::stringstream& out) const override;
+};
+
+class EqExpAST: public BaseAST{
+    public:
+    std::unique_ptr<BaseAST> SubExp;
+    std::unique_ptr<BaseAST> NextExp;
+    enum {EQ,NE} op;
+    enum {REL,OP} tag;
+    void Dump(std::stringstream& out) const override;
+};
+
+class LAndExpAST: public BaseAST{
+    public:
+    std::unique_ptr<BaseAST> SubExp;
+    std::unique_ptr<BaseAST> NextExp;
+    enum {EQ,OP} tag;
+    void Dump(std::stringstream& out) const override;
+};
+
+class LOrExpAST: public BaseAST{
+    public:
+    std::unique_ptr<BaseAST> SubExp;
+    std::unique_ptr<BaseAST> NextExp;
+    enum {LA,OP} tag;
+    void Dump(std::stringstream& out) const override;
+};
+
 #endif
\ No newline at end of file
diff --git a/src/sysy.l b/src/sysy.l
index 665bbd44b0e46b04c24d3c487d9462bfaa5ff4eb..38d18342c3d8e4c33c258bc2c4aa992816470bb8 100644
--- a/src/sysy.l
+++ b/src/sysy.l
@@ -36,7 +36,12 @@ Hexadecimal   0[xX][0-9a-fA-F]+
 {BlockComment}  {}
 "int"           { return INT; }
 "return"        { return RETURN; }
-
+"<="            {return LE;}
+">="            {return GE;}
+"=="            {return EQ;}
+"!="            {return NE;}
+"&&"            {return LAND;}
+"||"            {return LOR;}
 {Identifier}    { yylval.str_val = new string(yytext); return IDENT; }
 
 {Decimal}       { yylval.int_val = strtol(yytext, nullptr, 0); return INT_CONST; }
diff --git a/src/sysy.y b/src/sysy.y
index 97d41e4820cd54ec51a5964eea1f7dacec50314e..9fffa73d7b9adbb7a14e003f9f690d488f9a1e61 100644
--- a/src/sysy.y
+++ b/src/sysy.y
@@ -33,11 +33,13 @@ using namespace std;
 // lexer 返回的所有 token 种类的声明
 // 注意 IDENT 和 INT_CONST 会返回 token 的值, 分别对应 str_val 和 int_val
 %token INT RETURN
+%token LE GE EQ NE LAND LOR
 %token <str_val> IDENT
 %token <int_val> INT_CONST
 
 // 非终结符的类型定义
-%type <ast_val> FuncDef FuncType Block Stmt Exp UnaryExp PrimaryExp AddExp MulExp
+%type <ast_val> FuncDef FuncType Block Stmt 
+%type <ast_val> Exp UnaryExp PrimaryExp AddExp MulExp RelExp EqExp LAndExp LOrExp
 %type <int_val> Number
 %type <char_val> UnaryOp
 
@@ -97,7 +99,7 @@ Number
   ;
 
 Exp         
-  : AddExp{
+  : LOrExp{
     auto ast = new ExpAST();
     ast->SubExp = unique_ptr<BaseAST>($1);
     $$ = ast;
@@ -193,6 +195,100 @@ AddExp
     $$=ast;
   }
   ;
+RelExp      
+  : AddExp {
+    auto ast=new RelExpAST();
+    ast->tag =RelExpAST::ADD;
+    ast->SubExp=unique_ptr<BaseAST>($1);
+    $$=ast;
+  }
+  | RelExp '<' AddExp{
+    auto ast =new RelExpAST();
+    ast->tag=RelExpAST::OP;
+    ast->NextExp=unique_ptr<BaseAST>($1);
+    ast->op=RelExpAST::L;
+    ast->SubExp=unique_ptr<BaseAST>($3);
+    $$=ast;
+  }
+  | RelExp '>' AddExp{
+    auto ast =new RelExpAST();
+    ast->tag=RelExpAST::OP;
+    ast->NextExp=unique_ptr<BaseAST>($1);
+    ast->op=RelExpAST::G;
+    ast->SubExp=unique_ptr<BaseAST>($3);
+    $$=ast;
+  }
+  | RelExp LE AddExp{
+    auto ast =new RelExpAST();
+    ast->tag=RelExpAST::OP;
+    ast->NextExp=unique_ptr<BaseAST>($1);
+    ast->op=RelExpAST::LE;
+    ast->SubExp=unique_ptr<BaseAST>($3);
+    $$=ast;
+  }
+  | RelExp GE AddExp{
+    auto ast =new RelExpAST();
+    ast->tag=RelExpAST::OP;
+    ast->NextExp=unique_ptr<BaseAST>($1);
+    ast->op=RelExpAST::GE;
+    ast->SubExp=unique_ptr<BaseAST>($3);
+    $$=ast;
+  }
+  ;
+EqExp       
+  : RelExp {
+    auto ast=new EqExpAST();
+    ast->tag =EqExpAST::REL;
+    ast->SubExp=unique_ptr<BaseAST>($1);
+    $$=ast;
+  }
+  | EqExp EQ RelExp{
+    auto ast =new EqExpAST();
+    ast->tag=EqExpAST::OP;
+    ast->NextExp=unique_ptr<BaseAST>($1);
+    ast->op=EqExpAST::EQ;
+    ast->SubExp=unique_ptr<BaseAST>($3);
+    $$=ast;
+  }
+  | EqExp NE RelExp{
+    auto ast =new EqExpAST();
+    ast->tag=EqExpAST::OP;
+    ast->NextExp=unique_ptr<BaseAST>($1);
+    ast->op=EqExpAST::NE;
+    ast->SubExp=unique_ptr<BaseAST>($3);
+    $$=ast;
+  }
+  ;
+LAndExp     
+  : EqExp {
+    auto ast=new LAndExpAST();
+    ast->tag =LAndExpAST::EQ;
+    ast->SubExp=unique_ptr<BaseAST>($1);
+    $$=ast;
+  }
+  | LAndExp LAND EqExp{
+    auto ast =new LAndExpAST();
+    ast->tag=LAndExpAST::OP;
+    ast->NextExp=unique_ptr<BaseAST>($1);
+    ast->SubExp=unique_ptr<BaseAST>($3);
+    $$=ast;
+  }
+  ;
+LOrExp      
+  : LAndExp {
+    auto ast=new LOrExpAST();
+    ast->tag =LOrExpAST::LA;
+    ast->SubExp=unique_ptr<BaseAST>($1);
+    $$=ast;
+  }
+  | LOrExp LOR LAndExp{
+    auto ast =new LOrExpAST();
+    ast->tag=LOrExpAST::OP;
+    ast->NextExp=unique_ptr<BaseAST>($1);
+    ast->SubExp=unique_ptr<BaseAST>($3);
+    $$=ast;
+  }
+  ;
 %%
 
 // 定义错误处理函数, 其中第二个参数是错误信息