IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> javacc 语义分析 -> 正文阅读

[移动开发]javacc 语义分析

javacc 语义分析

在词法和语法分析的基础上添加语义子程序,并且掌握“拉链”、“回填”操作的原理以及实现;并且针对测试代码,输出四元式序列。

仍然是使用和语法分析相同的MiniC语法作为参考文法。

<程序> ->Type main(){<语句块>*}

<语句块> -> <语句>|{<语句块>*}

<语句> -> <顺序语句>|<条件语句>|<循环语句>

<顺序语句> ->(<声明语句>|<赋值语句>)”;”

<声明语句> ->Type ID,ID,…,ID

<赋值语句> ->ID =<表达式>

<条件语句> ->if(<条件>)<语句块>else<语句块>

<循环语句> ->while(<条件>)<语句块>

<逻辑> -><条件>(<逻辑运算符><条件>)*

<条件> -><表达式>(<关系符><表达式>)?

<表达式> ->//可以使用默认的

<关系符> -><|<=|>|>=|==|!=

<逻辑运算> ->&& | || (包含在逻辑中)

修改.jjt文件中的main方法,使其执行任务是:指定要进行语义分析的源程序,执行语义分析,输出四元式到文件中。

要想好编译程序的结构,除了JavaCC生成的类,还需要哪些辅助类。如四元式类、四元式链表类、自动产生临时变量的类等。这里的四个类都可以使用所给的类,直接添加到项目进行使用。

为了使得输出的四元式子在文件中而不输出语法树,我们可以选择将QTList类中的printQTTable方法进行修改。

?public void printQTTable() {
?        // System.out.println(toString());
?        Iterator<QTInfo> itr = QTList.iterator();
?        try {
?            FileWriter fw = new FileWriter("./result.txt",true);
?            BufferedWriter bw = new BufferedWriter(fw);
?            while (itr.hasNext()) {
?                QTInfo tmp = (QTInfo) itr.next();
?                //System.out.println(tmp.toString());
?                bw.write(tmp.toString());
?                bw.newLine();
?            }
?            bw.close();
?            fw.close();
?            
?        } catch (Exception e) {
?            e.printStackTrace();
?        }
?    }

?

在.jjt文件中添加Minic文法表达式

?SimpleNode Start() :
?{}
?{
? ?Program()
? ?//AdditiveExpression()
?  {
? ? ?return jjtThis;
?  }
?}
?void Program() ://主程序
?{}
?{
?Type()
? ?< MAIN >
? ?< LB >
? ?< RB >
? ?< BLB >
?  (
?    SentenceBlock()
? ?  )*
?// ?  (ReturnSentence()
?// ?  )
? ? ?< BRB >
?}
?void Type() ://类别
?{}
?{
? < INT >
?| < VOID >
?| < STRING >
?| < CHAR >
?| < DOUBLE >
?| < FLOAT >
?}
?void ReturnSentence()://返回
?{}
?{
?< RETURN > <INTEGER_LITERAL> < SEMICOLON>
?}
??
?void SentenceBlock() ://语句块
?{}
?{
?    Sentence()
?| < BLB > (SentenceBlock())* < BRB >
?}
?void Sentence() ://语句
?{}
?{
? ?SequenceSentence()
?| ConditionSentence()
?| LoopSentence()
??
?}
?void SequenceSentence() ://顺序语句
?{}
?{
? ? ?StateSentence() < SEMICOLON >
? ?| AssignSentence() < SEMICOLON >
?}
?void StateSentence() ://声明语句
?{}
?{
? Type()
?Identifier() (< COMMA > Identifier())*
?}
?void AssignSentence() ://赋值语句
?{
? ?String str2=null,str1=null;
? ?Token op;
?}
?{
? ?str1 = Identifier()
? ?op = "="
? ?str2 = Expression()
?  {
? ? ?QTInfo qt = new QTInfo(op.image,str2,"_",str1);
? ? ?qtList.addQTInfo(qt);
?  }
?}
??
??
??
??
?void ConditionSentence()://条件语句
?{
? ?int QTSize = QTInfo.size;
? ?ConditionValue Value = null;
?}
?{
? ?< IF >< LB >
?    (
?     ?Value = ifCondition()
?    )
? ?< RB >
?  {
? ? ?Value.backpatchTrueChain(QTInfo.size+1);
?  }
? ?SentenceBlock()
?  {
?    Value.backpatchFalseChain(QTInfo.size+1);
?  }
?  (
? ? 
? ? ?< ELSE >
?    {
?     QTInfo qt = new QTInfo("J","_","_","T");
?     qtList.addQTInfo(qt);
?     Value.mergeTrue(qt);
? ?  }
? ?SentenceBlock()
? ?  {
? ? ? ?Value.backpatchTrueChain(QTInfo.size+1);
? ? ? ?Value.backpatchFalseChain(QTInfo.size);
? ? 
? ?  }
?  )?
?}
?ConditionValue Condition() ://循环条件
?{
?    ConditionValue Value = new ConditionValue();
?    String str1 = null,str2 = null;
?    Token op = null; 
?}
?{
? ?str1 = Expression()(
? ?  (
? ? ?op = ">"
? ?|op = "<"
? ?|op = ">="
? ?|op = "<="
? ?|op = "!="
? ?|op = "||"
? ?|op = "&&"
?  )
? ?
? ? ?str2 = Expression())?
?{
? ?QTInfo qt1 = new QTInfo("J"+op.image,str1,str2,"_");
? ?qtList.addQTInfo(qt1);
? ?QTInfo qt2 = new QTInfo("J","_","_","_");
? ?qtList.addQTInfo(qt2);
? ?Value.mergeTrue(qt1);
? ?Value.mergeFalse(qt2);
? ?return Value;
?//  QTInfo qt1;
?//  if(str2 != "")
?//      qt1 = new QTInfo("J"+op.image,str1,str2,"_");
?//  else
?// ?  qt1 = new QTInfo("Jnz",str1,"_","_");
?//  qtList.addQTInfo(qt1);
?//  QTInfo qt2 = new QTInfo("J","_","_","_");
?//  qtList.addQTInfo(qt2);
?//  Value.mergeTrue(qt1);
?//  Value.mergeFalse(qt2);
?//  return Value;
?}
?}
?ConditionValue ifCondition() ://判定条件
?{
?    ConditionValue Value = new ConditionValue();
?    String str1 = null,str2 = null;
?    Token op = null;
?    int qtSize = QTInfo.size;
?}
?{
? ?str1 = Expression()(
? ?  (
? ? ?op = ">"
? ?|op = "<"
? ?|op = ">="
? ?|op = "<="
? ?|op = "!="
? ?|op = "||"
? ?|op = "&&"
?  )
? ?
? ? ?str2 = Expression())?
?{
??
? ?QTInfo qt1;
? ?
? ?if(op != null) { 
?    qt1 = new QTInfo("J"+op.image,str1,str2,QTInfo.size+3);
?    qtList.addQTInfo(qt1);
? ? ?//Value.mergeTrue(qt1);
? }
? ?else { 
? ? ?qt1 = new QTInfo("Jnz",str1,"_",QTInfo.size+3);
? ? ?qtList.addQTInfo(qt1);
? ? ?//Value.mergeTrue(qt1);
?  }
? ?
? ?QTInfo qt2 = new QTInfo("J","_","_","F");
? ?qtList.addQTInfo(qt2);
? ?
? ?Value.mergeFalse(qt2);
? ?return Value;
?}
?}
?void LoopSentence()://循环语句
?{
? ?int QTSize = QTInfo.size;
? ?ConditionValue Value = null;
?}
?{
?    < WHILE >
?    < LB >
?    Value = Condition()
?    < RB >
?    {
?        Value.backpatchTrueChain(QTInfo.size+1);
?    }
?    SentenceBlock()
?    {
?     ?QTInfo qt = new QTInfo("J","_","_",QTSize+1);
?     ?qtList.addQTInfo(qt);
?     ?Value.backpatchFalseChain(QTInfo.size+1);
?    }
?}
?String Expression() ://表达式
?{String str;}
?{
? str = AdditiveExpression()
? {
? ? return str;
? }
?}
??
?String AdditiveExpression() :
?{
? ?String str1,str2;
? ?String newTemp;
? ?Token op;
?}
?{
? ?str1 = MultiplicativeExpression()
?  {
? ? ?newTemp = str1;
?  }
?  (
? ?  (
? ? ? ?op = "+"
? ? ?| op = "-"
? ?  )
? ?str2 = MultiplicativeExpression()
?  {
? ? ?newTemp = VariableNameGenerator.genVariableName();
? ? ?QTInfo qt = new QTInfo(op.image,str1,str2,newTemp);
? ? ?qtList.addQTInfo(qt);
? ? ?str1 = newTemp;
?  }
?  )*
?  {
? ? ?return newTemp;
?  }
?}
??
?String MultiplicativeExpression() :
?{
? ?String str1,str2;
? ?String newTemp;
? ?Token op;
?}
?{
? ?str1 = UnaryExpression()
?  {
? ? ?newTemp = str1;
?  }
?  (
? ?  (
? ? ? ?op = "*"
? ? ?| op = "/"
? ? ?| op = "%"
? ?  )
? ?str2 = UnaryExpression()
?  {
? ? ?newTemp = VariableNameGenerator.genVariableName();
? ? ?QTInfo qt = new QTInfo(op.image,str1,str2,newTemp);
? ? ?qtList.addQTInfo(qt);
? ? ?str1 = newTemp;
?  }
?  )*
?  {
? ? ?return newTemp;
?  }
?}
??
?String UnaryExpression() :
?{String str = null;}
?{
?    (
?    
?        "(" str = Expression() ")"
?        | str = Identifier()
?        | str = Integer()
?        | str = Constant()
?    )
?    {
?     ?return str;
?    }
?}
??
??
?String Identifier() :
?{Token t = null;}
?{
? ?t = < IDENTIFIER >
?  {
? ? ?return t.image;
?  }
?}
??
?String Integer() :
?{Token t = null;}
?{
? ?t = < INTEGER_LITERAL >
?  {
? ? ?return t.image;
?  }
?}
?String Constant() :
?{Token t =null;}
?{
? ?t = < CONSTANT >
?  {
? ? ?return t.image;
?  }
?}

测试代码和生成的四元式如下:

?

?

?

完整的jjt文件如下:

?/**
? * JJTree template file created by SF JavaCC plugin 1.5.28+ wizard for JavaCC 1.5.0+
? */
?options
?{
? ?static = true;
?}
??
?PARSER_BEGIN(MyNewGrammar)
?package byylworkform3;
?import utils.*;
?import java.io.FileInputStream;
?public class MyNewGrammar
?{
? ?static QTList qtList = new QTList();
? ?public void printQTList() {
?    qtList.printQTTable();
?  }
? ?public static void main(String args [])
?  {
?// ?  System.out.println("Reading from standard input...");
?// ?  System.out.print("Enter an expression like \"1+(2+3)*var;\" :");
?// ?  MyNewGrammar input = new MyNewGrammar(System.in);
? ? ?try
? ?  {
? ? ? ?//String file = "./text1.txt";
? ? ? ?String file = "./text2.txt";
? ? ? ?//String file = "./text3.txt";
? ? ? ?//String file = "./text4.txt";
? ? ? ?FileInputStream fin = new FileInputStream(file);
? ? ? ?MyNewGrammar input = new MyNewGrammar(fin);
? ? ? ?SimpleNode n = MyNewGrammar.Start();
? ? ? ?input.printQTList();
? ? ? ?n.dump("");
? ? ? ?System.out.println("Thank you.");
? ?  }
? ? ?catch (Exception e)
? ?  {
? ? ? ?System.out.println("Oops.");
? ? ? ?System.out.println(e.getMessage());
? ?  }
?  }
?}
??
?PARSER_END(MyNewGrammar)
??
?SKIP :
?{
? ?" "
?| "\t"
?| "\n"
?| "\r"
?| < "//" (~[ "\n", "\r" ])*
? ?  (
? ? ? ?"\n"
? ? ?| "\r"
? ? ?| "\r\n"
? ?  ) >
?| < "/*" (~[ "*" ])* "*"
? ?  (
? ? ? ?~[ "/" ] (~[ "*" ])* "*"
? ?  )*
? ? ?"/" >
?}
??
?TOKEN : /* LITERALS */
?{
? ?< INTEGER_LITERAL :
? ? ?< DECIMAL_LITERAL > ([ "l", "L" ])?
? ?| < HEX_LITERAL > ([ "l", "L" ])?
? ?| < OCTAL_LITERAL > ([ "l", "L" ])? 
? ? ?>
?| < #DECIMAL_LITERAL : [ "1"-"9" ] ([ "0"-"9" ])* >
?| < #HEX_LITERAL : "0" [ "x", "X" ] ([ "0"-"9", "a"-"f", "A"-"F" ])+ >
?| < #OCTAL_LITERAL : "0" ([ "0"-"7" ])* >
?}
??
?TOKEN :
?{
? ?< CONSTANT :
? ?  (< DIGIT >)+
? ?  (
? ? ? ?"." (< DIGIT >)+
? ?  )? >
?}
??
?TOKEN : /* KEYWORDS */
?{
?    < MAIN : "main" >
?|   < INT : "int" >
?| ?< RETURN :"return" >
?| < IF:"if" >
?| < ELSE:"else" >
?| < VOID : "void" >
?| < DOUBLE:"double" >
?| < FLOAT:"float" >
?| < WHILE:"while" >
?| < DO:"do" >
?| < FOR:"for" >
?| < CHAR:"char" >
?| < STRING:"string" >
?| < BOOL:"bool" >
?}
??
?TOKEN: /*OPERATORS*/
?{
?    < PLUS : "+" >
?|   < MINUS : "-" >
?|   < MULTIPLY : "*" >
?|   < DIVIDE : "/" >
?| < GD:">" >
?| < LD:"<" >
?| < SQRT:"^" >
?| < EQ:"=" >
?| < GE:">=" >
?| < LE:"<=" >
?| < EQQ:"==" >
?| < NE:"!=" >
?| < ANDD:"&&" >
?| < ORR:"||" >
?}
?TOKEN: /* SEPARATER */
?{
?< COMMA:"," >
?| < SEMICOLON:";" >
?| < LB:"(" >
?| < RB:")" >
?| < BLB:"{" >
?| < BRB:"}" >
?| < LBB:"[" >
?| < RBB:"]" >
??
?}
?TOKEN : /* IDENTIFIERS */
?{
? ?< IDENTIFIER :
? ? ?< LETTER >
? ?  (
? ? ? ?< LETTER >
? ? ?| < DIGIT >
? ?  )* >
?| < #LETTER : [ "_", "a"-"z", "A"-"Z" ] >
?| < #DIGIT : [ "0"-"9" ] >
?}
??
?SimpleNode Start() :
?{}
?{
? ?Program()
? ?//AdditiveExpression()
?  {
? ? ?return jjtThis;
?  }
?}
?void Program() ://主程序
?{}
?{
?Type()
? ?< MAIN >
? ?< LB >
? ?< RB >
? ?< BLB >
?  (
?    SentenceBlock()
? ?  )*
?// ?  (ReturnSentence()
?// ?  )
? ? ?< BRB >
?}
?void Type() ://类别
?{}
?{
? < INT >
?| < VOID >
?| < STRING >
?| < CHAR >
?| < DOUBLE >
?| < FLOAT >
?}
?void ReturnSentence()://返回
?{}
?{
?< RETURN > <INTEGER_LITERAL> < SEMICOLON>
?}
??
?void SentenceBlock() ://语句块
?{}
?{
?    Sentence()
?| < BLB > (SentenceBlock())* < BRB >
?}
?void Sentence() ://语句
?{}
?{
? ?SequenceSentence()
?| ConditionSentence()
?| LoopSentence()
??
?}
?void SequenceSentence() ://顺序语句
?{}
?{
? ? ?StateSentence() < SEMICOLON >
? ?| AssignSentence() < SEMICOLON >
?}
?void StateSentence() ://声明语句
?{}
?{
? Type()
?Identifier() (< COMMA > Identifier())*
?}
?void AssignSentence() ://赋值语句
?{
? ?String str2=null,str1=null;
? ?Token op;
?}
?{
? ?str1 = Identifier()
? ?op = "="
? ?str2 = Expression()
?  {
? ? ?QTInfo qt = new QTInfo(op.image,str2,"_",str1);
? ? ?qtList.addQTInfo(qt);
?  }
?}
??
??
??
??
?void ConditionSentence()://条件语句
?{
? ?int QTSize = QTInfo.size;
? ?ConditionValue Value = null;
?}
?{
? ?< IF >< LB >
?    (
?     ?Value = ifCondition()
?    )
? ?< RB >
?  {
? ? ?Value.backpatchTrueChain(QTInfo.size+1);
?  }
? ?SentenceBlock()
?  {
?    Value.backpatchFalseChain(QTInfo.size+1);
?  }
?  (
? ? 
? ? ?< ELSE >
?    {
?     QTInfo qt = new QTInfo("J","_","_","T");
?     qtList.addQTInfo(qt);
?     Value.mergeTrue(qt);
? ?  }
? ?SentenceBlock()
? ?  {
? ? ? ?Value.backpatchTrueChain(QTInfo.size+1);
? ? ? ?Value.backpatchFalseChain(QTInfo.size);
? ? 
? ?  }
?  )?
?}
?ConditionValue Condition() ://循环条件
?{
?    ConditionValue Value = new ConditionValue();
?    String str1 = null,str2 = null;
?    Token op = null; 
?}
?{
? ?str1 = Expression()(
? ?  (
? ? ?op = ">"
? ?|op = "<"
? ?|op = ">="
? ?|op = "<="
? ?|op = "!="
? ?|op = "||"
? ?|op = "&&"
?  )
? ?
? ? ?str2 = Expression())?
?{
? ?QTInfo qt1 = new QTInfo("J"+op.image,str1,str2,"_");
? ?qtList.addQTInfo(qt1);
? ?QTInfo qt2 = new QTInfo("J","_","_","_");
? ?qtList.addQTInfo(qt2);
? ?Value.mergeTrue(qt1);
? ?Value.mergeFalse(qt2);
? ?return Value;
?//  QTInfo qt1;
?//  if(str2 != "")
?//      qt1 = new QTInfo("J"+op.image,str1,str2,"_");
?//  else
?// ?  qt1 = new QTInfo("Jnz",str1,"_","_");
?//  qtList.addQTInfo(qt1);
?//  QTInfo qt2 = new QTInfo("J","_","_","_");
?//  qtList.addQTInfo(qt2);
?//  Value.mergeTrue(qt1);
?//  Value.mergeFalse(qt2);
?//  return Value;
?}
?}
?ConditionValue ifCondition() ://判定条件
?{
?    ConditionValue Value = new ConditionValue();
?    String str1 = null,str2 = null;
?    Token op = null;
?    int qtSize = QTInfo.size;
?}
?{
? ?str1 = Expression()(
? ?  (
? ? ?op = ">"
? ?|op = "<"
? ?|op = ">="
? ?|op = "<="
? ?|op = "!="
? ?|op = "||"
? ?|op = "&&"
?  )
? ?
? ? ?str2 = Expression())?
?{
??
? ?QTInfo qt1;
? ?
? ?if(op != null) { 
?    qt1 = new QTInfo("J"+op.image,str1,str2,QTInfo.size+3);
?    qtList.addQTInfo(qt1);
? ? ?//Value.mergeTrue(qt1);
? }
? ?else { 
? ? ?qt1 = new QTInfo("Jnz",str1,"_",QTInfo.size+3);
? ? ?qtList.addQTInfo(qt1);
? ? ?//Value.mergeTrue(qt1);
?  }
? ?
? ?QTInfo qt2 = new QTInfo("J","_","_","F");
? ?qtList.addQTInfo(qt2);
? ?
? ?Value.mergeFalse(qt2);
? ?return Value;
?}
?}
?void LoopSentence()://循环语句
?{
? ?int QTSize = QTInfo.size;
? ?ConditionValue Value = null;
?}
?{
?    < WHILE >
?    < LB >
?    Value = Condition()
?    < RB >
?    {
?        Value.backpatchTrueChain(QTInfo.size+1);
?    }
?    SentenceBlock()
?    {
?     ?QTInfo qt = new QTInfo("J","_","_",QTSize+1);
?     ?qtList.addQTInfo(qt);
?     ?Value.backpatchFalseChain(QTInfo.size+1);
?    }
?}
?String Expression() ://表达式
?{String str;}
?{
? str = AdditiveExpression()
? {
? ? return str;
? }
?}
??
?String AdditiveExpression() :
?{
? ?String str1,str2;
? ?String newTemp;
? ?Token op;
?}
?{
? ?str1 = MultiplicativeExpression()
?  {
? ? ?newTemp = str1;
?  }
?  (
? ?  (
? ? ? ?op = "+"
? ? ?| op = "-"
? ?  )
? ?str2 = MultiplicativeExpression()
?  {
? ? ?newTemp = VariableNameGenerator.genVariableName();
? ? ?QTInfo qt = new QTInfo(op.image,str1,str2,newTemp);
? ? ?qtList.addQTInfo(qt);
? ? ?str1 = newTemp;
?  }
?  )*
?  {
? ? ?return newTemp;
?  }
?}
??
?String MultiplicativeExpression() :
?{
? ?String str1,str2;
? ?String newTemp;
? ?Token op;
?}
?{
? ?str1 = UnaryExpression()
?  {
? ? ?newTemp = str1;
?  }
?  (
? ?  (
? ? ? ?op = "*"
? ? ?| op = "/"
? ? ?| op = "%"
? ?  )
? ?str2 = UnaryExpression()
?  {
? ? ?newTemp = VariableNameGenerator.genVariableName();
? ? ?QTInfo qt = new QTInfo(op.image,str1,str2,newTemp);
? ? ?qtList.addQTInfo(qt);
? ? ?str1 = newTemp;
?  }
?  )*
?  {
? ? ?return newTemp;
?  }
?}
??
?String UnaryExpression() :
?{String str = null;}
?{
?    (
?    
?        "(" str = Expression() ")"
?        | str = Identifier()
?        | str = Integer()
?        | str = Constant()
?    )
?    {
?     ?return str;
?    }
?}
??
??
?String Identifier() :
?{Token t = null;}
?{
? ?t = < IDENTIFIER >
?  {
? ? ?return t.image;
?  }
?}
??
?String Integer() :
?{Token t = null;}
?{
? ?t = < INTEGER_LITERAL >
?  {
? ? ?return t.image;
?  }
?}
?String Constant() :
?{Token t =null;}
?{
? ?t = < CONSTANT >
?  {
? ? ?return t.image;
?  }
?}
??
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-01-17 11:36:04  更:2022-01-17 11:36:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:45:36-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码