基于Java语言的语法分析器
LR(0)语法分析器
- 实验目的:
根据LR(0)语法分析的原理,编写、调试一个语法分析代码程序,对输入的句子进行分析。
- 实验工具:
使用了Java语言进行编写 ,使用Java开发工具IntelliJ IDEA 。
- 实验过程分析:
3.1、进行对LR(0)语法分析过程的深入了解。首先我们需要在文件data. txt中保存我们想要分析的文法。(这里展示的是课本例题6.1)
3.2、利用Java文件读取类进行读取文件data. txt(如下伪代码)
BufferedReader bf = new BufferedReader(new FileReader(“这里输入文件地址”));
然后使用bf.readLine()就可以按行读取出文件中的句子。 String p = "";while((p = bf.readLine()) != null){…要进行的操作…}
3.3、读取之后,使用数据结构数组保存非总结符和总结符。
结果输出:
3.4、同时利用链表left 和 right 保存文法的左右两部分,比如S’->S
Left链表就保存 S’,right链表就保存S。
3.5、之后,我们需要输出所有的加黑点的文法,这一步比较简单,直接遍历left和right ,然后根据right的长度进行移动黑点,再输出即可。
3.6、在这之后,我们需要构造出所有的状态来,来构造DFA,为此,我专门自定义了一个类,叫做DFA ,具体属性如图所示,可以完美表示单个状态,然后我们使用List<DFA>ok 用来保存整个状态连接图!
3.7、在对于状态图的构建上,我们的思路是,先把文法拓展一下,放入 S’->S 进入第1个状态,也就是T0,然后根据黑点的右部首个字符,如果他属于非终结符,意味着我们要拓展这个状态!这里拓展状态的算法是使用了递归回溯算法。
最终在不懈的努力下,完成了各个状态的保存,以及状态的转移:
3.8、接下来我们便需要构建LR(0)分析表了,我们知道LR(0)分析表包含了Action 表 和 Goto表,这里保存他们需要选择好的数据结构来保存。思来想去,最后还是选择了HashMap内置HashMap来保存数据。
我们根据所有的状态来进行遍历,同时在内部遍历一下终结符和非终结符的状态转移,也就是每个DFA对象的next中的数据,就可以将其保存。然后再输出时候,使用System.out.printf(“%-ns”); 来进行n位缩进,这样子输出来更好看。
3.9、最后,我们使用了while()循环输入一段句子,在句子最后判断有无#,加上它,然后进行语法分析。如果再分析过程,我们的HashMap中对应的值为空了,说明分析不对。具体情况如下:
如果输入的句子分析正确,我们就开始输出啦,对于数据的保存,我们又自定义了一个类,然后再对这个类进行对象数组的构建,用来保存一整个表:
4、实验结论:
此次实验,其实原理并不困难,难的是,将原理用代码展示出来,我们需要选择合适的数据结构还有算法才可以进行,这也应证了那句“程序 = 数据结构 + 算法“,总之,通过此次实验,我们学到了很多语法分析的知识,对于其分析过程有了很深入的了解。
5、最终效果:
6、最终代码:
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.*;
import java.util.logging.Level;public class Main {public static List<String> left;public static List<String> right;//产生式 比如 :A -> a//构造dfapublic static List<DFA> ok; //已经搞好的dfapublic static Map<Integer,Map<Character,String>>Action;public static Map<Integer,Map<Character,Integer>>Goto;public static Map<String,Integer> R; //第几条产生式规约public static boolean is[];public static char ZhongJie[]; //保存终结符public static char FeiZhongJie[]; //保存非终结符public static int ZhongJieNum = 0;public static int FeiZhongJieNum = 0;public static class DFA{Integer id;List<String> DFAleft;List<String> DFAright;Map<Character,Integer> next;public DFA(){}public DFA(Integer id, List<String> DFAleft, List<String> DFAright, Map<Character, Integer> next) {this.id = id;this.DFAleft = DFAleft;this.DFAright = DFAright;this.next = next;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public List<String> getDFAleft() {return DFAleft;}public void setDFAleft(List<String> DFAleft) {this.DFAleft = DFAleft;}public List<String> getDFAright() {return DFAright;}public void setDFAright(List<String> DFAright) {this.DFAright = DFAright;}public Map<Character, Integer> getNext() {return next;}public void setNext(Map<Character, Integer> next) {this.next = next;}}//打开文件,将所有的产生式存进List数据结构public static void OpenFile() throws Exception{left.add("S'");right.add("S");String property = System.getProperty("user.dir");BufferedReader bf = new BufferedReader(new FileReader(property+"\\data.txt"));String p = "";while((p = bf.readLine()) != null){for(int k = 0;k<p.length();k++){char ch = p.charAt(k);if(is[ch]){continue;}if(ch >= 'A' && ch <= 'Z'){ //非终结符FeiZhongJie[FeiZhongJieNum++] = ch;}else { //终结符if(ch != '-' && ch != '>')ZhongJie[ZhongJieNum++] = ch;}is[ch] = true;}String a[] = p.split("->");String b[] = a[1].split("\\|");for(int i = 0;i<b.length;i++){left.add(a[0]);right.add(b[i]);}}bf.close();}//在头部加点public static String addFirstPoint(String str){return "."+str;}public static int getPointPosition(String str){return str.indexOf(".");}//往右边移动点public static String movePoint(String str){if(getPointPosition(str) != str.length()-1){String[] a = str.split("\\.");String newStr = a[0]+a[1].charAt(0)+"."+a[1].substring(1);return newStr;}return str;}//public static void OutWenFa() throws Exception{R = new HashMap<>();OpenFile();for(int i = 0;i<left.size();i++){String s = left.get(i) + "->" + right.get(i);R.put(s,i);System.out.println(s);}System.out.println("----------------------------------------------------------------");}public static void OutJiaDianWenFa(){for(int i = 0;i<left.size();i++){String a1 = left.get(i);String a2 = addFirstPoint(right.get(i));while(getPointPosition(a2) != a2.length()-1){System.out.println(a1+"->" + a2);a2 = movePoint(a2);}System.out.println(a1+"->" + a2);}System.out.println("----------------------------------------------------------------");}//扩展非终结符X的项目public static boolean isok[] = new boolean[1001];public static void soloveTuoZhanDFA(List<String> le , List<String>ri ,String X){int size = left.size();for(int i = 0;i<size;i++){if(X.equals(left.get(i))){ // 如果le.add(left.get(i)); // 添加左边的ri.add(addFirstPoint(right.get(i)));//添加右边的if(right.get(i).charAt(0) >= 'A' && right.get(i).charAt(0) <= 'Z' && !isok[right.get(i).charAt(0)]){String nextStr = ""+right.get(i).charAt(0);isok[right.get(i).charAt(0)] = true;soloveTuoZhanDFA(le,ri,nextStr);}}}}public static void TuozhanDFA(DFA dfa){ //拓展dfaList<String> dfAright = dfa.getDFAright();int lenth = dfAright.size();List<String> dfaLeft = new LinkedList<>();List<String> dfaRight = new LinkedList<>();for(int l = 0;l<lenth;l++){String rg = dfAright.get(l);int len = rg.length();int pos = getPointPosition(rg);if(pos < len-1 && rg.charAt(pos+1) >= 'A' && rg.charAt(pos+1) <= 'Z'){String Arg = ""+rg.charAt(pos+1);Arrays.fill(isok,false);isok[Arg.charAt(0)] = true;soloveTuoZhanDFA(dfaLeft,dfaRight,Arg);int sz = dfaLeft.size();for(int i = 0;i<sz;i++){dfa.getDFAleft().add(dfaLeft.get(i));dfa.getDFAright().add(dfaRight.get(i));}}}}
// 状态public static void OutZhuangTai(){//先新建一个S'->S吧。。。、List<String> firstLeft = new LinkedList<>();List<String> firstRight = new LinkedList<>();firstLeft.add("S'");firstRight.add(addFirstPoint("S"));DFA dfa = new DFA();dfa.setDFAleft(firstLeft);dfa.setDFAright(firstRight);ok.add(dfa);TuozhanDFA(dfa);}public static int QuChuChongFu(){ //去除重复int sz = ok.size();for(int i =0;i<sz-1;i++){if(ok.get(i).getDFAleft().get(0).equals(ok.get(sz-1).getDFAleft().get(0)) &&ok.get(i).getDFAright().get(0).equals(ok.get(sz-1).getDFAright().get(0))){ok.remove(sz-1);return i;}}return -1;}public static void createNewDFA(String le,String ri){ //创建新的状态DFA dfa = new DFA();ri = movePoint(ri);dfa.setId(ok.size());List<String> LEFT = dfa.getDFAleft() == null ? new LinkedList<>() : dfa.getDFAleft();List<String> RIGHT = dfa.getDFAright() == null ? new LinkedList<>() : dfa.getDFAright();LEFT.add(le);RIGHT.add(ri);dfa.setDFAleft(LEFT);dfa.setDFAright(RIGHT);ok.add(dfa);}public static boolean Exist[] = new boolean[1001];public static void AddNewZhuangTai(){for(int i = 0;i<ok.size();i++){Arrays.fill(Exist,false);for(int j = 0;j<ok.get(i).getDFAleft().size();j++){String riStr = ok.get(i).getDFAright().get(j);if(riStr.indexOf(".") == riStr.length()-1){break;//不可以移动黑点}int pointPosition = getPointPosition(riStr);char c = riStr.charAt(pointPosition+1);if(Exist[c]){continue;}createNewDFA(ok.get(i).getDFAleft().get(j),ok.get(i).getDFAright().get(j));Exist[c] = true;for(int k = j+1;k<ok.get(i).getDFAleft().size();k++){String s = ok.get(i).getDFAright().get(k);if(s.indexOf(".") == s.length()-1){continue;}int pointPosition1 = getPointPosition(s);if(s.charAt(pointPosition1+1) == c){String s1 = ok.get(i).getDFAleft().get(k);String s2 = ok.get(i).getDFAright().get(k);s2 = movePoint(s2);ok.get(ok.size()-1).getDFAleft().add(s1);ok.get(ok.size()-1).getDFAright().add(s2);System.out.println(s1+"===>"+s2);}}int chong = QuChuChongFu();if(chong == -1){TuozhanDFA(ok.get(ok.size()-1));///用第一行拓展int dotpos = getPointPosition(riStr);Map<Character,Integer> map = ok.get(i).getNext() == null ? new HashMap<>() : ok.get(i).getNext();map.put(riStr.charAt(dotpos+1) , ok.size()-1);ok.get(i).setNext(map);}else{int dotpos = getPointPosition(riStr);Map<Character,Integer> map = ok.get(i).getNext() == null ? new HashMap<>() : ok.get(i).getNext();map.put(riStr.charAt(dotpos+1) , chong);ok.get(i).setNext(map);}}}}public static void PrintZhuangTai(){System.out.println("--------所有的状态--------");int size = ok.size();for(int i = 0;i<size;i++){System.out.println("I"+i+":");for(int j = 0;j<ok.get(i).getDFAleft().size();j++){System.out.println(ok.get(i).getDFAleft().get(j) + " -> " + ok.get(i).getDFAright().get(j));}System.out.println("-------------------");}}public static void OutBiaoLine(){ //输出表的行线System.out.print("-------");for(int i = 0;i<FeiZhongJieNum+ZhongJieNum;i++){System.out.print("-------");}System.out.println("-");}public static void PrintShu(){System.out.print("|");}public static void PrintBiao(){OutBiaoLine();//输出表的行线PrintShu();System.out.printf("%-5s"," 状态");for(int i = 0;i<ZhongJieNum;i++){PrintShu();System.out.printf("%-6s"," "+ZhongJie[i]);}for(int i = 0;i<FeiZhongJieNum;i++){PrintShu();System.out.printf("%-6s"," "+FeiZhongJie[i]);}System.out.println("|");// for(int i = 0;i<ok.size();i++){ // 测试输出Action
// Map<Character, String> characterStringMap = Action.get(i);
// for(int j = 0;j<ZhongJieNum;j++){
// char ch = ZhongJie[j];
// String s = characterStringMap.get(ch);
// System.out.print(s+" ");
// }
// System.out.println();
// }
// System.out.println("Goto");
// for(int i = 0;i<ok.size();i++){ //测试输出Goto
// Map<Character, Integer> characterStringMap = Goto.get(i);
// for(int j = 0;j<FeiZhongJieNum;j++){
// char ch = FeiZhongJie[j];
// int s = characterStringMap.get(ch);
// System.out.print(s+" ");
// }
// System.out.println();
// }for(int i = 0;i<ok.size();i++){OutBiaoLine();PrintShu();System.out.printf("%-6s"," "+i);for(int j = 0;j<ZhongJieNum;j++){char ch = ZhongJie[j];if(Action.get(i).get(ch).equals("-1")){PrintShu();System.out.print(" ");}else{PrintShu();System.out.printf("%-6s"," "+Action.get(i).get(ch));}}for(int j = 0;j<FeiZhongJieNum;j++){char ch = FeiZhongJie[j];if(Goto.get(i).get(ch) != -1){PrintShu();System.out.printf("%-6s"," "+Goto.get(i).get(ch));}else{PrintShu();System.out.print(" ");}}System.out.println("|");}OutBiaoLine();}public static void GouJianACTION(){ //构造ACTION表Action = new HashMap<>();for(int i = 0;i<ok.size();i++){Map<Character,String> ac = new HashMap<>();for(int j = 0;j<ZhongJieNum;j++){char ch = ZhongJie[j];if(i == 1){if(ch == '#'){ac.put(ch,"acc");}else{ac.put(ch,"-1");}continue;}if(ok.get(i).getNext() == null){String s = ""+ok.get(i).getDFAleft().get(0)+"->"+ok.get(i).getDFAright().get(0);s = s.substring(0,s.length()-1);ac.put(ch,"r"+R.get(s));continue;}if(ok.get(i).getNext().containsKey(ch)){ac.put(ch,"s"+ok.get(i).getNext().get(ch));}else{ac.put(ch,"-1");}}Action.put(i,ac);}}public static void GouJianGoto(){//构建Goto表Goto = new HashMap<>(); // Map<Integer,Map<Character,Integer>>Goto;for(int i = 0;i<ok.size();i++){Map<Character,Integer> ac = new HashMap<>();for(int j = 0;j<FeiZhongJieNum;j++){char ch = FeiZhongJie[j];if(ok.get(i).getNext() == null || ok.get(i).getNext().get(ch) == null){ac.put(ch,-1);continue;}Integer integer = ok.get(i).getNext().get(ch);ac.put(ch,integer);}Goto.put(i,ac);}}public static void OutZhong(){ //输出终结符和非终结符....System.out.print("非终结符:");for(int i = 0;i<FeiZhongJieNum;i++){System.out.print(FeiZhongJie[i]+" ");}System.out.println();System.out.print("终结符:");ZhongJie[ZhongJieNum++] = '#';for(int i = 0;i<ZhongJieNum;i++){System.out.print(ZhongJie[i]+" ");}System.out.println();}public static void PrintZhuangTaiZhuanYi(){for(int i = 0;i<ok.size();i++){Map<Character, Integer> next = ok.get(i).getNext();if(next != null){for(Character key : next.keySet()){Integer to = next.get(key);System.out.println("状态T"+i+"----"+key+"------>状态T"+to);}}}}public static class GuoCheng{String ZhuanTai;String FuHao;String ShuRuChuan;String Action;Integer goTo;public GuoCheng() {}public String getZhuanTai() {return ZhuanTai;}public void setZhuanTai(String zhuanTai) {ZhuanTai = zhuanTai;}public String getFuHao() {return FuHao;}public void setFuHao(String fuHao) {FuHao = fuHao;}public String getShuRuChuan() {return ShuRuChuan;}public void setShuRuChuan(String shuRuChuan) {ShuRuChuan = shuRuChuan;}public String getAction() {return Action;}public void setAction(String action) {Action = action;}public Integer getGoTo() {return goTo;}public void setGoTo(Integer goTo) {this.goTo = goTo;}}public static String StackToString(Stack st){String s = st.toString();String[] split = s.substring(1, s.length() - 1).split(", ");String ans = "";for(int i = split.length-1;i>=0;i--){ans+=split[i];}return ans;}public static void find(String str){ //对输入串的分析Stack<Character> Shuruchuan = new Stack<>();//这是输入串的栈 abb#GuoCheng mp[] = new GuoCheng[1001]; //穿它个1000个int num = 0;Stack<Integer> ZhuangTai = new Stack<>(); //这是状态 0345....Stack<Character> Fuhao = new Stack<>();//这是符号的栈for(int i = str.length()-1;i>=0;i--){Shuruchuan.add(str.charAt(i)); //加进去}ZhuangTai.add(0);Fuhao.add('#');while(true){mp[num] = new GuoCheng();StringBuffer sf = new StringBuffer(StackToString(ZhuangTai));mp[num].setZhuanTai(sf.reverse().toString());//状态放进入输出sf = new StringBuffer(StackToString(Fuhao));mp[num].setFuHao(sf.reverse().toString());//符号放进入输出mp[num].setShuRuChuan(StackToString(Shuruchuan));//符号放进入输出char ch = Shuruchuan.peek(); //取出首个字符int pi = ZhuangTai.peek(); //取出栈顶的状态Map<Character, String> map = Action.get(pi);String s = map.get(ch);if(s.equals("-1")){System.out.println("输入串不符合LR(0)的规则,请重新输入...");return ;}mp[num].setAction(s);if(s.charAt(0) == 's'){int Jin = s.charAt(1)-'0';Shuruchuan.pop();ZhuangTai.add(Jin);Fuhao.add(ch);}else if(s.charAt(0) == 'r'){int Jin = s.charAt(1) - '0';String s1 = left.get(Jin);String s2 = right.get(Jin);for(int k = 0;k<s2.length();k++){ZhuangTai.pop();Fuhao.pop();}ch = s1.charAt(0);Jin = ZhuangTai.peek();Map<Character, Integer> map1 = Goto.get(Jin);Jin = map1.get(ch);ZhuangTai.add(Jin);Fuhao.add(ch);mp[num].setGoTo(Jin);}num++;if(mp[num-1].getAction() .equals("acc")){break;}}System.out.println("---------字符串"+str+"的分析过程:---------");PrintLine();System.out.printf("%-14s","| 步骤");System.out.printf("%-13s","| 状态栈");System.out.printf("%-13s","| 符号栈");System.out.printf("%-13s","| 输入串");System.out.printf("%-16s","| ACTION");System.out.printf("%-16s","| GOTO");System.out.println("|");PrintLine();for(int i = 0;i<num;i++){String kk = "| ";System.out.printf("%-16s",kk+i);System.out.printf("%-16s",kk+mp[i].getZhuanTai());System.out.printf("%-16s",kk+mp[i].getFuHao());System.out.printf("%-16s",kk+mp[i].getShuRuChuan());System.out.printf("%-16s",kk+mp[i].getAction());System.out.printf("%-16s",kk+mp[i].getGoTo());System.out.println("|");PrintLine();}}public static void PrintLine(){for(int i = 0;i< 6;i++){System.out.print("----------------");}System.out.println();}public static String add(String str){if(str.charAt(str.length()-1) != '#'){str+="#";}return str;}public static String str;public static void In(){Scanner cin = new Scanner(System.in);while(true){System.out.print("请输入待分析的字符串:");str = cin.next();if(str.equals("stop")){break;}str = add(str);find(str);}}public static void main(String[] args) throws Exception {System.out.println("--------------制作人----------------");System.out.println("| 姓名 | 学号 | 班级 |");System.out.println("| 吴锦坤 | 2020611107 | 20计算机 |");System.out.println("| 温金宝 | 2020611106 | 20计算机 |");System.out.println("| 谢宇琛 | 2020611109 | 20计算机 |");System.out.println("| 王文杰 | 2020611105 | 20计算机 |");System.out.println("| 张展航 | 2020611117 | 20计算机 |");System.out.println("-----------------------------------");System.out.println("本实验以例题6.1作报告。当然,只需要改变data.txt中的文法就可以实现任何LR(0)语法分析!");left = new LinkedList<>();right = new LinkedList<>();ok = new LinkedList<>();is = new boolean[1001];ZhongJie = new char[1001];FeiZhongJie = new char[1001];
// System.out.println("Hello world!");System.out.println("拓广文法为:");OutWenFa();System.out.println("终结符与非终结符:");OutZhong();System.out.println("加点的文法:");OutJiaDianWenFa();//解决状态OutZhuangTai();
// 添加新的状态AddNewZhuangTai();//输出所有的状态PrintZhuangTai();System.out.println("--------------状态转移-----------------");PrintZhuangTaiZhuanYi();//累寄了,终于可以开始建表了.......System.out.println(" LR(0)分析表:");GouJianACTION();//构建action表GouJianGoto(); //构建Goto表//输出分析表PrintBiao();//解决分析过程!!完结撒花,嘿嘿嘿In();}
}
需要源文件的可以联系我
基于Java语言的语法分析器相关推荐
- 基于c语言的语法分析器的实现
一. 总体实现思想 我采用自顶向下的预测分析技术来实现,其基本方法如下: 从文法开始符号出发,在每一步推导过程中根据当前句型的最左非终结符A和当前输入符号a,选择正确的A-产生式.为保证分析的确定性, ...
- 《编译原理》实验报告——基于YACC的TINY语法分析器的构建
一.实验要求 运用YACC,针对TINY语言,构造一个语法分析器.给出实验方案,实施并描述结果. 二.实验方案 (1)设计基于LEX的TINY词法分析器 (2)设计基于YACC的TINY语法分析器 ( ...
- 编译原理——实验叁——基于YACC的TINY语法分析器的构建
一. 实验要求 运用YACC,针对TINY语言,构造一个语法分析器.给出实验方案,实施并描述结果. 二. 实验方案 (1)设计基于YACC的TINY词法分析器 (2)设计基于LEX的TINY语法分析器 ...
- 编译原理——实验叁预习报告——基于YACC的TINY语法分析器的构建
一.实验目的: 运用YACC,针对给定的文法,构造一个语法分析器.给出实验方案,实施并描述结果. 二.实验预习提示 1.表达:针对5.5节中的calculator文法,设计输入和输出 2.观察:观察p ...
- Leetcode刷题第1题:两数之和(基于Java语言)
** Leetcode刷题第1题:两数之和(基于Java语言) ** 题目: 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标 ...
- Leetcode刷题 463题:岛屿的周长(基于Java语言)
** Leetcode刷题 463题:岛屿的周长(基于Java语言) ** 一. 题目描述: 给定一个包含 0 和 1 的二维网格地图,其中 1 表示陆地 0 表示水域. 网格中的格子水平和垂直方向相 ...
- 基于Java语言构建区块链(一)—— 基本原型
最终内容请以原文为准:https://wangwei.one/posts/df1... 引言 区块链技术是一项比人工智能更具革命性的技术,人工智能只是提高了人类的生产力,而区块链则将改变人类社会的生产 ...
- java 计算移动平均线_基于Java语言开发的个性化股票分析技术:移动平均线(MA)...
基于Java语言开发的个性化股票分析技术:移动平均线(MA) 基于 Java 语言开发的个性化股票分析技术:移动平均线(MA)移动平均线(MA)是以道·琼斯的"平均成本概念"为理论 ...
- 基于Java语言构建区块链(四)—— 交易(UTXO)
基于Java语言构建区块链(四)-- 交易(UTXO) 2018年03月11日 00:48:01 wangwei_hz 阅读数:909 标签: 区块链比特币 更多 个人分类: 区块链 文章的主要思想和 ...
最新文章
- 马化腾六年后知乎再提问:未来十年哪些基础科学突破会影响互联网科技产业?...
- java 字符串拼接优化_JAVA字符串拼接效率
- xmanager 3 远程连接REDHAT 4 桌面
- Java hashCode() 和 equals()的若干问题解答
- 拓端tecdat|SAS中用单因素ANOVA研究不同疗法对焦虑症的有效性
- 00023 自考高等数学
- 第四章——数据库安全性
- HTML实例—以一个简单网页为例
- 等保安全计算环境之Windows(身份鉴别+访问控制)(二级)
- 智能电视硬件架构设计——整机研发
- Qt 免注册版本下载
- cos和sin的使用
- Nature Neuroscience:边中心功能网络模型下大脑系统水平的重叠组织构架
- 解读企业领域热词——BYOD
- unity C#脚本介绍
- 工业大数据分析,主要有哪些应用?
- Redux 入门教程,应用的状态管理器
- 3dmax顶点动画导入unity_3DMAX点缓存的动画怎么导入unity呀?
- 用C语言实现复数和相量的四则运算和相互转化
- 高德地图聚合android,GitHub - lingyanluoxue/android-togetherMap: 实现高德地图的marker聚合功能...
热门文章
- Quick BI移动端:让数据在更多业务场景中流通
- 国内常见的一些代码托管平台
- Android自定义控件-仿淘宝ios客户端天猫商品详情界面
- 面试必备:《Java 最常见 200+ 面试题全面解析》
- kendoUI系列教程之DropDownList下拉菜单
- 信仰:生或者死——读海子、史铁生
- 为什么element ui 中表单验证validate验证成功不执行验证成功的逻辑代码
- 2021清远市清城中学高考成绩查询,清远市清城中学中考成绩
- [Setting]win7下运行exe失败:应用程序无法启动,因为应用程序的并行配置不正确
- 相关系数R-判定系数R方的matlab实现