├── grammer
├── a4.txt
├── a2.txt
├── a3.txt
├── a1.txt
└── a5.txt
├── .idea
├── .gitignore
├── vcs.xml
├── misc.xml
├── modules.xml
└── uiDesigner.xml
├── README.md
├── 实验报告.doc
├── .DS_Store
├── out
└── production
│ └── Lexer-Parser-master
│ ├── META-INF
│ └── Lexer-Parser-master.kotlin_module
│ ├── Main.class
│ ├── lr0
│ ├── IE.class
│ ├── Grammar.class
│ ├── LR0Main.class
│ ├── Grammar$1.class
│ └── Production.class
│ ├── compile
│ ├── Lexer.class
│ ├── Parser.class
│ ├── Parser$1.class
│ ├── MainComplier.class
│ └── MainComplier$ActListener.class
│ ├── frame
│ ├── OutText.class
│ └── ReadText.class
│ ├── pojo
│ ├── TokenList.class
│ ├── MultiComment.class
│ └── SingleComment.class
│ ├── window
│ ├── OutText.class
│ └── ReadText.class
│ └── entity
│ ├── TokenList.class
│ ├── MultiComment.class
│ └── SingleComment.class
├── src
├── .DS_Store
├── Main.java
├── window
│ ├── ReadText.java
│ └── OutText.java
├── frame
│ ├── ReadText.java
│ └── OutText.java
├── pojo
│ ├── SingleComment.java
│ ├── MultiComment.java
│ └── TokenList.java
├── entity
│ ├── SingleComment.java
│ ├── MultiComment.java
│ └── TokenList.java
├── lr0
│ ├── IE.java
│ ├── LR0Main.java
│ ├── Production.java
│ └── Grammar.java
└── compile
│ ├── MainComplier.java
│ ├── Lexer.java
│ └── Parser.java
├── 文法测试.txt
├── Lexer-Parser.iml
└── Lexer-Parser-master.iml
/grammer/a4.txt:
--------------------------------------------------------------------------------
1 | S→AaS|a
2 | A→a
--------------------------------------------------------------------------------
/grammer/a2.txt:
--------------------------------------------------------------------------------
1 | S→AaS|BbS|d
2 | A→a
3 | B→ε|c
--------------------------------------------------------------------------------
/grammer/a3.txt:
--------------------------------------------------------------------------------
1 | X→ABCd
2 | A→a|ε
3 | B→b|ε
4 | C→c|ε
--------------------------------------------------------------------------------
/grammer/a1.txt:
--------------------------------------------------------------------------------
1 | E→T|E+T|E-T
2 | T→F|T*F|T/F
3 | F→(E)|i
--------------------------------------------------------------------------------
/grammer/a5.txt:
--------------------------------------------------------------------------------
1 | E->aA|bB
2 | C->ε
3 | A->cA|d
4 | B->cB|d
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | #
2 | ## 编译原理课程设计,包含词法分析程序、LL1语法分析程序、LR0语法分析程序。
3 | ## SDUST编译原理实践结课作业。
4 |
--------------------------------------------------------------------------------
/实验报告.doc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielSun11/CourseDesignofCompiling/HEAD/实验报告.doc
--------------------------------------------------------------------------------
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielSun11/CourseDesignofCompiling/HEAD/.DS_Store
--------------------------------------------------------------------------------
/out/production/Lexer-Parser-master/META-INF/Lexer-Parser-master.kotlin_module:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielSun11/CourseDesignofCompiling/HEAD/src/.DS_Store
--------------------------------------------------------------------------------
/out/production/Lexer-Parser-master/Main.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielSun11/CourseDesignofCompiling/HEAD/out/production/Lexer-Parser-master/Main.class
--------------------------------------------------------------------------------
/out/production/Lexer-Parser-master/lr0/IE.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielSun11/CourseDesignofCompiling/HEAD/out/production/Lexer-Parser-master/lr0/IE.class
--------------------------------------------------------------------------------
/out/production/Lexer-Parser-master/lr0/Grammar.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielSun11/CourseDesignofCompiling/HEAD/out/production/Lexer-Parser-master/lr0/Grammar.class
--------------------------------------------------------------------------------
/out/production/Lexer-Parser-master/lr0/LR0Main.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielSun11/CourseDesignofCompiling/HEAD/out/production/Lexer-Parser-master/lr0/LR0Main.class
--------------------------------------------------------------------------------
/out/production/Lexer-Parser-master/compile/Lexer.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielSun11/CourseDesignofCompiling/HEAD/out/production/Lexer-Parser-master/compile/Lexer.class
--------------------------------------------------------------------------------
/out/production/Lexer-Parser-master/compile/Parser.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielSun11/CourseDesignofCompiling/HEAD/out/production/Lexer-Parser-master/compile/Parser.class
--------------------------------------------------------------------------------
/out/production/Lexer-Parser-master/frame/OutText.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielSun11/CourseDesignofCompiling/HEAD/out/production/Lexer-Parser-master/frame/OutText.class
--------------------------------------------------------------------------------
/out/production/Lexer-Parser-master/frame/ReadText.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielSun11/CourseDesignofCompiling/HEAD/out/production/Lexer-Parser-master/frame/ReadText.class
--------------------------------------------------------------------------------
/out/production/Lexer-Parser-master/lr0/Grammar$1.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielSun11/CourseDesignofCompiling/HEAD/out/production/Lexer-Parser-master/lr0/Grammar$1.class
--------------------------------------------------------------------------------
/out/production/Lexer-Parser-master/lr0/Production.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielSun11/CourseDesignofCompiling/HEAD/out/production/Lexer-Parser-master/lr0/Production.class
--------------------------------------------------------------------------------
/out/production/Lexer-Parser-master/pojo/TokenList.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielSun11/CourseDesignofCompiling/HEAD/out/production/Lexer-Parser-master/pojo/TokenList.class
--------------------------------------------------------------------------------
/out/production/Lexer-Parser-master/window/OutText.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielSun11/CourseDesignofCompiling/HEAD/out/production/Lexer-Parser-master/window/OutText.class
--------------------------------------------------------------------------------
/out/production/Lexer-Parser-master/window/ReadText.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielSun11/CourseDesignofCompiling/HEAD/out/production/Lexer-Parser-master/window/ReadText.class
--------------------------------------------------------------------------------
/out/production/Lexer-Parser-master/compile/Parser$1.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielSun11/CourseDesignofCompiling/HEAD/out/production/Lexer-Parser-master/compile/Parser$1.class
--------------------------------------------------------------------------------
/out/production/Lexer-Parser-master/entity/TokenList.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielSun11/CourseDesignofCompiling/HEAD/out/production/Lexer-Parser-master/entity/TokenList.class
--------------------------------------------------------------------------------
/out/production/Lexer-Parser-master/pojo/MultiComment.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielSun11/CourseDesignofCompiling/HEAD/out/production/Lexer-Parser-master/pojo/MultiComment.class
--------------------------------------------------------------------------------
/out/production/Lexer-Parser-master/compile/MainComplier.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielSun11/CourseDesignofCompiling/HEAD/out/production/Lexer-Parser-master/compile/MainComplier.class
--------------------------------------------------------------------------------
/out/production/Lexer-Parser-master/entity/MultiComment.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielSun11/CourseDesignofCompiling/HEAD/out/production/Lexer-Parser-master/entity/MultiComment.class
--------------------------------------------------------------------------------
/out/production/Lexer-Parser-master/entity/SingleComment.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielSun11/CourseDesignofCompiling/HEAD/out/production/Lexer-Parser-master/entity/SingleComment.class
--------------------------------------------------------------------------------
/out/production/Lexer-Parser-master/pojo/SingleComment.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielSun11/CourseDesignofCompiling/HEAD/out/production/Lexer-Parser-master/pojo/SingleComment.class
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/out/production/Lexer-Parser-master/compile/MainComplier$ActListener.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielSun11/CourseDesignofCompiling/HEAD/out/production/Lexer-Parser-master/compile/MainComplier$ActListener.class
--------------------------------------------------------------------------------
/src/Main.java:
--------------------------------------------------------------------------------
1 | import compile.MainComplier;
2 |
3 | import java.io.*;
4 |
5 | public class Main {
6 | public static void main(String[] args)throws IOException {
7 | new MainComplier(); //对象的引用
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/文法测试.txt:
--------------------------------------------------------------------------------
1 | 文法1:
2 | E→T|E+T|E-T
3 | T→F|T*F|T/F
4 | F→(E)|i
5 | 输入:i+i*i
6 |
7 | 文法2:
8 | S→AaS|BbS|d
9 | A→a
10 | B→ε|c
11 | 输入:aabd
12 | 输入:aaaa
13 |
14 | 文法3:
15 | X→ABCd
16 | A→a|ε
17 | B→b|ε
18 | C→c|ε
19 | 输入:abcd
20 |
21 | 文法4. 非LL(1)文法
22 | S→AaS|a
23 | A→a
24 |
25 | 文法5 LR0文法
26 | E->aA|bB
27 | C->ε
28 | A->cA|d
29 | B->cB|d
30 | 输入:bccd
31 |
--------------------------------------------------------------------------------
/src/window/ReadText.java:
--------------------------------------------------------------------------------
1 | package window;
2 |
3 | import java.awt.*;
4 |
5 | /**
6 | * 输入区域,读取文本域的信息
7 | */
8 | public class ReadText extends TextArea{
9 | public ReadText(int rows,int columns) {
10 | setBackground(Color.white);
11 | setForeground(Color.black);
12 | setRows(rows);
13 | setColumns(columns);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/frame/ReadText.java:
--------------------------------------------------------------------------------
1 | package frame;
2 |
3 | import java.awt.*;
4 |
5 | /**
6 | * 输入区域,读取文本域的信息
7 | */
8 | public class ReadText extends TextArea{
9 | public ReadText(int rows,int columns) {
10 | setBackground(Color.white);
11 | setForeground(Color.black);
12 | setRows(rows);
13 | setColumns(columns);
14 |
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/frame/OutText.java:
--------------------------------------------------------------------------------
1 | package frame;
2 |
3 | import java.awt.*;
4 |
5 | /**
6 | * 输出域,将词法分析结果或者语法分析结果输出到这个域中
7 | */
8 | public class OutText extends TextArea{
9 | public OutText(int rows,int columns) {
10 | setBackground(Color.white);
11 | setForeground(Color.black);
12 | setRows(rows);
13 | setColumns(columns);
14 | setFont(new Font("Courier",1,12));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/window/OutText.java:
--------------------------------------------------------------------------------
1 | package window;
2 |
3 | import java.awt.*;
4 |
5 | /**
6 | * 输出域,将词法分析结果或者语法分析结果输出到这个域中
7 | */
8 | public class OutText extends TextArea{
9 | public OutText(int rows,int columns) {
10 | setBackground(Color.white);
11 | setForeground(Color.black);
12 | setRows(rows);
13 | setColumns(columns);
14 | setFont(new Font("Courier",1,12));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Lexer-Parser.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Lexer-Parser-master.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/pojo/SingleComment.java:
--------------------------------------------------------------------------------
1 | package pojo;
2 |
3 | /**
4 | * 用于存储单行注释的信息
5 | */
6 | @SuppressWarnings("all")
7 | public class SingleComment {
8 |
9 | //相关定义
10 | private int row;//行
11 | private int column;//列
12 |
13 | //构造函数
14 | public SingleComment(int row, int column) {
15 | this.row = row;
16 | this.column = column;
17 | }
18 | //生成相应的 get-set方法
19 | public int getRow() {
20 | return row;
21 | }
22 | public void setRow(int row) {
23 | this.row = row;
24 | }
25 | public int getColumn() {
26 | return column;
27 | }
28 | public void setColumn(int column) {
29 | this.column = column;
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/src/entity/SingleComment.java:
--------------------------------------------------------------------------------
1 | package entity;
2 |
3 | /**
4 | * 用于存储单行注释的信息
5 | */
6 | @SuppressWarnings("all")
7 | public class SingleComment {
8 |
9 | //相关定义
10 | private int row;//行
11 | private int column;//列
12 |
13 | //构造函数
14 | public SingleComment(int row, int column) {
15 | this.row = row;
16 | this.column = column;
17 | }
18 | //生成相应的 get-set方法
19 | public int getRow() {
20 | return row;
21 | }
22 | public void setRow(int row) {
23 | this.row = row;
24 | }
25 | public int getColumn() {
26 | return column;
27 | }
28 | public void setColumn(int column) {
29 | this.column = column;
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/src/entity/MultiComment.java:
--------------------------------------------------------------------------------
1 | package entity;
2 |
3 | //专门用来存储多行注释的行列信息,/*存放在奇数位置,*/存放在偶数位置
4 | @SuppressWarnings("all")
5 | public class MultiComment {
6 | private int row;//多行注释的行号
7 | private int column;//多行注释的列号
8 | private String comment;//注释
9 |
10 | //构造方法
11 | public MultiComment(int row,int column,String comment) {
12 | this.row = row;
13 | this.column = column;
14 | this.comment = comment;
15 | }
16 |
17 | //生成相应的get set方法
18 | public void setComment(String comment) {
19 | this.comment = comment;
20 | }
21 | public String getComment() {
22 | return comment;
23 | }
24 | public void setRow(int row) {
25 | this.row = row;
26 | }
27 | public int getRow() {
28 | return row;
29 | }
30 | public void setColumn(int column) {
31 | this.column = column;
32 | }
33 | public int getColumn() {
34 | return column;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/pojo/MultiComment.java:
--------------------------------------------------------------------------------
1 | package pojo;
2 |
3 | //专门用来存储多行注释的行列信息,/*存放在奇数位置,*/存放在偶数位置
4 | @SuppressWarnings("all")
5 | public class MultiComment {
6 | private int row;//多行注释的行号
7 | private int column;//多行注释的列号
8 | private String comment;//注释
9 |
10 | //构造方法
11 | public MultiComment(int row,int column,String comment) {
12 | this.row = row;
13 | this.column = column;
14 | this.comment = comment;
15 | }
16 |
17 | //生成相应的get set方法
18 | public void setComment(String comment) {
19 | this.comment = comment;
20 | }
21 | public String getComment() {
22 | return comment;
23 | }
24 | public void setRow(int row) {
25 | this.row = row;
26 | }
27 | public int getRow() {
28 | return row;
29 | }
30 | public void setColumn(int column) {
31 | this.column = column;
32 | }
33 | public int getColumn() {
34 | return column;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/entity/TokenList.java:
--------------------------------------------------------------------------------
1 | package entity;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | /**
7 | * 定义tocken序列
8 | */
9 | @SuppressWarnings("all")
10 | public class TokenList {
11 |
12 | private List tokenList = new ArrayList<>();//用一个arraylist来存储token序列
13 | private int row;//记录每一行的记号
14 | private List identifier;//为语法分析做准备存储的记号类型
15 |
16 | //第一次实验词法分析所用到的构造函数
17 | public TokenList(int row,List tokenList) {
18 | this.row = row;
19 | this.tokenList = tokenList;
20 | }
21 |
22 | //生成相应的get,set方法
23 | public void setRow(int row) {
24 | this.row = row;
25 | }
26 | public int getRow() {
27 | return row;
28 | }
29 | public void setTokenList(List tokenList) {
30 | this.tokenList = tokenList;
31 | }
32 | public List getTokenList() {
33 | return tokenList;
34 | }
35 |
36 | @Override
37 | public String toString() {
38 | return super.toString();
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/src/pojo/TokenList.java:
--------------------------------------------------------------------------------
1 | package pojo;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | /**
7 | * 定义tocken序列的实体类
8 | */
9 | @SuppressWarnings("all")
10 | public class TokenList {
11 |
12 | private List tokenList = new ArrayList<>();//用一个arraylist来存储token序列
13 | private int row;//记录每一行的记号
14 | private List identifier;//为语法分析做准备存储的记号类型
15 |
16 | //第一次实验词法分析所用到的构造函数
17 | public TokenList(int row,List tokenList) {
18 | this.row = row;
19 | this.tokenList = tokenList;
20 | }
21 |
22 | //生成相应的get,set方法
23 | public void setRow(int row) {
24 | this.row = row;
25 | }
26 | public int getRow() {
27 | return row;
28 | }
29 | public void setTokenList(List tokenList) {
30 | this.tokenList = tokenList;
31 | }
32 | public List getTokenList() {
33 | return tokenList;
34 | }
35 |
36 | @Override
37 | public String toString() {
38 | return super.toString();
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/src/lr0/IE.java:
--------------------------------------------------------------------------------
1 | package lr0;
2 |
3 | public class IE {
4 | //一个项目集到另一个项目集
5 | int orgin;
6 | int aim;
7 | String value;
8 |
9 | public IE(int orgin, String value, int aim) {
10 | this.orgin = orgin;
11 | this.aim = aim;
12 | this.value = value;
13 | }
14 |
15 | @Override
16 | public boolean equals(Object o) {
17 | if (this == o) return true;
18 | if (o == null || getClass() != o.getClass()) return false;
19 |
20 | IE IE = (IE) o;
21 |
22 | if (orgin != IE.orgin) return false;
23 | if (aim != IE.aim) return false;
24 | return value != null ? value.equals(IE.value) : IE.value == null;
25 | }
26 |
27 | @Override
28 | public int hashCode() {
29 | int result = orgin;
30 | result = 31 * result + aim;
31 | result = 31 * result + (value != null ? value.hashCode() : 0);
32 | return result;
33 | }
34 | public String toString(){
35 | return "\nI"+orgin+"--"+value+"-->"+"I"+aim;
36 | }
37 | public int getOrgin() {
38 | return orgin;
39 | }
40 |
41 | public void setOrgin(int orgin) {
42 | this.orgin = orgin;
43 | }
44 |
45 | public int getAim() {
46 | return aim;
47 | }
48 |
49 | public void setAim(int aim) {
50 | this.aim = aim;
51 | }
52 |
53 | public String getValue() {
54 | return value;
55 | }
56 |
57 | public void setValue(String value) {
58 | this.value = value;
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/src/lr0/LR0Main.java:
--------------------------------------------------------------------------------
1 | package lr0;
2 | import frame.OutText;
3 | import frame.ReadText;
4 | import java.io.BufferedReader;
5 | import java.io.File;
6 | import java.io.FileReader;
7 | import java.util.ArrayList;
8 | import java.util.HashSet;
9 |
10 | public class LR0Main {
11 | private static final char Njump = 'ε';
12 |
13 | public static void run(OutText outText, ReadText readText) {
14 | String S="E";//开始符
15 | // String P[]={"E->aA|bB","A->cA|d","B->cB|d"};//规则集
16 | HashSet productionSet = readFile(outText);
17 | String P[]=productionSet.toArray(new String[productionSet.size()]);//规则集
18 |
19 | Grammar G=new Grammar(P,S);
20 | G.out(outText);
21 | if(G.isLRO == false){
22 | outText.append("输入文法不是LR0文法!!\r\n");
23 | return;
24 | }
25 | try {
26 | if(G.contains(readText.getText()) == false){
27 | outText.append("不符合所给的LR0文法 分析失败!!");
28 | }
29 | else{
30 | outText.append("分析成功!!");
31 | }
32 | } catch (Exception e) {
33 | e.printStackTrace();
34 | }
35 | }
36 | public static HashSet readFile(OutText outText) {
37 | BufferedReader br = null;
38 | outText.append("从文件读入的文法为:"+"\r\n");
39 | HashSet result = new HashSet<>();
40 | try {
41 | String path = System.getProperty("user.dir")+File.separator+"grammer"+File.separator;
42 | br = new BufferedReader(new FileReader(path+"a5.txt"));
43 | String s = null;
44 | while ((s = br.readLine()) != null) {
45 | outText.append("\t" + s+"\r\n");
46 | result.add(s.trim());
47 | }
48 | br.close();
49 | } catch (Exception e) {
50 | e.printStackTrace();
51 | }
52 | return result;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/compile/MainComplier.java:
--------------------------------------------------------------------------------
1 | package compile;
2 |
3 | import frame.OutText;
4 | import frame.ReadText;
5 | import lr0.LR0Main;
6 |
7 | import javax.swing.*;
8 | import java.awt.*;
9 | import java.awt.event.*;
10 | import java.io.*;
11 |
12 | /**
13 | * @description 这是主运行窗口
14 | */
15 | @SuppressWarnings("all")
16 | public class MainComplier extends JFrame {
17 |
18 | //UI组件,运行窗口一些按钮
19 | JButton jButton1 = new JButton("词法分析");
20 | JButton jButton2 = new JButton("清空");
21 | JButton jButton3 = new JButton("LL1文法1");
22 | JButton jButton4 = new JButton("LL1文法2");
23 | JButton jButton5 = new JButton("LL1文法3");
24 | JButton jButton6 = new JButton("LL1文法4");
25 | JButton jButton7 = new JButton("LR0文法");
26 |
27 | JLabel inLabel = new JLabel("待分析文件");
28 | JLabel outLabel = new JLabel("分析结果");
29 | ReadText readText = new ReadText(7, 90);//输入区
30 | OutText outText = new OutText(30, 90);//输出区
31 |
32 | //供子类继承使用
33 | public MainComplier(ReadText readText, OutText outText) throws HeadlessException {
34 | this.readText = readText;
35 | this.outText = outText;
36 | }
37 | //事件监听器
38 | public void initListener() {
39 | ActListener actListener = new ActListener();
40 | jButton1.addActionListener(actListener);
41 | jButton2.addActionListener(actListener);
42 | jButton3.addActionListener(actListener);
43 | jButton4.addActionListener(actListener);
44 | jButton5.addActionListener(actListener);
45 | jButton6.addActionListener(actListener);
46 | jButton7.addActionListener(actListener);
47 |
48 | }
49 | //构建事件监听器
50 | class ActListener implements ActionListener {
51 | @Override
52 | public void actionPerformed(ActionEvent e) {
53 | if (e.getSource() == jButton1) {
54 | new Lexer(readText, outText).Analysis();
55 | } else if (e.getSource() == jButton2) {
56 | readText.setText("");
57 | outText.setText("");
58 | } else if (e.getSource() == jButton3) {
59 | new Parser(readText, outText,1).Main();
60 | }
61 | else if (e.getSource() == jButton4) {
62 | new Parser(readText, outText,2).Main();
63 | }
64 | else if (e.getSource() == jButton5) {
65 | new Parser(readText, outText,3).Main();
66 | }
67 | else if (e.getSource() == jButton6) {
68 | new Parser(readText, outText,4).Main();
69 | }
70 | else if(e.getSource() == jButton7){
71 | LR0Main.run(outText,readText);
72 | }
73 | }
74 | }
75 | //主窗口
76 | public MainComplier() throws IOException {
77 | super("词法分析器");
78 | setSize(775, 780);
79 | this.setLocation(400, 70);
80 | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
81 | this.setLayout(new FlowLayout(FlowLayout.CENTER));//中间对齐
82 | this.add(this.inLabel);
83 | this.add(this.readText);
84 | this.add(this.outLabel);
85 | this.add(this.outText);
86 | this.add(this.jButton1);
87 | this.add(this.jButton2);
88 | this.add(this.jButton3);
89 | this.add(this.jButton4);
90 | this.add(this.jButton5);
91 | this.add(this.jButton6);
92 | this.add(this.jButton7);
93 | initListener();
94 | this.setVisible(true);//设置窗口可输入文本
95 | }
96 | }
--------------------------------------------------------------------------------
/src/lr0/Production.java:
--------------------------------------------------------------------------------
1 | package lr0;
2 |
3 | import java.util.ArrayList;
4 |
5 | import static java.util.Arrays.sort;
6 |
7 | public class Production {//语句
8 | private static final char Point = '・';
9 | private static final char Njump = 'ε';
10 | String left;
11 | String right;
12 |
13 | //left->right
14 | public Production(String str) {
15 | String s[] = str.split("->");
16 | left = s[0];
17 | right = s[1];
18 | }
19 | public Production() { }
20 |
21 | public String getLeft() {
22 | return left;
23 | }
24 |
25 | public void setLeft(String left) {
26 | this.left = left;
27 | }
28 |
29 | public String getRight() {
30 | return right;
31 | }
32 |
33 | public void setRight(String right) {
34 | this.right = right;
35 | }
36 |
37 | public boolean isSimple() {
38 | if (right.indexOf("|") == -1)
39 | return true;
40 | else
41 | return false;
42 | }
43 | //简化产生式
44 | public ArrayList toSimple() {
45 | ArrayList productionList = new ArrayList();
46 | String b[] = right.split("\\|");
47 | for (int i = 0; i < b.length; i++) {
48 | // System.out.println(b[i]);
49 | Production ib = new Production(left + "->" + b[i]);
50 | productionList.add(ib);
51 | }
52 | return productionList;
53 | }
54 |
55 | public String toString() {
56 | return left + "->" + right;
57 | }
58 |
59 | public Production insertDian() {//加点
60 | Production a;
61 | if(right.equals(String.valueOf(Njump))){// A->ε 转 A->・
62 | a=new Production(left + "->" + Point);
63 | }else{
64 | a=new Production(left + "->" + Point +right);
65 | }
66 |
67 | return a;
68 | }
69 | public Production deleteDian() {//去除点
70 | Production a=new Production();
71 | a.setLeft(left);
72 | int iD=right.indexOf(Point);
73 | StringBuffer ab=new StringBuffer(right);
74 | ab.deleteCharAt(iD);
75 | if(ab.length()==0){//A->・ 转 A->ε
76 | ab.append(Njump);
77 | }
78 | a.setRight(ab.toString());
79 | return a;
80 | }
81 | public Production moveDian() {//向右移动点
82 | Production a=new Production();
83 | a.setLeft(left);
84 | int iD=right.indexOf(Point);
85 | StringBuffer ab=new StringBuffer(right);
86 | ab.deleteCharAt(iD);
87 | ab.insert(iD+1, Point);
88 | a.setRight(ab.toString());
89 | return a;
90 | }
91 | @Override
92 | public boolean equals(Object obj) {
93 | Production other = (Production) obj;
94 | if(!left.equals(other.left)){
95 | return false;
96 | }
97 | String[] a = right.split("\\|");
98 | sort(a);
99 | String[] b = other.right.split("\\|");
100 | sort(b);
101 | if (a.length == b.length) {
102 | for (int i = 0; i < b.length; i++) {
103 | if (!a[i].equals(b[i]))
104 | return false;
105 | }
106 | return true;
107 | } else {
108 | return false;
109 | }
110 |
111 | }
112 |
113 | @Override
114 | public int hashCode() {//不写的话HashSet认为同一“A->B”生成的Production(值)不相等
115 | int result = 0;
116 | String b[] = right.split("\\|");
117 | for (String ib : b) {
118 | result += ib.hashCode();
119 | }
120 | result += left.hashCode() * 31;
121 | return result;
122 | }
123 |
124 | }
125 |
--------------------------------------------------------------------------------
/.idea/uiDesigner.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | -
6 |
7 |
8 | -
9 |
10 |
11 | -
12 |
13 |
14 | -
15 |
16 |
17 | -
18 |
19 |
20 |
21 |
22 |
23 | -
24 |
25 |
26 |
27 |
28 |
29 | -
30 |
31 |
32 |
33 |
34 |
35 | -
36 |
37 |
38 |
39 |
40 |
41 | -
42 |
43 |
44 |
45 |
46 | -
47 |
48 |
49 |
50 |
51 | -
52 |
53 |
54 |
55 |
56 | -
57 |
58 |
59 |
60 |
61 | -
62 |
63 |
64 |
65 |
66 | -
67 |
68 |
69 |
70 |
71 | -
72 |
73 |
74 | -
75 |
76 |
77 |
78 |
79 | -
80 |
81 |
82 |
83 |
84 | -
85 |
86 |
87 |
88 |
89 | -
90 |
91 |
92 |
93 |
94 | -
95 |
96 |
97 |
98 |
99 | -
100 |
101 |
102 | -
103 |
104 |
105 | -
106 |
107 |
108 | -
109 |
110 |
111 | -
112 |
113 |
114 |
115 |
116 | -
117 |
118 |
119 | -
120 |
121 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/src/compile/Lexer.java:
--------------------------------------------------------------------------------
1 | package compile;
2 |
3 | import entity.MultiComment;
4 | import entity.SingleComment;
5 | import entity.TokenList;
6 | import frame.OutText;
7 | import frame.ReadText;
8 | import java.awt.*;
9 | import java.util.ArrayList;
10 | import java.util.List;
11 | import java.util.StringTokenizer;
12 |
13 | /**
14 | * @description 这是词法分析的具体实现
15 | */
16 | @SuppressWarnings("all")
17 | public class Lexer extends MainComplier{
18 |
19 | //词法分析解释规则,定义字符数组
20 | String[] keyWords = {"if", "else", "while", "for","read", "write", "int", "double","float","public","static","void","main","class"}; //关键字数组
21 | String[] operator = {"+", "-", "*", "/"};//运算符数组
22 | String[] roperator = {">", "<", "==", "!=",">=","<="};//关系运算符数组
23 | String[] sepretor = {";", "{", "}", "(", ")", "."};//分隔符数组
24 |
25 | String RegexToId = "^[a-zA-Z]([a-zA-Z_0-9])*[a-zA-Z0-9]$||[a-zA-Z]";//标识符的正则表达式
26 | String RegexToNumber = "^-?\\d+$";//整数的正则表达式
27 | String RegexToFloat = "^(-?\\d+)(\\.\\d+)?$";//浮点数的正则表达式
28 | String RegexToArray = "[a-zA-Z]+(\\[[0-9][1-9]*\\])+";//数组变量的正则表达式
29 |
30 | //将父类的readText, outText继承过来
31 | public Lexer(ReadText readText, OutText outText) throws HeadlessException {
32 | super(readText, outText);
33 | }
34 |
35 | //分析过程,此处为语法分析和词法分析提供已经修饰过的源程序
36 | public List getTokens() {
37 | List tokenLists = new ArrayList<>();//用于记录Token的信息
38 | String inputText = readText.getText();
39 | StringTokenizer totalStrt = new StringTokenizer(inputText, "\r\n");//用回车与换行区分
40 | int row = 0;//行号
41 | //获取所有的记号以及记号的信息
42 | while (totalStrt.hasMoreTokens()) {
43 | List Tokens = new ArrayList<>();//行记号,一行中所有的Token
44 | StringTokenizer rowOfStrt = new StringTokenizer(totalStrt.nextToken(), " \n\r\t;(){}<>\"\'+-*/=", true);
45 | //所有可能的界符,初步得到所有的Token,但需要进一步的合并
46 | while (rowOfStrt.hasMoreTokens()) {
47 | Tokens.add(rowOfStrt.nextToken());
48 | }
49 | TokenList tokenList = new TokenList(row, Tokens);
50 | tokenLists.add(tokenList);
51 | row++;
52 | }
53 | //对于初步得到的记号集合的进一步判断与整合,用于区别注释和*,/;以及=与==,以及<与<>
54 | for (int i = 0; i < tokenLists.size(); i++) {
55 | List tokenList = tokenLists.get(i).getTokenList();//获取行记号组
56 | for (int j = 0; j < tokenList.size() - 1; j++) {
57 | if (tokenList.get(j).equals("/") && tokenList.get(j + 1).equals("/")) {
58 | //单行注释记号的识别
59 | tokenList.set(j, "//");
60 | tokenList.remove(j + 1);
61 | } else if (tokenList.get(j).equals("/") && tokenList.get(j + 1).equals("*")) {
62 | //多行注释的识别
63 | tokenList.set(j, "/*");
64 | tokenList.remove(j + 1);
65 | } else if (tokenList.get(j).equals("*") && tokenList.get(j + 1).equals("/")) {
66 | //多行注释的识别
67 | tokenList.set(j, "*/");
68 | tokenList.remove(j + 1);
69 | } else if (tokenList.get(j).equals("=") && tokenList.get(j + 1).equals("=")) {
70 | tokenList.set(j, "==");
71 | tokenList.remove(j + 1);
72 | } else if (tokenList.get(j).equals("!") && tokenList.get(j + 1).equals("=")) {
73 | tokenList.set(j, "!=");
74 | tokenList.remove(j + 1);//判断不等于符号
75 | }else if (tokenList.get(j).equals(">") && tokenList.get(j + 1).equals("=")) {
76 | tokenList.set(j, ">=");
77 | tokenList.remove(j + 1);//判断不等于符号
78 | }else if (tokenList.get(j).equals("<") && tokenList.get(j + 1).equals("=")) {
79 | tokenList.set(j, "<=");
80 | tokenList.remove(j + 1);//判断不等于符号
81 | }
82 | }
83 | }
84 | //第二次对记号进行判断整合,主要用于去除各种分隔符
85 | for (int i = 0; i < tokenLists.size(); i++) {
86 | List tokenList = tokenLists.get(i).getTokenList();//获取行记号组
87 | String Pattern = "\\s+|\t|\r\n";//匹配空字符制表符换行符
88 | int j = 0;
89 | while(j multiComments = new ArrayList<>();//存放多行注释的位置信息
103 | List singleComments = new ArrayList<>();//存放单行注释的位置信息
104 | for (int i = 0; i < tokenLists.size(); i++)//多行注释的记号获取
105 | {
106 | List TokenOfrow = tokenLists.get(i).getTokenList();
107 | int rowCount = tokenLists.get(i).getRow();//多行注释行号
108 | for (int j = 0; j < TokenOfrow.size(); j++) {
109 | if (TokenOfrow.get(j).equals("//")) {
110 | SingleComment singleComment = new SingleComment(rowCount, j);
111 | singleComments.add(singleComment);//记录单行注释位置
112 | }
113 | if (TokenOfrow.get(j).equals("/*")) {
114 | MultiComment multiComment = new MultiComment(rowCount, j, "/*");//j为列号
115 | multiComments.add(multiComment);
116 | } else if (TokenOfrow.get(j).equals("*/")) {
117 | MultiComment multiComment = new MultiComment(rowCount, j, "*/");
118 | multiComments.add(multiComment);
119 | }
120 | }
121 | }
122 | for (int i = 0; i < multiComments.size(); i = i + 2)//去除多行注释中的整行注释
123 | {
124 | if ((multiComments.size() % 2) == 0 && i <= multiComments.size() - 2)//判断注释是否未闭合
125 | {
126 | if (multiComments.get(i).getComment().equals("/*") && multiComments.get(i + 1).getComment().equals("*/")) {
127 | int tempj = multiComments.get(i).getRow();
128 | for (int j = multiComments.get(i).getRow() ; j <=multiComments.get(i + 1).getRow(); j++) {
129 | tokenLists.remove(tempj);
130 | }
131 | /*List StartLine = tokenLists.get(multiComments.get(i).getRow()).getTokenList();//注释行起始
132 | List EndLine = tokenLists.get(multiComments.get(i + 1).getRow()).getTokenList();//注释行结束
133 | for (int j = multiComments.get(i).getColumn(); j < StartLine.size(); )//因为随着元素的删除减少,size大小也会发生改变
134 | {
135 | StartLine.remove(j);
136 | }
137 | int position = multiComments.get(i).getColumn();//位置指针
138 | for (int j = 0; j <= position; )//同理,元素的数量的减少导致size改变
139 | {
140 | EndLine.remove(j);
141 | position--;
142 | }*/
143 | }
144 | } else {
145 | outText.append("无法继续分析");
146 | outText.append("第" + multiComments.get(i).getRow() + "行第" + multiComments.get(i).getColumn() + "处的注释未闭合");
147 | return new ArrayList<>();
148 | //break;
149 | }
150 | }
151 | for (int i = 0; i < singleComments.size(); i++) {
152 | List SignleLine = tokenLists.get(singleComments.get(i).getRow()).getTokenList();
153 | for (int j = singleComments.get(i).getColumn(); j < SignleLine.size(); ) {
154 | SignleLine.remove(j);//去除单行注释
155 | }
156 | }
157 | return tokenLists;
158 | }
159 |
160 | //所有的记号处理都做好,此处纯分析记号
161 | public void Analysis() {
162 | List tokenLists = getTokens();
163 | for (int i = 0; i < tokenLists.size(); i++) {
164 | List tokenList = tokenLists.get(i).getTokenList();
165 | int lineid = tokenLists.get(i).getRow();
166 | outText.append("--------------------------------------------------分析第" + (lineid + 1) + "行--------------------------------------------------" + "\r\n");
167 | for (int j = 0; j < tokenList.size(); j++) {
168 | int Count = 0;
169 | for (int k = 0; k < keyWords.length; k++) {
170 | if (tokenList.get(j).equals(keyWords[k])) {
171 | outText.append(tokenList.get(j) + " 是关键字" + "\r\n");
172 | Count++;
173 | }
174 | }
175 | for (int k = 0; k < operator.length; k++) {
176 | if (tokenList.get(j).equals(operator[k])) {
177 | outText.append(tokenList.get(j) + " 是运算符" + "\r\n");
178 | Count++;
179 | }
180 | }
181 | for (int k = 0; k < roperator.length; k++) {
182 | if (tokenList.get(j).equals(roperator[k])) {
183 | outText.append(tokenList.get(j) + " 是关系运算符" + "\r\n");
184 | Count++;
185 | }
186 | }
187 | for (int k = 0; k < sepretor.length; k++) {
188 | if (tokenList.get(j).equals(sepretor[k])) {
189 | outText.append(tokenList.get(j) + " 是分隔符" + "\r\n");
190 | Count++;
191 | }
192 | }
193 | if (tokenList.get(j).matches(RegexToId) && (Count == 0)) {
194 | outText.append(tokenList.get(j) + " 是标识符" + "\r\n");
195 | } else if (tokenList.get(j).matches(RegexToNumber)) {
196 | outText.append(tokenList.get(j) + " 是整数" + "\r\n");
197 | } else if (tokenList.get(j).matches(RegexToFloat)) {
198 | outText.append(tokenList.get(j) + " 是浮点数" + "\r\n");
199 | } else if (tokenList.get(j).matches(RegexToArray)) {
200 | outText.append(tokenList.get(j) + " 是数组变量" + "\r\n");
201 | } else if (tokenList.get(j).equals("=")) {
202 | outText.append(tokenList.get(j) + " 是赋值号" + "\r\n");
203 | } else if (Count == 0) {
204 | outText.append(tokenList.get(j) + " 标识符命名错误" + "\r\n");
205 | }
206 | }
207 | }
208 | }
209 | }
210 |
--------------------------------------------------------------------------------
/src/lr0/Grammar.java:
--------------------------------------------------------------------------------
1 | package lr0;
2 |
3 | import frame.OutText;
4 |
5 | import java.io.PrintStream;
6 | import java.util.*;
7 |
8 | public class Grammar {
9 | private static final char Njump = 'ε';
10 | private static final char Point = '・';
11 | Set VN;//非终结符
12 | Set VT;//终结符集
13 | Set P;//规则集
14 | String S;//开始符
15 | Set IESet;//活前缀项目集间的边集
16 | ArrayList> IList;//项目集的数组
17 | ArrayList PList;//规则集的数组
18 | String[][] LRTable;
19 | ArrayList tableHead;
20 | Boolean isLRO = true;
21 |
22 | public Grammar(Set VN, Set VT, Set p, String s) {
23 | this.VN = VN;
24 | this.VT = VT;
25 | P = p;
26 | S = s;
27 | }
28 |
29 | public Grammar(String[] productions, String S) {
30 | this.S = "S'";//拓广文法
31 | VN = new HashSet<>();
32 | VT = new HashSet<>();
33 | P = new HashSet<>();
34 | VN.add(S);
35 | P.add(new Production(this.S + "->" + S));
36 | for (int i = 0; i < productions.length; i++) {
37 | Production p = new Production(productions[i]);
38 | VN.add(p.getLeft());
39 | if (p.isSimple()) {
40 | P.add(p);
41 | String pr = p.getRight();
42 | for (int j = 0; j < pr.length(); j++) {
43 | VT.add(String.valueOf(pr.charAt(j)));
44 | }
45 | } else {
46 | for (Production sp : p.toSimple()) {
47 | P.add(sp);
48 | String spr = sp.getRight();
49 | for (int j = 0; j < spr.length(); j++) {
50 | VT.add(String.valueOf(spr.charAt(j)));
51 | }
52 | }
53 | }
54 | }
55 | VT.removeAll(VN);
56 | VT.remove(String.valueOf(Njump));
57 |
58 | Set I0 = new HashSet<>();//活前缀项目集的开始集
59 | I0.add(new Production(this.S + "->" + Point + S));
60 | calculationCLOSURE(I0);
61 | IList = new ArrayList<>();
62 | IList.add(I0);
63 | calculationDFA();
64 | if (!(isLRO = createLRTable())) {
65 | System.out.println("NO LR(0)!");
66 | }
67 |
68 | }
69 |
70 | //对项目集I进行闭包运算
71 | private void calculationCLOSURE(Set I) {
72 | Set nV = new HashSet<>();//点后面的非终结符
73 | int ISize;
74 | do {
75 | ISize = I.size();
76 | for (Production i : I) {
77 | String iRight = i.right;
78 | int Di = iRight.indexOf(Point);
79 | //截取 . 后面的非终结符
80 | if (Di + 1 < iRight.length()) {
81 | String inV = iRight.substring(Di + 1, Di + 2);
82 | if (VN.contains(inV)) {
83 | nV.add(inV);
84 | }
85 | }
86 | }
87 | for (Production ip : P) {
88 | if (nV.contains(ip.left)) {
89 | I.add(ip.insertDian());//加点
90 | }
91 | }
92 | } while (ISize != I.size());
93 | }
94 |
95 | //求活前缀DFA,得到边集、项目集
96 | private void calculationDFA() {
97 | IESet = new HashSet<>();//存放DFA的边
98 | Queue> queue = new LinkedList<>();
99 | queue.add(IList.get(0));
100 | Set nI;
101 | Map> nIMap;
102 |
103 | while (!queue.isEmpty()) {
104 | Set iI = queue.poll();
105 | nIMap = new HashMap<>();
106 | //求转换
107 | for (Production i : iI) {
108 | String iRight = i.right;
109 | int Di = iRight.indexOf(Point);
110 | if (Di + 1 < iRight.length()) {
111 | String iV = iRight.substring(Di + 1, Di + 2);
112 | nI = nIMap.get(iV);
113 | if (nI == null) {
114 | nI = new HashSet<>();
115 | nI.add(i.moveDian());//移点
116 | nIMap.put(iV, nI);
117 | } else {
118 | nI.add(i.moveDian());
119 | }
120 | }
121 | }
122 | //求闭包
123 | int iList = IList.indexOf(iI);
124 | for (String v : nIMap.keySet()) {
125 | nI = nIMap.get(v);
126 | calculationCLOSURE(nI);
127 | int jList = IList.indexOf(nI);
128 | if (jList == -1) {
129 | queue.add(nI);
130 | IList.add(nI);
131 | jList = IList.size() - 1;
132 | }
133 | //加入边集
134 | IESet.add(new IE(iList, v, jList));
135 | }
136 | //清空
137 | nIMap.clear();
138 | }
139 | }
140 | public String format(int len,String str){
141 | if(str.length() == len)return str;
142 | String temp = str;
143 | for (int i = str.length(); i <= len; i++) {
144 | temp+=" ";
145 | }
146 | return temp;
147 | }
148 |
149 | public void out(OutText outText) {
150 | outText.append("非终结符集 VN:{ ");
151 | for (Object iVN : VN) {
152 | outText.append(iVN.toString()+" ");
153 | }
154 | outText.append("}\r\n");
155 | outText.append("终结符集 VT:{ ");
156 |
157 | for (Object iVT : VT) {
158 | outText.append(iVT.toString()+" ");
159 |
160 | }
161 | outText.append("}\r\n");
162 | outText.append("产生式集 P:{\r\n");
163 | for (Object ip : PList) {
164 | outText.append(ip.toString()+" \r\n");
165 | }
166 | outText.append("}\r\n");
167 |
168 | outText.append("开始符 S: "+S+"\r\n");
169 | outText.append("DFA:\r\n\n"+IESet);
170 | PrintStream ps = null;
171 | ps = new PrintStream(System.out) {
172 | public void println(String x) {
173 | outText.append(x + "\r\n");
174 | }
175 | public PrintStream printf(String format, Object ... args){
176 | outText.append(String.format(format,args));
177 | return null;
178 | }
179 | public void print(String s) {
180 | outText.append(s);
181 | }
182 | public void println(int x){
183 | outText.append(x+"\r\n");
184 | }
185 | };
186 | System.setOut(ps);
187 | outText.append("\r\n\n\n");
188 |
189 | outText.append("LR0表:");
190 | outText.append("\r\n");
191 | outText.append(format(80, " "));
192 | for (String i : tableHead) {
193 | outText.append(format(10, i));
194 | }
195 | outText.append("\r\n");
196 |
197 | for (int i = 0; i < LRTable.length; i++) {
198 | outText.append(format(80, "S" + i + IList.get(i).toString()));
199 | outText.append("\r\n");
200 | outText.append(format(80, " "));
201 |
202 | for (int j = 0; j < LRTable[0].length; j++) {
203 | if (LRTable[i][j] != null) {
204 | outText.append(format(10, LRTable[i][j]));
205 | }
206 |
207 | else
208 | {
209 | outText.append(format(10, " "));
210 |
211 | }
212 | }
213 | outText.append("\r\n");
214 | //System.out.print("\n");
215 | }
216 | }
217 |
218 | //构造LR0分析表
219 | public boolean createLRTable() {
220 | PList = new ArrayList<>();
221 | PList.addAll(P);
222 | tableHead = new ArrayList<>();
223 | tableHead.addAll(VT);
224 | tableHead.add("#");
225 | tableHead.addAll(VN);
226 | tableHead.remove(S);
227 |
228 |
229 | // ArrayList> IList;//项目集的数组
230 | LRTable = new String[IList.size()][tableHead.size()];
231 | //构造GO表
232 | int go[][] = new int[IList.size()][tableHead.size()];
233 | for (IE ie : IESet) {
234 | int ivalue = tableHead.indexOf(ie.getValue());
235 | int k = ie.getOrgin();
236 | if (go[k][ivalue] == 0)
237 | go[k][ivalue] = ie.getAim();
238 | else
239 | return false; //说明一个表内有重复值 也就是说识别一个字符到达两个状态
240 | }
241 | //填Action表
242 | for (int k = 0; k < IList.size(); k++) {
243 | for (Production ip : IList.get(k)) {
244 | String right = ip.getRight();
245 | int iD = right.indexOf(Point);
246 | if (iD < right.length() - 1) { //A->α・aβ GO(Ik,a)=Ij
247 | String a = right.substring(iD + 1, iD + 2);
248 | if (VT.contains(a)) {//a为终结符
249 | int ia = tableHead.indexOf(a);
250 | if (LRTable[k][ia] == null)
251 | LRTable[k][ia] = "S" + go[k][ia];
252 | else
253 | return false;//有重复值 出错
254 | }
255 | } else {//A->α・
256 | if (ip.getLeft().equals(S)) {
257 | if (LRTable[k][VT.size()] == null)
258 | LRTable[k][VT.size()] = "acc";
259 | else
260 | return false;
261 | } else {
262 | for (int ia = 0; ia < VT.size() + 1; ia++) {
263 |
264 | if (LRTable[k][ia] == null)
265 | LRTable[k][ia] = "r" + PList.indexOf(ip.deleteDian());
266 | else
267 | return false;
268 | }
269 | }
270 | }
271 | }
272 | }
273 |
274 |
275 | //合并表
276 | for (int j = VT.size(); j < tableHead.size(); j++) {
277 | for (int k = 0; k < IList.size(); k++) {
278 | if (go[k][j] != 0) {
279 | if (LRTable[k][j] == null)
280 | LRTable[k][j] = "" + go[k][j];
281 | else
282 | return false;
283 | }
284 | }
285 | }
286 | return true;
287 | }
288 |
289 | //判断st是否符合文法,LR0分析器
290 | public boolean contains(String st) throws Exception {
291 | if (isLRO) {
292 | st += "#";
293 | Stack stateStack = new Stack<>();
294 | Stack signStack = new Stack<>();
295 | stateStack.push(0);
296 | signStack.push("#");
297 | Production p;
298 | int VTL = VT.size();
299 | int bz = 0;//步骤数
300 | for (int i = 0; i < st.length(); i++) {
301 | if (true) {//显示分析过程
302 | System.out.println(++bz);
303 | System.out.print("状态栈:");
304 | System.out.println(stateStack);
305 | System.out.println(" ");
306 | System.out.print("符号栈:");
307 | System.out.println(signStack);
308 | System.out.println(" ");
309 | System.out.print("输入串:");
310 | System.out.println(st.substring(i));
311 | System.out.println(" ");
312 |
313 | }
314 | String a = st.substring(i, i + 1);
315 | int ai = tableHead.indexOf(a);
316 | String ag = LRTable[stateStack.peek()][ai];
317 | if (ag == null) return false;
318 | else if (ag.equals("acc")) {
319 | return true;
320 | }
321 | if (ai < VT.size() + 1) {//action
322 | int nub = Integer.valueOf(ag.substring(1));
323 | if (ag.charAt(0) == 'S') {
324 | stateStack.push(nub);
325 | signStack.push(a);
326 | } else {//r
327 | p = PList.get(nub);
328 | int k = p.getRight().length();
329 | if (!p.getRight().equals(String.valueOf(Njump))) {//排除归约为 A->ε
330 | while (k-- > 0) {
331 | stateStack.pop();
332 | signStack.pop();
333 | }
334 | }
335 | //goto
336 | String go = LRTable[stateStack.peek()][tableHead.indexOf(p.getLeft())];
337 | if (go == null) return false;
338 | stateStack.push(Integer.valueOf(go));
339 | signStack.push(p.getLeft());
340 | i--;
341 | }
342 | }
343 | }
344 | return false;
345 | }
346 | throw new Exception("无法判断:该文法不是LR(0)文法!");
347 |
348 | }
349 | }
350 |
--------------------------------------------------------------------------------
/src/compile/Parser.java:
--------------------------------------------------------------------------------
1 | package compile;
2 |
3 | import frame.OutText;
4 | import frame.ReadText;
5 | import java.awt.*;
6 | import java.io.BufferedReader;
7 | import java.io.File;
8 | import java.io.FileReader;
9 | import java.security.PublicKey;
10 | import java.util.*;
11 |
12 | /**
13 | * @description 这是词法分析的具体实现
14 | */
15 | @SuppressWarnings("all")
16 | public class Parser extends MainComplier{
17 | //语法分析的规则
18 | public static final String PATH = "./grammar2";// 文法
19 | private static String START; // 开始符号
20 | private static HashSet VN, VT; // 非终结符号集、终结符号集
21 | private static HashMap>> MAP;// key:产生式左边 value:产生式右边(含多条)
22 | private static HashMap oneLeftFirst;// "|" 分开的单条产生式对应的FIRST集合,用于构建预测分析表
23 | private static HashMap> FIRST, FOLLOW; // FIRST、FOLLOW集合
24 | private static String[][] FORM; // 存放预测分析表的数组,用于输出
25 | private static HashMap preMap;// 存放预测分析表的map,用于快速查找
26 | private int choice;
27 |
28 | //将父类的readText, outText继承过来
29 | public Parser(ReadText readText, OutText outText, int choice) throws HeadlessException {
30 | super(readText, outText);
31 | this.choice=choice;
32 | }
33 |
34 | //程序入口
35 | public void Main() {
36 | init(); // 初始化变量
37 | identifyVnVt(readFile(new File(PATH)));// 符号分类,并以key-value形式存于MAP中
38 | reformMap();// 消除左递归和提取左公因子
39 | findFirst(); // 求FIRST集合
40 | findFollow(); // 求FOLLOW集合
41 | if (isLL1()) {
42 | preForm(); // 构建预测分析表
43 | printAutoPre(readText.getText());
44 | }
45 | }
46 | // 从文件读文法
47 | public ArrayList readFile(File file) {
48 | BufferedReader br = null;
49 | outText.append("从文件读入的文法为:"+"\r\n");
50 | ArrayList result = new ArrayList<>();
51 | try {
52 | String path = System.getProperty("user.dir")+File.separator+"grammer"+File.separator;
53 | if (choice == 1) {
54 | br = new BufferedReader(new FileReader(path+"a1.txt"));
55 | } else if (choice == 2){
56 | br = new BufferedReader(new FileReader(path+"a2.txt"));
57 | } else if (choice == 3){
58 | br = new BufferedReader(new FileReader(path+"a3.txt"));
59 | } else if (choice == 4){
60 | br = new BufferedReader(new FileReader(path+"a4.txt"));
61 | }
62 | String s = null;
63 | while ((s = br.readLine()) != null) {
64 | outText.append("\t" + s+"\r\n");
65 | result.add(s.trim());
66 | }
67 | br.close();
68 | } catch (Exception e) {
69 | e.printStackTrace();
70 | }
71 | return result;
72 | }
73 | // 变量初始化
74 | private static void init() {
75 | VN = new HashSet<>();
76 | VT = new HashSet<>();
77 | MAP = new HashMap<>();
78 | FIRST = new HashMap<>();
79 | FOLLOW = new HashMap<>();
80 | oneLeftFirst = new HashMap<>();
81 | preMap = new HashMap<>();
82 | }
83 | // 符号分类
84 | private void identifyVnVt(ArrayList list) {
85 | START = list.get(0).charAt(0) + "";// 存放开始符号
86 |
87 | for (int i = 0; i < list.size(); i++) {
88 | String oneline = list.get(i);
89 | String[] vnvt = oneline.split("→");// 用定义符号分割
90 | String left = vnvt[0].trim(); // 文法的左边
91 | VN.add(left);
92 |
93 | // 文法右边
94 | ArrayList> mapValue = new ArrayList<>();
95 | ArrayList right = new ArrayList<>();
96 |
97 | for (int j = 0; j < vnvt[1].length(); j++) { // 用 “|”分割右边
98 | if (vnvt[1].charAt(j) == '|') {
99 | VT.addAll(right);
100 | mapValue.add(right);
101 | // right.clear();// 清空之后,依然是同一个地址,需要重新new对象
102 | right = null;
103 | right = new ArrayList<>();
104 | continue;
105 | }
106 | // 如果产生式某字符的左边含有中文或英文的单引号,则视为同一个字符
107 | if (j + 1 < vnvt[1].length() && (vnvt[1].charAt(j + 1) == '\'' || vnvt[1].charAt(j + 1) == '’')) {
108 | right.add(vnvt[1].charAt(j) + "" + vnvt[1].charAt(j + 1));
109 | j++;
110 | } else {
111 | right.add(vnvt[1].charAt(j) + "");
112 | }
113 | }
114 | VT.addAll(right);
115 | mapValue.add(right);
116 |
117 | MAP.put(left, mapValue);
118 | }
119 | VT.removeAll(VN); // 从终结字符集中移除非终结符
120 | // 打印Vn、Vt
121 | outText.append("\nVn集合:\r\n\t{" + String.join("、", VN.toArray(new String[VN.size()])) + "}"+"\r\n");
122 | outText.append("Vt集合:\n\t{" + String.join("、", VT.toArray(new String[VT.size()])) + "}"+"\r\n");
123 |
124 | }
125 | // 消除直接左递归
126 | private void reformMap() {
127 | boolean isReForm = false;// MAP是否被修改
128 | Set keys = new HashSet<>();
129 | keys.addAll(MAP.keySet());
130 | Iterator it = keys.iterator();
131 | ArrayList nullSign = new ArrayList<>();
132 | nullSign.add("ε");
133 | while (it.hasNext()) {
134 | String left = it.next();
135 | boolean flag = false;// 是否有左递归
136 | ArrayList> rightList = MAP.get(left);
137 | ArrayList oldRightCell = new ArrayList<>(); // 旧产生的右边
138 | ArrayList> newLeftNew = new ArrayList<>();// 存放新的左边的新的右边
139 |
140 | // 消除直接左递归
141 | for (int i = 0; i < rightList.size(); i++) {
142 | ArrayList newRightCell = new ArrayList<>(); // 新产生式的右边
143 | if (rightList.get(i).get(0).equals(left)) {
144 | //P‘的右部分
145 | for (int j = 1; j < rightList.get(i).size(); j++) {
146 | newRightCell.add(rightList.get(i).get(j));
147 | }
148 | flag = true;
149 | newRightCell.add(left + "\'");
150 | newLeftNew.add(newRightCell);
151 | } else {
152 | //P的右部分
153 | for (int j = 0; j < rightList.get(i).size(); j++) {
154 | oldRightCell.add(rightList.get(i).get(j));
155 | }
156 | oldRightCell.add(left + "\'");
157 | }
158 | }
159 | // 如果有左递归,则更新MAP
160 | if (flag) {
161 | isReForm = true;
162 | newLeftNew.add(nullSign);
163 | MAP.put(left + "\'", newLeftNew);
164 | VN.add(left + "\'"); // 加入新的VN
165 | VT.add("ε"); // 加入ε到VT
166 | ArrayList> newLeftOld = new ArrayList<>();// 存放原先,但是产生新的右边
167 | newLeftOld.add(oldRightCell);
168 | MAP.put(left, newLeftOld);
169 | }
170 | }
171 | // 如果文法被修改,则输出修改后的文法
172 | if (isReForm) {
173 | outText.append("消除文法的左递归:"+"\r\n");
174 | Set kSet = new HashSet<>(MAP.keySet());
175 | Iterator itk = kSet.iterator();
176 | while (itk.hasNext()) {
177 | String k = itk.next();
178 | ArrayList> leftList = MAP.get(k);
179 | outText.append("\t" + k + "→");
180 | for (int i = 0; i < leftList.size(); i++) {
181 | outText.append(String.join("", leftList.get(i).toArray(new String[leftList.get(i).size()])));
182 | if (i + 1 < leftList.size()) {
183 | outText.append("|");
184 | }
185 | }
186 | outText.append("\r\n");
187 | }
188 | }
189 | }
190 | // 求每个非终结符号的FIRST集合 和 分解单个产生式的FIRST集合
191 | private void findFirst() {
192 | outText.append("\nFIRST集合:"+"\r\n");
193 | Iterator it = VN.iterator();
194 | while (it.hasNext()) {
195 | HashSet firstCell = new HashSet<>();// 存放单个非终结符号的FIRST
196 | String key = it.next();
197 | ArrayList> list = MAP.get(key);
198 | // System.out.println(key+":");
199 | // 遍历单个产生式的左边
200 | for (int i = 0; i < list.size(); i++) {
201 | ArrayList listCell = list.get(i);// listCell为“|”分割出来
202 | HashSet firstCellOne = new HashSet<>();// 产生式左边用“ | ”分割的单个式子的First(弃用)
203 | String oneLeft = String.join("", listCell.toArray(new String[listCell.size()]));
204 | // System.out.println("oneLeft: "+oneLeft);
205 | if (VT.contains(listCell.get(0))) {
206 | firstCell.add(listCell.get(0));
207 | firstCellOne.add(listCell.get(0));
208 | oneLeftFirst.put(key + "$" + listCell.get(0), key + "→" + oneLeft);
209 | } else {
210 | boolean[] isVn = new boolean[listCell.size()];// 标记是否有定义为空,如果有则检查下一个字符
211 | isVn[0] = true;// 第一个为非终结符号
212 | int p = 0;
213 | while (isVn[p]) {
214 | // System.out.println(p+" "+listCell.size());
215 | if (VT.contains(listCell.get(p))) {
216 | firstCell.add(listCell.get(p));
217 | firstCellOne.add(listCell.get(p));
218 | oneLeftFirst.put(key + "$" + listCell.get(p), key + "→" + oneLeft);
219 | break;
220 | }
221 | String vnGo = listCell.get(p);//
222 | Stack stack = new Stack<>();
223 | stack.push(vnGo);
224 | //遍历非终结符的产生式右端
225 | while (!stack.isEmpty()) {
226 | ArrayList> listGo = MAP.get(stack.pop());
227 | for (int k = 0; k < listGo.size(); k++) {
228 | ArrayList listGoCell = listGo.get(k);
229 | if (VT.contains(listGoCell.get(0))) { // 如果第一个字符是终结符号
230 | if ("ε".equals(listGoCell.get(0))) {
231 | if (!key.equals(START)) { // 开始符号不能推出空
232 | firstCell.add(listGoCell.get(0));
233 | firstCellOne.add(listGoCell.get(0));
234 | oneLeftFirst.put(key + "$" + listGoCell.get(0), key + "→" + oneLeft);
235 | }
236 | if (p + 1 < isVn.length) {// 如果为空,可以查询下一个字符
237 | isVn[p + 1] = true;
238 | }
239 | } else { // 非空的终结符号加入对应的FIRST集合
240 | firstCell.add(listGoCell.get(0));
241 | firstCellOne.add(listGoCell.get(0));
242 | oneLeftFirst.put(key + "$" + listGoCell.get(0), key + "→" + oneLeft);
243 | }
244 | } else {// 不是终结符号,入栈
245 | stack.push(listGoCell.get(0));
246 | }
247 | }
248 | }
249 | p++;
250 | if (p > isVn.length - 1) {
251 | break;
252 | }
253 | }
254 | }
255 | FIRST.put(key + "→" + oneLeft, firstCellOne);
256 | }
257 | FIRST.put(key, firstCell);
258 | // 输出key的FIRST集合
259 | outText.append(
260 | "\tFIRST(" + key + ")={" + String.join("、", firstCell.toArray(new String[firstCell.size()])) + "}"+"\r\n");
261 | }
262 | }
263 | private void MyfindFollow(){
264 | outText.append("\nFOLLOW集合:"+"\r\n");
265 | HashMap> keyFollow = new HashMap<>();
266 | HashSetStartFollow = new HashSet<>();
267 | StartFollow.add("#");
268 | keyFollow.put(START,StartFollow);
269 | boolean isChange = true;
270 | while(isChange){
271 | isChange = false;
272 | Iterator it = VN.iterator();
273 | while (it.hasNext()){
274 | String key = it.next();
275 | ArrayList>lists = new ArrayList<>();
276 | lists = MAP.get(key);
277 | for (int i = 0; i < lists.size(); i++) {
278 | ArrayList listCell = lists.get(i);
279 | for (int j = 0; j < listCell.size(); j++) {
280 | String v = listCell.get(j);
281 | if(VN.contains(v)){
282 | if(j+1 >= listCell.size()){
283 | continue;
284 | }
285 | HashSetfollow = new HashSet<>();
286 | if(keyFollow.containsKey(v)){
287 | follow = keyFollow.get(v);
288 | }
289 | int followsize = follow.size();
290 | if(VT.contains(listCell.get(j+1))){
291 | follow.add(listCell.get(j+1));
292 | }
293 | else{
294 | if(FIRST.get(listCell.get(j+1)).contains("ε") == false){
295 | follow.addAll(FIRST.get(listCell.get(j+1)));
296 | }
297 | else{
298 | Set set = FIRST.get(listCell.get(j+1));
299 | set.remove("ε");
300 | follow.addAll(set);
301 | if(keyFollow.containsKey(listCell.get(j+1))){
302 | follow.addAll(keyFollow.get(listCell.get(j+1)));
303 | }
304 | }
305 | }
306 | if(followsize!=follow.size()){
307 | isChange = true;
308 | keyFollow.put(v,follow);
309 | }
310 | }
311 | }
312 | }
313 |
314 | }
315 | }
316 | Iterator itF = keyFollow.keySet().iterator();
317 | while (itF.hasNext()) {
318 | String key = itF.next();
319 | HashSet f = keyFollow.get(key);
320 | outText.append("\tFOLLOW(" + key + ")={" + String.join("、", f.toArray(new String[f.size()])) + "}"+"\r\n");
321 | }
322 |
323 |
324 | }
325 | // 求每个非终结符号的FOLLOW集合
326 | private void findFollow() {
327 | outText.append("\nFOLLOW集合:"+"\r\n");
328 | Iterator it = VN.iterator();
329 | HashMap> keyFollow = new HashMap<>();
330 |
331 | ArrayList> vn_VnList = new ArrayList<>();// 用于存放/A->...B 或者 A->...Bε的组合
332 |
333 | HashSet vn_VnListLeft = new HashSet<>();// 存放vn_VnList的左边和右边
334 | HashSet vn_VnListRight = new HashSet<>();
335 | // 开始符号加入#
336 | keyFollow.put(START, new HashSet() {
337 | private static final long serialVersionUID = 1L;
338 | {
339 | add(new String("#"));
340 | }
341 | });
342 |
343 | while (it.hasNext()) {
344 | String key = it.next();
345 | ArrayList> list = MAP.get(key);
346 | ArrayList listCell;
347 |
348 | // 先把每个VN作为keyFollow的key,之后在查找添加其FOLLOW元素
349 | if (!keyFollow.containsKey(key)) {
350 | keyFollow.put(key, new HashSet<>());
351 | }
352 | keyFollow.toString();
353 |
354 | for (int i = 0; i < list.size(); i++) {
355 | listCell = list.get(i);
356 |
357 | // (1)直接找非终结符号后面跟着终结符号
358 | for (int j = 1; j < listCell.size(); j++) {
359 | HashSet set = new HashSet<>();
360 | if (VT.contains(listCell.get(j))) {
361 | // System.out.println(listCell.get(j - 1) + ":" + listCell.get(j));
362 | set.add(listCell.get(j));
363 | if (keyFollow.containsKey(listCell.get(j - 1))) {
364 | set.addAll(keyFollow.get(listCell.get(j - 1)));
365 | }
366 | keyFollow.put(listCell.get(j - 1), set);
367 | }
368 | }
369 | // (2)找...VnVn...组合
370 | for (int j = 0; j < listCell.size() - 1; j++) {
371 | HashSet set = new HashSet<>();
372 | if (VN.contains(listCell.get(j)) && VN.contains(listCell.get(j + 1))) {
373 | set.addAll(FIRST.get(listCell.get(j + 1)));
374 | set.remove("ε");
375 |
376 | if (keyFollow.containsKey(listCell.get(j))) {
377 | set.addAll(keyFollow.get(listCell.get(j)));
378 | }
379 | keyFollow.put(listCell.get(j), set);
380 | }
381 | }
382 |
383 | // (3)A->...B 或者 A->...Bε(可以有n个ε)的组合存起来
384 | for (int j = 0; j < listCell.size(); j++) {
385 | HashMap vn_Vn;
386 | if (VN.contains(listCell.get(j)) && !listCell.get(j).equals(key)) {// 是VN且A不等于B
387 | boolean isAllNull = false;// 标记VN后是否为空
388 | if (j + 1 < listCell.size()) {// 即A->...Bε(可以有n个ε)
389 | for (int k = j + 1; k < listCell.size(); k++) {
390 | if ((FIRST.containsKey(listCell.get(k)) ? FIRST.get(listCell.get(k)).contains("ε")
391 | : false)) {// 如果其后面的都是VN且其FIRST中包含ε
392 | isAllNull = true;
393 | } else {
394 | isAllNull = false;
395 | break;
396 | }
397 | }
398 | }
399 | // 如果是最后一个为VN,即A->...B
400 | if (j == listCell.size() - 1) {
401 | isAllNull = true;
402 | }
403 | if (isAllNull) {
404 | vn_VnListLeft.add(key);
405 | vn_VnListRight.add(listCell.get(j));
406 |
407 | // 往vn_VnList中添加,分存在和不存在两种情况
408 | boolean isHaveAdd = false;
409 | for (int x = 0; x < vn_VnList.size(); x++) {
410 | HashMap vn_VnListCell = vn_VnList.get(x);
411 | if (!vn_VnListCell.containsKey(key)) {
412 | vn_VnListCell.put(key, listCell.get(j));
413 | vn_VnList.set(x, vn_VnListCell);
414 | isHaveAdd = true;
415 | break;
416 | } else {
417 | // 去重
418 | if (vn_VnListCell.get(key).equals(listCell.get(j))) {
419 | isHaveAdd = true;
420 | break;
421 | }
422 | continue;
423 | }
424 | }
425 | if (!isHaveAdd) {// 如果没有添加,表示是新的组合
426 | vn_Vn = new HashMap<>();
427 | vn_Vn.put(key, listCell.get(j));
428 | vn_VnList.add(vn_Vn);
429 | }
430 | }
431 | }
432 | }
433 | }
434 | }
435 |
436 | keyFollow.toString();
437 |
438 | // (4)vn_VnListLeft减去vn_VnListRight,剩下的就是入口产生式,
439 | vn_VnListLeft.removeAll(vn_VnListRight);
440 | Queue keyQueue = new LinkedList<>();// 用栈或者队列都行
441 | Iterator itVnVn = vn_VnListLeft.iterator();
442 | while (itVnVn.hasNext()) {
443 | keyQueue.add(itVnVn.next());
444 | }
445 | while (!keyQueue.isEmpty()) {
446 | String keyLeft = keyQueue.poll();
447 | for (int t = 0; t < vn_VnList.size(); t++) {
448 | HashMap vn_VnListCell = vn_VnList.get(t);
449 | if (vn_VnListCell.containsKey(keyLeft)) {
450 | HashSet set = new HashSet<>();
451 | // 原来的FOLLOW加上左边的FOLLOW
452 | if (keyFollow.containsKey(keyLeft)) {
453 | set.addAll(keyFollow.get(keyLeft));
454 | }
455 | if (keyFollow.containsKey(vn_VnListCell.get(keyLeft))) {
456 | set.addAll(keyFollow.get(vn_VnListCell.get(keyLeft)));
457 | }
458 | keyFollow.put(vn_VnListCell.get(keyLeft), set);
459 | keyQueue.add(vn_VnListCell.get(keyLeft));
460 |
461 | // 移除已处理的组合
462 | vn_VnListCell.remove(keyLeft);
463 | vn_VnList.set(t, vn_VnListCell);
464 | }
465 | }
466 | }
467 |
468 | // 此时keyFollow为完整的FOLLOW集
469 | FOLLOW = keyFollow;
470 | // 打印FOLLOW集合
471 | Iterator itF = keyFollow.keySet().iterator();
472 | while (itF.hasNext()) {
473 | String key = itF.next();
474 | HashSet f = keyFollow.get(key);
475 | outText.append("\tFOLLOW(" + key + ")={" + String.join("、", f.toArray(new String[f.size()])) + "}"+"\r\n");
476 | }
477 | }
478 | // 判断是否是LL(1)文法
479 | private boolean isLL1() {
480 | outText.append("\n正在判断是否是LL(1)文法...."+"\r\n");
481 | boolean flag = true;// 标记是否是LL(1)文法
482 | Iterator it = VN.iterator();
483 | while (it.hasNext()) {
484 | String key = it.next();
485 | ArrayList> list = MAP.get(key);// 单条产生式
486 | if (list.size() > 1) { // 如果单条产生式的左边包含两个式子以上,则进行判断
487 | for (int i = 0; i < list.size(); i++) {
488 | String aLeft = String.join("", list.get(i).toArray(new String[list.get(i).size()]));
489 | for (int j = i + 1; j < list.size(); j++) {
490 | String bLeft = String.join("", list.get(j).toArray(new String[list.get(j).size()]));
491 | if ("ε".equals(aLeft) || "ε".equals(bLeft)) { // (1)若b=ε,则要FIRST(A)∩FOLLOW(A)=φ
492 | HashSet retainSet = new HashSet<>();
493 | // retainSet=FIRST.get(key);//需要要深拷贝,否则修改retainSet时FIRST同样会被修改
494 | retainSet.addAll(FIRST.get(key));
495 | if (FOLLOW.get(key) != null) {
496 | retainSet.retainAll(FOLLOW.get(key));
497 | }
498 | if (!retainSet.isEmpty()) {
499 | flag = false;// 不是LL(1)文法,输出FIRST(a)FOLLOW(a)的交集
500 | outText.append("\tFIRST(" + key + ") ∩ FOLLOW(" + key + ") = {"
501 | + String.join("、", retainSet.toArray(new String[retainSet.size()])) + "}\r\n");
502 | break;
503 | } else {
504 | outText.append("\tFIRST(" + key + ") ∩ FOLLOW(" + key + ") = φ"+"\r\n");
505 | }
506 | } else { // (2)b!=ε若,则要FIRST(a)∩FIRST(b)= Ф
507 | HashSet retainSet = new HashSet<>();
508 | retainSet.addAll(FIRST.get(key + "→" + aLeft));
509 | retainSet.retainAll(FIRST.get(key + "→" + bLeft));
510 | if (!retainSet.isEmpty()) {
511 | flag = false;// 不是LL(1)文法,输出FIRST(a)FIRST(b)的交集
512 | outText.append("\tFIRST(" + aLeft + ") ∩ FIRST(" + bLeft + ") = {"
513 | + String.join("、", retainSet.toArray(new String[retainSet.size()])) + "}"+"\r\n");
514 | break;
515 | } else {
516 | outText.append("\tFIRST(" + aLeft + ") ∩ FIRST(" + bLeft + ") = φ"+"\r\n");
517 | }
518 | }
519 | }
520 | }
521 | }
522 | }
523 | if(flag) {
524 | outText.append("\t是LL(1)文法,继续分析!"+"\r\n");
525 | }else {
526 | outText.append("\t不是LL(1)文法,退出分析!"+"\r\n");
527 | }
528 | return flag;
529 | }
530 | // 构建预测分析表FORM
531 | private void preForm() {
532 | HashSet set = new HashSet<>();
533 | set.addAll(VT);
534 | set.remove("ε");
535 | FORM = new String[VN.size() + 1][set.size() + 2];
536 | Iterator itVn = VN.iterator();
537 | Iterator itVt = set.iterator();
538 |
539 | // (1)初始化FORM,并根据oneLeftFirst(VN$VT,产生式)填表
540 | for (int i = 0; i < FORM.length; i++){
541 | for (int j = 0; j < FORM[0].length; j++) {
542 | if (i == 0 && j > 0) {// 第一行为Vt
543 | if (itVt.hasNext()) {
544 | FORM[i][j] = itVt.next();
545 | }
546 | if (j == FORM[0].length - 1) {// 最后一列加入#
547 | FORM[i][j] = "#";
548 | }
549 | }
550 | if (j == 0 && i > 0) {// 第一列为Vn
551 | if (itVn.hasNext()) {
552 | FORM[i][j] = itVn.next();
553 | }
554 | }
555 | if (i > 0 && j > 0) {// 其他情况先根据oneLeftFirst填表
556 | String oneLeftKey = FORM[i][0] + "$" + FORM[0][j];// 作为key查找其First集合
557 | FORM[i][j] = oneLeftFirst.get(oneLeftKey);
558 | }
559 | }
560 | }
561 |
562 | // (2)如果有推出了ε,则根据FOLLOW填表
563 | for (int i = 1; i < FORM.length; i++) {
564 | String oneLeftKey = FORM[i][0] + "$ε";
565 | if (oneLeftFirst.containsKey(oneLeftKey)) {
566 | HashSet followCell = FOLLOW.get(FORM[i][0]);
567 | Iterator it = followCell.iterator();
568 | while (it.hasNext()) {
569 | String vt = it.next();
570 | for (int j = 1; j < FORM.length; j++) {
571 | for (int k = 1; k < FORM[0].length; k++) {
572 | if (FORM[j][0].equals(FORM[i][0]) && FORM[0][k].equals(vt)) {
573 | FORM[j][k] = oneLeftFirst.get(oneLeftKey);//Vn->ε
574 | }
575 | }
576 | }
577 | }
578 | }
579 | }
580 |
581 | // (3)打印预测表,并存于Map的数据结构中用于快速查找
582 | outText.append("\n该文法的预测分析表为:"+"\r\n");
583 | for (int i = 0; i < FORM.length; i++) {
584 | for (int j = 0; j < FORM[0].length; j++) {
585 | if (FORM[i][j] == null) {
586 | outText.append(" " + "\t");
587 | }
588 | else {
589 | outText.append(FORM[i][j] + "\t");
590 | if (i > 0 && j > 0) {
591 | String[] tmp = FORM[i][j].split("→");
592 | preMap.put(FORM[i][0] + "" + FORM[0][j], tmp[1]);
593 | }
594 | }
595 | }
596 | outText.append("\r\n");
597 | }
598 | outText.append("\r\n");
599 | }
600 | // 输入的单词串分析推导过程
601 | public void printAutoPre(String str) {
602 | outText.append(str + "的分析过程:"+"\r\n");
603 | Queue queue = new LinkedList<>();// 句子拆分存于队列
604 | for (int i = 0; i < str.length(); i++) {
605 | String t = str.charAt(i) + "";
606 | if (i + 1 < str.length() && (str.charAt(i + 1) == '\'' || str.charAt(i + 1) == '’')) {
607 | t += str.charAt(i + 1);
608 | i++;
609 | }
610 | queue.offer(t);
611 | }
612 | queue.offer("#");// "#"结束
613 | // 分析栈
614 | Stack stack = new Stack<>();
615 | stack.push("#");// "#"开始
616 | stack.push(START);// 初态为开始符号
617 | boolean isSuccess = false;
618 | int step = 1;
619 | while (!stack.isEmpty()) {
620 | String left = stack.peek();
621 | String right = queue.peek();
622 | // (1)分析成功
623 | if (left.equals(right) && "#".equals(right)) {
624 | isSuccess = true;
625 | outText.append((step++) + "\t#\t#\t" + "分析成功"+"\r\n");
626 | break;
627 | }
628 | // (2)匹配栈顶和当前符号,均为终结符号,消去
629 | if (left.equals(right)) {
630 | String stackStr = String.join("", stack.toArray(new String[stack.size()]));
631 | String queueStr = String.join("", queue.toArray(new String[queue.size()]));
632 | outText.append((step++) + "\t" + stackStr + "\t" + queueStr + "\t匹配成功" + left + "\r\n");
633 | stack.pop();
634 | queue.poll();
635 | continue;
636 | }
637 | // (3)从预测表中查询
638 | if (preMap.containsKey(left + right)) {
639 | String stackStr = String.join("", stack.toArray(new String[stack.size()]));
640 | String queueStr = String.join("", queue.toArray(new String[queue.size()]));
641 | outText.append((step++) + "\t" + stackStr + "\t" + queueStr + "\t用" + left + "→"
642 | + preMap.get(left + right) + "," + right + "逆序进栈" + "\r\n");
643 | stack.pop();
644 | String tmp = preMap.get(left + right);
645 | for (int i = tmp.length() - 1; i >= 0; i--) {// 逆序进栈
646 | String t = "";
647 | if (tmp.charAt(i) == '\'' || tmp.charAt(i) == '’') {
648 | t = tmp.charAt(i-1)+""+tmp.charAt(i);
649 | i--;
650 | }else {
651 | t=tmp.charAt(i)+"";
652 | }
653 | if (!"ε".equals(t)) {
654 | stack.push(t);
655 | }
656 | }
657 | continue;
658 | }
659 | break;// (4)其他情况失败并退出
660 | }
661 | if (!isSuccess) {
662 | outText.append((step++) + "\t#\t#\t" + "分析失败"+"\r\n");
663 | }
664 | }
665 | }
666 |
--------------------------------------------------------------------------------